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