Tag Archives: c

Arduino Game

At times, I have fun creating devices.  The similarity to programming amazes me and the ability to be able interact with the physical world is a lot of fun.  I took my standard game, a tank that moves side to side and shoots objects from the sky (think Space Invaders).  Here’s the shopping list.

  1. Microcontroller – Arduino Uno
  2. Display – Nokia 5110 LCD
  3. Sensor – ADXL334 Triple Axis Acelerometer
  4. Tactile Switch and misc wiring/resistors.

So for a relatively small amount of shopping, you have the ability to make an interactive game.  The wiring basically merges basic wiring for the tactile switch, standard input for triple axis acelerometer, and

Enough talk, here’s a picture:

Here’s a video of it:

And here’s the code I wrote:

#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
 
// Display
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);
 
// Setup
int pressed = false;
int times = 0;
int led = 13;
int but = 12;
int val = 0;
int count = 0;
 
// Tank size and direction
int tx = 0;
int ty = 0;
int tw = 10;
int th = 4;
int td = 0;
 
// Bullet
bool bAlive = false;
int bx = 0;
int by = 0;
int bw = 3;
int bh = 3;
 
// Accelerometer
const int powerpin = 18;
const int groundpin = 14;
const int xpin = A3;
int xMoveInit = 0;
 
void setup()
{
  Serial.begin(9600);
   
  pinMode(led, OUTPUT);
  pinMode(but, INPUT);
  pinMode(groundpin, OUTPUT);
  pinMode(powerpin, OUTPUT);
   
  digitalWrite(groundpin, LOW); 
  digitalWrite(powerpin, HIGH);
   
  display.begin();
  display.setContrast(50);
  
  tx = (display.width()/2)-(tw/2);
  ty = display.height()-10-th;
   
  xMoveInit = analogRead(xpin);
}
 
void loop()
{
  // clear
  display.clearDisplay();
  // x,y,h,w,color
   
  // movement
  if(isPressed() == true)
  {
    //display.fillRect(30,12,24,24,BLACK);
    if(bAlive == false)
    {
      bAlive = true;
      bx = tx+(tw/2);
      by = ty+bh;
    }
  }
   
  // draw
  drawGround();
  drawTank();
  drawBullet();
   
  // show
  display.display();
   
  // wait
  delay(10);
}
 
void drawTank()
{
  doMove();
   
  tx += td;
   
  if(tx+tw+1 >= display.width())
  {
    tx = display.width()-tw-1;
  }
   
  if(tx <= 0)
  {
    tx = 1;
  }
   
  display.drawRect(tx,ty,tw,th,BLACK);
}
 
void drawBullet()
{
  if(by+bh <= 0)
  {
    bAlive = false;
    return;
  }
  by -= 2;
 
  display.fillRect(bx,by,bw,bh,BLACK);
}
 
void drawGround()
{
  int lx = 0;
  int ly = display.height()-10;
  int lw = display.width();
  int lh = 10;
   
  display.fillRect(lx,ly,lw,lh, BLACK);
}
 
void doMove()
{
  int xMoveTemp = analogRead(xpin);
  int diff = xMoveInit-xMoveTemp;
   
  // DEBUG
  Serial.print("Diff: ");
  Serial.print(diff);
  Serial.println();
   
  if(diff >= 20)
  {
    if(diff >= 40)
    {
      td = -2;
      return;
    }
    td = -1;
    return;
  }
   
  if(diff <= -20)
  {
    if(diff <= -40)
    {
      td = 2;
      return;
    }
    td = 1;
    return;
  }
   
  td = 0;
}
 
bool isPressed()
{
  val = digitalRead(but);
  if(val == LOW and pressed == false) {
    return false;
  }
  return true;
}

GZip with ZLib

In an effort to use zlib in VBA, I had to first learn to use it.  I’m looking to gunzip the XFDL files to use the data as an MS  Office plugin.  In tinkering with zlib’s GZip functions, I found them to be very much like normal file handling in C.  Here’s a link to the official zlib reference manual, GZip is the tenth section.  So, to test it, I made a “micro-gunzip” which does work well.  When compiling, don’t forget to link to libz.a using gcc -o out -i in.c -lz.   Other than that, enjoy!  The basics are covered in the comments.

#include <stdio.h>
#include <zlib.h>
/* gcc filename.c -o outname -lz */

