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
render(SDL_Renderer * renderer,int w,int h,double deltaTime)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
initializeTextures(SDL_Renderer * renderer)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
main(int argc,char * argv[])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 }
227