accelerometer.c 7.3 KB

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