int main(int argc, char *argv[]) {
	// variables
	gzFile gFile;           // gzip file object
	FILE *pFile;            // out file object
	char *filen = argv[1];  // get the name of the file
	char buffer[100];       // buffer for reading

	// open files
	gFile = gzopen(filen, "rb");        // same as file
	pFile = fopen("example.out","wb");
	if(pFile == NULL || gFile == NULL)
		perror("Error opening file");
	else {
	    // write
		while(!gzeof(gFile)) {
			gzgets(gFile,buffer,100);   // file object first
			fputs(buffer,pFile);        // write to plain tex
		}
		// close
		fclose(pFile);
		gzclose(gFile);
	}
	return 0;
}

Fern Screensaver : Part 3

Today, I had no Mac with me to work on my screensaver in Objective-C.  As you can see in my previous post, I used my python program and wrote it in C for SDL that works on either Windows or Linux.  Now, the basic principle is the same, I just need to output that location to the correct pixel plot method to use other systems.  I thought, since I was on Windows all day, I might as well use that to make the screensaver using Windows API.

I’ve had some use of Window’s API before to make a Breakout game for my children.  It is rustic at times but works.  I decided to not mess with OpenGL today and just use Win32 API and GDI methods.  Below you will find my complete source code and a link to download this screensaver.  Once downloaded, save it in C:\WINDOWS\System32\ and it will appear on your personalization menu.

A quick note before the code, for those unfamiliar with Windows API… there’s a lot of goobly gook here that looks scary.  It’s really not that bad but here’s the meat of the project:

  • Lines 8-34 are the same variables we’ve seen before.
  • Lines 36-40 are a ‘dot()’ method I made to clean the code (slightly).
  • After Line 42:
    • WM_CREATE is called on the start of the program.
    • WM_DESTROY is called on the completion of the program.
    • WM_PAINT is used to paint to the screen.
      • Here you see the same math as before until lines 78-82.
      • At Lines 78-82, I’m using Win32 API to create a color brush and paint it with the dot method.
    • WM_TIMER is called every millisecond in this program, it keeps the loop going.
      • InvalidateRect() will force a WM_PAINT message.
  • Everything that follows is not really applicable as it just meets the demands of the Screensaver library.

If you would like to try out this screen saver, download from this link and save the file to your C:/WINDOWS/system32/ folder.  Let me know how it works for you!

#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#include <scrnsave.h>

#define TIMER 1

// VARIABLES
float mat[4][7] = {
    {0.0,0.0,0.0,0.16,0.0,0.0,0.01},
    {0.85,0.04,-0.04,0.85,0.0,1.6,0.85},
    {0.2,-0.25,0.23,0.22,0.0,1.6,0.07},
    {-0.15,0.28,0.26,0.24,0.0,0.44,0.07}
};
// constant sets
float xa = -5.5;
float xb = 6.5;
float ya = -0.5;
float yb = 10.5;
// x and y to be altered
float x = 0.0;
float y = 0.0;
// screen/image size
int imgx = 128;
int imgy = 128;
// floats for math fulction
float p = 0.0;
float x0 = 0;
float jx = 0;
float jy = 0;
// variables to control function
int i = 0;
int k = 1;
int end = imgx*imgy;
int done = 0;

void dot(HDC hdc, HBRUSH whtBr, int x, int y) {
        SelectObject(hdc, whtBr);
            Rectangle(hdc, x-2, y-2, x+1, y+1);
        DeleteObject(whtBr);
}

