Demo of iPhone accelerometer as SDL joystick gsoc2008_iphone
authorHolmes Futrell <hfutrell@umail.ucsb.edu>
Fri, 18 Jul 2008 20:50:59 +0000
branchgsoc2008_iphone
changeset 23807fbcfc1574dc
parent 2379 bce19d88266c
child 2381 d3952f445f4d
Demo of iPhone accelerometer as SDL joystick
XCodeiPhoneOS/Demos/src/accelerometer.c
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/XCodeiPhoneOS/Demos/src/accelerometer.c	Fri Jul 18 20:50:59 2008 +0000
     1.3 @@ -0,0 +1,225 @@
     1.4 +/*
     1.5 + *	accelerometer.c
     1.6 + *	written by Holmes Futrell
     1.7 + *	use however you want
     1.8 + */
     1.9 +
    1.10 +#include "SDL.h"
    1.11 +#include "math.h"
    1.12 +#include "common.h"
    1.13 +
    1.14 +#define MILLESECONDS_PER_FRAME 16	/* about 60 frames per second */
    1.15 +#define DAMPING 0.5f;				/* after bouncing off a wall, damping coefficient determines final speed */
    1.16 +#define FRICTION 0.0008f			/* coefficient of acceleration that opposes direction of motion */
    1.17 +#define GRAVITY_CONSTANT 0.02f		/* how sensitive the ship is to the accelerometer */
    1.18 +
    1.19 +static SDL_Joystick *accelerometer; /* used for controlling the ship */
    1.20 +
    1.21 +static struct {
    1.22 +	float x, y;			/* position of ship */
    1.23 +	float vx, vy;		/* velocity of ship (in pixels per millesecond) */
    1.24 +	SDL_Rect rect;		/* (drawn) position and size of ship */
    1.25 +} ship;
    1.26 +
    1.27 +static SDL_TextureID shipID=0;		/* texture for spaceship */
    1.28 +static SDL_TextureID spaceID=0;		/* texture for space (background */
    1.29 +
    1.30 +void render(void) {
    1.31 +		
    1.32 +	/* get joystick (accelerometer) axis values and normalize them */
    1.33 +	float amax = (float)(0x7FFF); /* largest Sint16 number */
    1.34 +	float ax = SDL_JoystickGetAxis(accelerometer, 0) / amax; 
    1.35 +	float ay = -SDL_JoystickGetAxis(accelerometer, 1) / amax; 
    1.36 +		
    1.37 +	/* ship screen constraints */
    1.38 +	Uint32 minx = 0.0f;
    1.39 +	Uint32 maxx = SCREEN_WIDTH - ship.rect.w;
    1.40 +	Uint32 miny = 0.0f;
    1.41 +	Uint32 maxy = SCREEN_HEIGHT - ship.rect.h;	
    1.42 +		
    1.43 +	/* update velocity from accelerometer */
    1.44 +	ship.vx += ax * GRAVITY_CONSTANT * MILLESECONDS_PER_FRAME;
    1.45 +	ship.vy += ay * GRAVITY_CONSTANT * MILLESECONDS_PER_FRAME;
    1.46 +	
    1.47 +	float speed = sqrt(ship.vx * ship.vx + ship.vy * ship.vy);
    1.48 +	
    1.49 +	if (speed > 0) {
    1.50 +		/* compensate for friction */
    1.51 +		float dirx =  ship.vx / speed; /* normalized x velocity */
    1.52 +		float diry =  ship.vy / speed; /* normalized y velocity */
    1.53 +		
    1.54 +		/* update velocity due to friction */
    1.55 +		if (speed - FRICTION * MILLESECONDS_PER_FRAME > 0) {
    1.56 +			/* apply friction */
    1.57 +			ship.vx -= dirx * FRICTION * MILLESECONDS_PER_FRAME;
    1.58 +			ship.vy -= diry * FRICTION * MILLESECONDS_PER_FRAME;
    1.59 +		}
    1.60 +		else {
    1.61 +			/* applying friction would MORE than stop the ship, so just stop the ship */
    1.62 +			ship.vx = 0.0f;
    1.63 +			ship.vy = 0.0f;
    1.64 +		}
    1.65 +	}
    1.66 +	
    1.67 +	/* update ship location */
    1.68 +	ship.x += ship.vx * MILLESECONDS_PER_FRAME;
    1.69 +	ship.y += ship.vy * MILLESECONDS_PER_FRAME;
    1.70 +		
    1.71 +	if (ship.x > maxx) {
    1.72 +		ship.x = maxx;
    1.73 +		ship.vx = -ship.vx * DAMPING;
    1.74 +	}
    1.75 +	else if (ship.x < minx) {
    1.76 +		ship.x = minx;
    1.77 +		ship.vx = -ship.vx * DAMPING;
    1.78 +	}
    1.79 +	if (ship.y > maxy) {
    1.80 +		ship.y = maxy;
    1.81 +		ship.vy = -ship.vy * DAMPING;
    1.82 +	}
    1.83 +	else if (ship.y < miny) {
    1.84 +		ship.y = miny;
    1.85 +		ship.vy = -ship.vy * DAMPING;
    1.86 +	}
    1.87 +	
    1.88 +	/* draw the background */
    1.89 +	SDL_RenderCopy(spaceID, NULL, NULL);
    1.90 +
    1.91 +	/* draw the ship */
    1.92 +	ship.rect.x = ship.x;
    1.93 +	ship.rect.y = ship.y;
    1.94 +
    1.95 +	SDL_RenderCopy(shipID, NULL, &ship.rect);
    1.96 +	
    1.97 +	/* update screen */
    1.98 +	SDL_RenderPresent();
    1.99 +		
   1.100 +}
   1.101 +
   1.102 +void initializeTextures() {
   1.103 +	
   1.104 +	SDL_Surface *bmp_surface;
   1.105 +	SDL_Surface *bmp_surface_rgba;
   1.106 +	int format = SDL_PIXELFORMAT_ABGR8888; /* desired texture format */
   1.107 +	Uint32 Rmask, Gmask, Bmask, Amask;	   /* masks for desired format */
   1.108 +	int bpp;							   /* bits per pixel for desired format */
   1.109 +
   1.110 +	/* load the ship */
   1.111 +	bmp_surface = SDL_LoadBMP("ship.bmp");
   1.112 +	if (bmp_surface == NULL) {
   1.113 +		fatalError("could not ship.bmp");
   1.114 +	}
   1.115 +	/* set blue to transparent on the ship */
   1.116 +	SDL_SetColorKey(bmp_surface, 1, SDL_MapRGB(bmp_surface->format, 0, 0, 255));
   1.117 +	SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
   1.118 +	/*
   1.119 +		create a new RGBA surface and blit the bmp to it
   1.120 +		this is an extra step, but it seems to be necessary for the color key to work
   1.121 +		
   1.122 +		does the fact that this is necessary indicate a bug in SDL?
   1.123 +	*/
   1.124 +	bmp_surface_rgba = SDL_CreateRGBSurface(0, bmp_surface->w, bmp_surface->h, bpp, Rmask, Gmask, Bmask, Amask);	
   1.125 +	SDL_BlitSurface(bmp_surface, NULL, bmp_surface_rgba, NULL);
   1.126 +	
   1.127 +	/* create ship texture from surface */
   1.128 +	shipID = SDL_CreateTextureFromSurface(format, bmp_surface_rgba);
   1.129 +	if (shipID == 0) {
   1.130 +		fatalError("could not create ship texture");
   1.131 +	}
   1.132 +	SDL_SetTextureBlendMode(shipID, SDL_TEXTUREBLENDMODE_BLEND);
   1.133 +	
   1.134 +	/* set the width and height of the ship from the surface dimensions */
   1.135 +	ship.rect.w = bmp_surface->w;
   1.136 +	ship.rect.h = bmp_surface->h;
   1.137 +	
   1.138 +	SDL_FreeSurface(bmp_surface_rgba);
   1.139 +	SDL_FreeSurface(bmp_surface);
   1.140 +	
   1.141 +	/* load the space background */
   1.142 +	bmp_surface = SDL_LoadBMP("space.bmp");
   1.143 +	if (bmp_surface == NULL) {
   1.144 +		fatalError("could not load space.bmp");
   1.145 +	}
   1.146 +	/* create space texture from surface */
   1.147 +	spaceID = SDL_CreateTextureFromSurface(format, bmp_surface);
   1.148 +	if (spaceID == 0) {
   1.149 +		fatalError("could not create space texture");
   1.150 +	}
   1.151 +	SDL_FreeSurface(bmp_surface);
   1.152 +
   1.153 +}
   1.154 +
   1.155 +
   1.156 +
   1.157 +int main(int argc, char *argv[]) {
   1.158 +	
   1.159 +	SDL_WindowID windowID;	/* ID of main window */
   1.160 +	Uint32 startFrame;		/* time frame began to process */
   1.161 +	Uint32 endFrame;		/* time frame ended processing */
   1.162 +	Uint32 delay;			/* time to pause waiting to draw next frame */
   1.163 +	int done;				/* should we clean up and exit? */
   1.164 +	
   1.165 +	/* initialize SDL */
   1.166 +	if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0) {
   1.167 +		fatalError("Could not initialize SDL");
   1.168 +	}
   1.169 +	
   1.170 +	/* create main window and renderer */
   1.171 +	windowID = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,\
   1.172 +								SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_BORDERLESS);
   1.173 +	SDL_CreateRenderer(windowID, 0, 0);		
   1.174 +	
   1.175 +	/* print out some info about joysticks and try to open accelerometer for use */
   1.176 +	printf("There are %d joysticks available\n", SDL_NumJoysticks());
   1.177 +	printf("Default joystick (index 0) is %s\n", SDL_JoystickName(0));
   1.178 +	accelerometer = SDL_JoystickOpen(0);
   1.179 +	if (accelerometer == NULL) {
   1.180 +		fatalError("Could not open joystick (accelerometer)");
   1.181 +	}
   1.182 +	printf("joystick number of axis = %d\n", SDL_JoystickNumAxes(accelerometer));
   1.183 + 	printf("joystick number of hats = %d\n", SDL_JoystickNumHats(accelerometer));
   1.184 + 	printf("joystick number of balls = %d\n", SDL_JoystickNumBalls(accelerometer));
   1.185 + 	printf("joystick number of buttons = %d\n", SDL_JoystickNumButtons(accelerometer));
   1.186 +	
   1.187 +	/* load graphics */
   1.188 +	initializeTextures();
   1.189 +	
   1.190 +	/* setup ship */
   1.191 +	ship.x = (SCREEN_WIDTH - ship.rect.w) / 2;
   1.192 +	ship.y = (SCREEN_HEIGHT - ship.rect.h) / 2;
   1.193 +	ship.vx = 0.0f;
   1.194 +	ship.vy = 0.0f;
   1.195 +	
   1.196 +	done = 0;
   1.197 +	/* enter main loop */
   1.198 +	while(!done) {
   1.199 +		startFrame = SDL_GetTicks();
   1.200 +		SDL_Event event;
   1.201 +        while (SDL_PollEvent(&event)) {
   1.202 +            if (event.type == SDL_QUIT) {
   1.203 +				done = 1;
   1.204 +            }
   1.205 +        }
   1.206 +		render();
   1.207 +		endFrame = SDL_GetTicks();
   1.208 +		
   1.209 +		/* figure out how much time we have left, and then sleep */
   1.210 +		delay = MILLESECONDS_PER_FRAME - (endFrame - startFrame);
   1.211 +		if (delay < 0) {
   1.212 +			delay = 0;
   1.213 +		} else if (delay > MILLESECONDS_PER_FRAME) {
   1.214 +			delay = MILLESECONDS_PER_FRAME;
   1.215 +		}
   1.216 +		SDL_Delay(delay);
   1.217 +	}
   1.218 +	
   1.219 +	/* delete textures */
   1.220 +	SDL_DestroyTexture(shipID);
   1.221 +	SDL_DestroyTexture(spaceID);
   1.222 +	
   1.223 +	/* shutdown SDL */
   1.224 +	SDL_Quit();
   1.225 +	
   1.226 +	return 0;
   1.227 +	
   1.228 +}
   1.229 \ No newline at end of file