accelerometer.c (6878B)
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 DAMPING 0.5f; /* after bouncing off a wall, damping coefficient determines final speed */ 12 #define FRICTION 0.0008f /* coefficient of acceleration that opposes direction of motion */ 13 #define GRAVITY_CONSTANT 0.004f /* how sensitive the ship is to the accelerometer */ 14 15 /* If we aren't on an iPhone, then this definition ought to yield reasonable behavior */ 16 #ifndef SDL_IPHONE_MAX_GFORCE 17 #define SDL_IPHONE_MAX_GFORCE 5.0f 18 #endif 19 20 static SDL_Joystick *accelerometer; /* used for controlling the ship */ 21 22 static struct 23 { 24 float x, y; /* position of ship */ 25 float vx, vy; /* velocity of ship (in pixels per millesecond) */ 26 SDL_Rect rect; /* (drawn) position and size of ship */ 27 } shipData; 28 29 static SDL_Texture *ship = 0; /* texture for spaceship */ 30 static SDL_Texture *space = 0; /* texture for space (background */ 31 32 void 33 render(SDL_Renderer *renderer, int w, int h, double deltaTime) 34 { 35 double deltaMilliseconds = deltaTime * 1000; 36 float speed; 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 deltaMilliseconds; 57 shipData.vy += 58 ay * SDL_IPHONE_MAX_GFORCE / SINT16_MAX * GRAVITY_CONSTANT * 59 deltaMilliseconds; 60 61 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 * deltaMilliseconds > 0) { 70 /* apply friction */ 71 shipData.vx -= dirx * FRICTION * deltaMilliseconds; 72 shipData.vy -= diry * FRICTION * deltaMilliseconds; 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 * deltaMilliseconds; 82 shipData.y += shipData.vy * deltaMilliseconds; 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 113 void 114 initializeTextures(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 157 int 158 main(int argc, char *argv[]) 159 { 160 161 SDL_Window *window; /* main window */ 162 SDL_Renderer *renderer; 163 int done; /* should we clean up and exit? */ 164 int w, h; 165 166 /* initialize SDL */ 167 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { 168 fatalError("Could not initialize SDL"); 169 } 170 171 /* create main window and renderer */ 172 window = SDL_CreateWindow(NULL, 0, 0, 320, 480, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_ALLOW_HIGHDPI); 173 renderer = SDL_CreateRenderer(window, 0, 0); 174 175 SDL_GetWindowSize(window, &w, &h); 176 SDL_RenderSetLogicalSize(renderer, w, h); 177 178 /* print out some info about joysticks and try to open accelerometer for use */ 179 printf("There are %d joysticks available\n", SDL_NumJoysticks()); 180 printf("Default joystick (index 0) is %s\n", SDL_JoystickName(0)); 181 accelerometer = SDL_JoystickOpen(0); 182 if (accelerometer == NULL) { 183 fatalError("Could not open joystick (accelerometer)"); 184 } 185 printf("joystick number of axis = %d\n", 186 SDL_JoystickNumAxes(accelerometer)); 187 printf("joystick number of hats = %d\n", 188 SDL_JoystickNumHats(accelerometer)); 189 printf("joystick number of balls = %d\n", 190 SDL_JoystickNumBalls(accelerometer)); 191 printf("joystick number of buttons = %d\n", 192 SDL_JoystickNumButtons(accelerometer)); 193 194 /* load graphics */ 195 initializeTextures(renderer); 196 197 /* setup ship */ 198 shipData.x = (w - shipData.rect.w) / 2; 199 shipData.y = (h - shipData.rect.h) / 2; 200 shipData.vx = 0.0f; 201 shipData.vy = 0.0f; 202 203 done = 0; 204 /* enter main loop */ 205 while (!done) { 206 double deltaTime = updateDeltaTime(); 207 SDL_Event event; 208 while (SDL_PollEvent(&event)) { 209 if (event.type == SDL_QUIT) { 210 done = 1; 211 } 212 } 213 render(renderer, w, h, deltaTime); 214 SDL_Delay(1); 215 } 216 217 /* delete textures */ 218 SDL_DestroyTexture(ship); 219 SDL_DestroyTexture(space); 220 221 /* shutdown SDL */ 222 SDL_Quit(); 223 224 return 0; 225 226 }