LRESULT WINAPI ScreenSaverProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    static HDC hdc;
    //static HGLRC hrc;
    PAINTSTRUCT ps;
    HBRUSH whtBr;
    static RECT rect;
    switch(message) {
        case WM_CREATE:
            GetClientRect(hwnd,&rect);
            imgx = rect.right;
            imgy = rect.bottom;
            int ret = SetTimer(hwnd, TIMER, 1, NULL);
            if(ret == 0)
                MessageBox(hwnd, "Could not set Timer", "ERROR", MB_OK);
            break;
        case WM_DESTROY:
            KillTimer(hwnd,TIMER);
            PostQuitMessage(0);
            break;
        case WM_PAINT:
            k++;
            p = (float) rand()/RAND_MAX;
            if(p <= mat[0][6])
                i = 0;
            else if(p <= (mat[0][6]+mat[1][6]))
                i = 1;
            else if(p <= (mat[0][6]+mat[1][6]+mat[2][6]))
                i = 2;
            else
                i = 3;
            x0 = ((x*mat[i][0])+(y*mat[i][1])+mat[i][4]);
            y = (x*mat[i][2]+y*mat[i][3]+mat[i][5]);
            x = x0;
            jx = ((x-xa)/(xb-xa)*(imgx-1));
            jy = (imgy-1)-(y-ya)/(yb-ya)*imgy-1;
            // Paint it
            whtBr = CreateSolidBrush(RGB(255,255,255));
            hdc = BeginPaint(hwnd, &ps);
                dot(hdc, whtBr, (int)jx, (int)jy);
            EndPaint(hwnd, &ps);
            ReleaseDC(hwnd, hdc);
            if(k == end) {
                Sleep(5);
                done = 1;
            }
            break;
        case WM_TIMER:
            if(done == 0)
                InvalidateRect(hwnd, NULL, FALSE);
            else {
                InvalidateRect(hwnd, NULL, TRUE);
                k = 0;
                done = 0;
            }
            break;
        default:
            return DefScreenSaverProc(hwnd, message, wParam, lParam);
        }
    return 0;
}

BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    //return FALSE;}
    switch(message) {
        case WM_INITDIALOG:
            //get configuration from the registry
            return TRUE;
        case WM_COMMAND:
            switch(LOWORD(wParam)) {
                case IDOK:
                    //write configuration
                    EndDialog(hDlg, LOWORD(wParam) == IDOK);
                    return TRUE;
                case IDCANCEL:
                    EndDialog(hDlg, LOWORD(wParam) == IDOK);
                    return TRUE;
            }
    }
    return FALSE;
}

BOOL WINAPI RegisterDialogClasses(HANDLE hInst) {
    return TRUE;
}

Just a note, this is the rare time you will find me messing with Windows.

Fern Screensaver : Part 2

For those interested, here is roughly the same code in C for use with SDL. This first block are standard variables that are not by default when CodeBlocks produces an SDL template.

#include <time.h>
#include <unistd.h>

    // START RANDOM NUMBERS
    srand((unsigned)(time(0)));

    // VARIABLES
    float mat[4][7] = {
        {0.0,0.0,0.0,0.16,0.0,0.0,0.01},
        {0.85,0.04,-0.04,0.85,0.0,1.6,0.85},
        {0.2,-0.25,0.23,0.22,0.0,1.6,0.07},
        {-0.15,0.28,0.26,0.24,0.0,0.44,0.07}
    };
    // constant sets
    float xa = -5.5;
    float xb = 6.5;
    float ya = -0.5;
    float yb = 10.5;
    // x and y to be altered
    float x = 0.0;
    float y = 0.0;
    // screen/image size
    int imgx = 512;
    int imgy = 512;
    // floats for math fulction
    float p = 0.0;
    float x0 = 0;
    float jx = 0;
    float jy = 0;
    // variables to control function
    int i = 0;
    int k = 1;
    int end = imgx*imgy;

    // dot rect
    SDL_Rect dot;
    dot.x = screen->w/2;
    dot.y = screen->h/2;
    dot.h = 1;
    dot.w = 1;

This next block is the heart of the program. You’ll see this is very close to the Python code, but be aware that in C, you’re needing to be careful about your defined types.

        // DRAWING STARTS HERE

        // random number
        p = (float) rand()/RAND_MAX;
        // find random i
        if(p <= mat[0][6])
            i = 0;
        else if(p <= (mat[0][6] + mat[1][6]))
            i = 1;
        else if(p <= (mat[0][6] + mat[1][6] + mat[2][6]))
            i = 2;
        else
            i = 3;
        // super math function
        x0 = ((x*mat[i][0])+(y*mat[i][1])+mat[i][4]);
        y = (x*mat[i][2]+y*mat[i][3]+mat[i][5]);
        x = x0;
        jx = ((x-xa)/(xb-xa)*(imgx-1));
        jy = (imgy-1)-(y-ya)/(yb-ya)*imgy-1;
        // set dot
        dot.x = (int) jx;
        dot.y = (int) jy;
        // draw bitmap
        SDL_FillRect(screen, &dot, SDL_MapRGB(screen->format, 255, 255, 255));

        // DRAWING ENDS HERE

