accelerometer.c (7459B)
1/* 2 * accelerometer.c 3 * written by Holmes Futrell 4 * use however you want 5 */ 6 7#include "SDL.h" 8#include "math.h" 9#include "common.h" 10 11#define MILLESECONDS_PER_FRAME 16 /* about 60 frames per second */ 12#define DAMPING 0.5f; /* after bouncing off a wall, damping coefficient determines final speed */ 13#define FRICTION 0.0008f /* coefficient of acceleration that opposes direction of motion */ 14#define GRAVITY_CONSTANT 0.004f /* how sensitive the ship is to the accelerometer */ 15 16/* If we aren't on an iPhone, then this definition ought to yield reasonable behavior */ 17#ifndef SDL_IPHONE_MAX_GFORCE 18#define SDL_IPHONE_MAX_GFORCE 5.0f 19#endif 20 21static SDL_Joystick *accelerometer; /* used for controlling the ship */ 22 23static struct 24{ 25 float x, y; /* position of ship */ 26 float vx, vy; /* velocity of ship (in pixels per millesecond) */ 27 SDL_Rect rect; /* (drawn) position and size of ship */ 28} shipData; 29 30static SDL_Texture *ship = 0; /* texture for spaceship */ 31static SDL_Texture *space = 0; /* texture for space (background */ 32 33void 34render(SDL_Renderer *renderer, int w, int h) 35{ 36 37 38 /* get joystick (accelerometer) axis values and normalize them */ 39 float ax = SDL_JoystickGetAxis(accelerometer, 0); 40 float ay = SDL_JoystickGetAxis(accelerometer, 1); 41 42 /* ship screen constraints */ 43 Uint32 minx = 0.0f; 44 Uint32 maxx = w - shipData.rect.w; 45 Uint32 miny = 0.0f; 46 Uint32 maxy = h - shipData.rect.h; 47 48#define SINT16_MAX ((float)(0x7FFF)) 49 50 /* update velocity from accelerometer 51 the factor SDL_IPHONE_MAX_G_FORCE / SINT16_MAX converts between 52 SDL's units reported from the joytick, and units of g-force, as reported by the accelerometer 53 */ 54 shipData.vx += 55 ax * SDL_IPHONE_MAX_GFORCE / SINT16_MAX * GRAVITY_CONSTANT * 56 MILLESECONDS_PER_FRAME; 57 shipData.vy += 58 ay * SDL_IPHONE_MAX_GFORCE / SINT16_MAX * GRAVITY_CONSTANT * 59 MILLESECONDS_PER_FRAME; 60 61 float speed = sqrt(shipData.vx * shipData.vx + shipData.vy * shipData.vy); 62 63 if (speed > 0) { 64 /* compensate for friction */ 65 float dirx = shipData.vx / speed; /* normalized x velocity */ 66 float diry = shipData.vy / speed; /* normalized y velocity */ 67 68 /* update velocity due to friction */ 69 if (speed - FRICTION * MILLESECONDS_PER_FRAME > 0) { 70 /* apply friction */ 71 shipData.vx -= dirx * FRICTION * MILLESECONDS_PER_FRAME; 72 shipData.vy -= diry * FRICTION * MILLESECONDS_PER_FRAME; 73 } else { 74 /* applying friction would MORE than stop the ship, so just stop the ship */ 75 shipData.vx = 0.0f; 76 shipData.vy = 0.0f; 77 } 78 } 79 80 /* update ship location */ 81 shipData.x += shipData.vx * MILLESECONDS_PER_FRAME; 82 shipData.y += shipData.vy * MILLESECONDS_PER_FRAME; 83 84 if (shipData.x > maxx) { 85 shipData.x = maxx; 86 shipData.vx = -shipData.vx * DAMPING; 87 } else if (shipData.x < minx) { 88 shipData.x = minx; 89 shipData.vx = -shipData.vx * DAMPING; 90 } 91 if (shipData.y > maxy) { 92 shipData.y = maxy; 93 shipData.vy = -shipData.vy * DAMPING; 94 } else if (shipData.y < miny) { 95 shipData.y = miny; 96 shipData.vy = -shipData.vy * DAMPING; 97 } 98 99 /* draw the background */ 100 SDL_RenderCopy(renderer, space, NULL, NULL); 101 102 /* draw the ship */ 103 shipData.rect.x = shipData.x; 104 shipData.rect.y = shipData.y; 105 106 SDL_RenderCopy(renderer, ship, NULL, &shipData.rect); 107 108 /* update screen */ 109 SDL_RenderPresent(renderer); 110 111} 112 113void 114initializeTextures(SDL_Renderer *renderer) 115{ 116 117 SDL_Surface *bmp_surface; 118 119 /* load the ship */ 120 bmp_surface = SDL_LoadBMP("ship.bmp"); 121 if (bmp_surface == NULL) { 122 fatalError("could not ship.bmp"); 123 } 124 /* set blue to transparent on the ship */ 125 SDL_SetColorKey(bmp_surface, 1, 126 SDL_MapRGB(bmp_surface->format, 0, 0, 255)); 127 128 /* create ship texture from surface */ 129 ship = SDL_CreateTextureFromSurface(renderer, bmp_surface); 130 if (ship == 0) { 131 fatalError("could not create ship texture"); 132 } 133 SDL_SetTextureBlendMode(ship, SDL_BLENDMODE_BLEND); 134 135 /* set the width and height of the ship from the surface dimensions */ 136 shipData.rect.w = bmp_surface->w; 137 shipData.rect.h = bmp_surface->h; 138 139 SDL_FreeSurface(bmp_surface); 140 141 /* load the space background */ 142 bmp_surface = SDL_LoadBMP("space.bmp"); 143 if (bmp_surface == NULL) { 144 fatalError("could not load space.bmp"); 145 } 146 /* create space texture from surface */ 147 space = SDL_CreateTextureFromSurface(renderer, bmp_surface); 148 if (space == 0) { 149 fatalError("could not create space texture"); 150 } 151 SDL_FreeSurface(bmp_surface); 152 153} 154 155 156 157int 158main(int argc, char *argv[]) 159{ 160 161 SDL_Window *window; /* main window */ 162 SDL_Renderer *renderer; 163 Uint32 startFrame; /* time frame began to process */ 164 Uint32 endFrame; /* time frame ended processing */ 165 Sint32 delay; /* time to pause waiting to draw next frame */ 166 int done; /* should we clean up and exit? */ 167 int w, h; 168 169 /* initialize SDL */ 170 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { 171 fatalError("Could not initialize SDL"); 172 } 173 174 /* create main window and renderer */ 175 window = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 176 SDL_WINDOW_OPENGL | 177 SDL_WINDOW_FULLSCREEN); 178 renderer = SDL_CreateRenderer(window, 0, 0); 179 180 SDL_GetWindowSize(window, &w, &h); 181 182 /* print out some info about joysticks and try to open accelerometer for use */ 183 printf("There are %d joysticks available\n", SDL_NumJoysticks()); 184 printf("Default joystick (index 0) is %s\n", SDL_JoystickName(0)); 185 accelerometer = SDL_JoystickOpen(0); 186 if (accelerometer == NULL) { 187 fatalError("Could not open joystick (accelerometer)"); 188 } 189 printf("joystick number of axis = %d\n", 190 SDL_JoystickNumAxes(accelerometer)); 191 printf("joystick number of hats = %d\n", 192 SDL_JoystickNumHats(accelerometer)); 193 printf("joystick number of balls = %d\n", 194 SDL_JoystickNumBalls(accelerometer)); 195 printf("joystick number of buttons = %d\n", 196 SDL_JoystickNumButtons(accelerometer)); 197 198 /* load graphics */ 199 initializeTextures(renderer); 200 201 /* setup ship */ 202 shipData.x = (w - shipData.rect.w) / 2; 203 shipData.y = (h - shipData.rect.h) / 2; 204 shipData.vx = 0.0f; 205 shipData.vy = 0.0f; 206 207 done = 0; 208 /* enter main loop */ 209 while (!done) { 210 startFrame = SDL_GetTicks(); 211 SDL_Event event; 212 while (SDL_PollEvent(&event)) { 213 if (event.type == SDL_QUIT) { 214 done = 1; 215 } 216 } 217 render(renderer, w, h); 218 endFrame = SDL_GetTicks(); 219 220 /* figure out how much time we have left, and then sleep */ 221 delay = MILLESECONDS_PER_FRAME - (endFrame - startFrame); 222 if (delay < 0) { 223 delay = 0; 224 } else if (delay > MILLESECONDS_PER_FRAME) { 225 delay = MILLESECONDS_PER_FRAME; 226 } 227 SDL_Delay(delay); 228 } 229 230 /* delete textures */ 231 SDL_DestroyTexture(ship); 232 SDL_DestroyTexture(space); 233 234 /* shutdown SDL */ 235 SDL_Quit(); 236 237 return 0; 238 239}