Finally, we control the program flow. I found that it looks like nothing is happend once the drawing is a quarter complete. So instead of running through every pixel, we’ll just do a quarter of them. This speeds up the program a bit. I’m thinking I may let them go but start a new one when each is a quarter done.

        // CLEANUP
        if(k == end) {
            k = 0;
            printf("Out of dots.\n");
            sleep(5);
            SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
        } else {
            k += 1;
            printf("\r%i out of %i",k,end);
            fflush(stdout);
        }

        SDL_Flip(screen);

Edit: For Windows users, you’ll need to have #include <Windows.h> and change sleep() to Sleep().

Fern Screensaver : Part 1

So my brother has asked me to help in making some iPhone/iPad applications.  Sounds like a great idea, I just need to get used to Objective-C.  If you already know C/C++, it’s not a huge leap to produce some iPhone code.  But I’m short of ideas to write and since most of the Mac is using Objective-C, I’ve decided practicing that language with something else, a screen saver!

I have done a simple screen saver using this excellent article to draw shapes.  I’ve decided to go from utilizing already produced code to doing something of my own.  My wife, who is a botanist at Iowa State was kind enough to loan me a Mac with Snow Leopard loaded, as school is out for the summer and they do not need this for their classes.  I asked her what she would like, and of course, it’s ferns (that’s the plant she studies).  Some quick thinking and googling lead me to the idea to use fractals!  In particular, Barnsley’s Fern.  To learn more, use google and this link.

Math drew this with a fractal equation, not by hand.

Now, as I have shown previously, I’m much better with Python, so to prototype the mathematical equation and code idea, I’ve developed a sample using pygame.  I found the math through this excellent code snippet, which saved me a lot of time in testing.  The use of the code is explained in the comments:

#!/usr/bin/python
import random, pygame, time
from PIL import Image
from pygame.locals import *
from pygame.color import THECOLORS as color

# VARIABLES TO INCLUDE MATH
mat = [[0.0,0.0,0.0,0.16,0.0,0.0,0.01],
	[0.85,0.04,-0.04,0.85,0.0,1.6,0.85],
	[0.2,-0.25,0.23,0.22,0.0,1.6,0.07],
	[-0.15,0.28,0.26,0.24,0.0,0.44,0.07]]

xa = -5.5
xb = 6.5
ya = -0.5
yb = 10.5

x = 0.0
y = 0.0

imgx = 700
imgy = 700

# VARIABLES FOR CONTROL
k = 1
end = imgx*imgy / 10 * 4 # Looks like nothing is happening after this point.

# START PYGAME AND SETUP
pygame.init()
screen = pygame.display.set_mode((imgx, imgy), 0, 8 )
pygame.display.set_caption('Fern Screensaver')
screen.fill(color['black'])

# START LOOP
done = False
while not done:
    # DETECT END OF DRAWING
    if k == end:
        # ENJOY AND RESET
        time.sleep(3)
        k = 0
        screen.fill(color['black'])
    else:
        # MATH FOR THE FRACTAL
        p = random.random()
        if p <= mat[0][6]:
            i = 0
        elif p <= mat[0][6] + mat[1][6]:
            i = 1
        elif p <= mat[0][6] + mat[1][6] + mat[2][6]:
            i = 2
        else:
            i = 3
        x0 = x * mat[i][0] + y * mat[i][1] + mat[i][4]
        y = x * mat[i][2] + y * mat[i][3] + mat[i][5]
        x = x0
        jx = int((x-xa)/(xb-xa)*(imgx-1))
        jy = int(imgy-1)-int((y-ya)/(yb-ya)*imgy-1)
        # AFTER PLAYING WITH SEVERAL COLORS, WHITE ON BLACK IS THE BEST
        c = color['white']
        screen.set_at((jx, jy), c)
        pygame.display.update()
    # DETECT EVENTS TO END PYGAME
    events = pygame.event.get()
    for e in events:
        if e.type == KEYDOWN and e.key == K_ESCAPE or e.type == QUIT:
            done = True
    # CYCLE AGAIN
    k += 1

# DONE
pygame.quit()

So, the next step is to code this for the Mac… keep posted for that code/tutorial.