1 /**
2  * SDL joystick test
3 
4  * Copyright (C) 2007  Sylvain Beucler
5 
6  * This file is part of GNU FreeDink
7 
8  * GNU FreeDink is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 3 of the
11  * License, or (at your option) any later version.
12 
13  * GNU FreeDink is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17 
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see
20  * <http://www.gnu.org/licenses/>.
21  */
22 
23 /* Moves the heart surface using the joystick. Button 2 quits, button
24    4 goes full screen, button 6 triples the speed. */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include "SDL.h"
29 
30 #define IMIN(a,b) ((a < b) ? a : b)
31 #define IMAX(a,b) ((a > b) ? a : b)
32 
main(int argc,char * argv[])33 int main(int argc, char *argv[]) {
34   SDL_Joystick *joystick;
35   int i;
36   int quit = 0;
37   SDL_Surface *screen, *pic;
38   Uint32 video_flags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_ANYFORMAT | SDL_RESIZABLE;
39   SDL_Rect dst = {320, 240};
40 
41   int default_screen_w = 640, default_screen_h = 480;
42   double
43     px = 320,
44     py = 240,
45     cur_joyx = 0,
46     cur_joyy = 0;
47   Uint32 last_update = 0;
48 
49   /* pixels per second */
50   int full_speed = 200;
51 
52   if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) < 0)
53     {
54       fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
55       exit(1);
56     }
57 
58   screen = SDL_SetVideoMode(0, 0, 0, video_flags); /* SDL >= 1.10 */
59   if (screen == NULL)
60     {
61       printf("Trying %dx%d...\n", default_screen_w, default_screen_h);
62       screen = SDL_SetVideoMode(default_screen_w, default_screen_h, 0, video_flags);
63       if (screen == NULL)
64 	{
65 	  fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
66 	  exit(1);
67 	}
68     }
69   SDL_WM_SetCaption("JoyTest", NULL);
70   SDL_ShowCursor(SDL_DISABLE);
71 
72   pic = SDL_LoadBMP("pic.bmp");
73   if (pic == NULL)
74     {
75       fprintf(stderr, "Failed to load pic.bmp: %s\n", SDL_GetError());
76       exit(1);
77     }
78   SDL_SetColorKey(pic, SDL_SRCCOLORKEY, SDL_MapRGB(pic->format, 255, 255, 255));
79 
80   printf("%i joysticks were found.\n\n", SDL_NumJoysticks() );
81   printf("The names of the joysticks are:\n");
82 
83   for (i=0; i < SDL_NumJoysticks(); i++)
84     {
85       printf("    %s\n", SDL_JoystickName(i));
86     }
87 
88   SDL_JoystickEventState(SDL_ENABLE);
89   joystick = SDL_JoystickOpen(0);
90   printf("Number of axes: %d\n", SDL_JoystickNumAxes(joystick));
91   printf("Number of buttons: %d\n", SDL_JoystickNumButtons(joystick));
92   printf("Number of balls: %d\n", SDL_JoystickNumBalls(joystick));
93   printf("Number of hats: %d\n", SDL_JoystickNumHats(joystick));
94 
95   /* Flush stacked joystick events */
96   {
97     SDL_Event event;
98     while (SDL_PollEvent(&event));
99   }
100 
101   /* Fill screen in blue */
102   SDL_FillRect(screen, NULL,
103 	       SDL_MapRGB(screen->format, 0, 0, 255));
104   SDL_Flip(screen);
105 
106   last_update = SDL_GetTicks();
107 
108   /* Main game loop */
109   while(!quit) {
110     SDL_Event event;
111     while (SDL_PollEvent(&event))
112       {
113 	switch(event.type)
114 	  {
115 	  case SDL_KEYDOWN:
116 	    /* handle keyboard stuff here */
117 	    printf("Key pressed\n");
118 	    if (event.key.keysym.sym == 'q' || event.key.keysym.sym == SDLK_ESCAPE)
119 	      quit = 1;
120 	    break;
121 
122 	  case SDL_VIDEORESIZE:
123 	    {
124 	      SDL_ResizeEvent *resize = (SDL_ResizeEvent*)&event;
125 	      screen = SDL_SetVideoMode(resize->w, resize->h, 0, video_flags);
126 	      printf("Screen resized to %dx%d\n", resize->w, resize->h);
127 	    }
128 	    break;
129 
130 	  case SDL_QUIT:
131 	    quit = 1;
132 
133 	    break;
134 
135 	  case SDL_JOYAXISMOTION:  /* Joystick pad moved */
136 	    if (event.jaxis.axis == 0)
137 	      {
138 		/* Ignore noise from joystick */
139 		if ((event.jaxis.value < -3276 ) || (event.jaxis.value > 3276))
140 		  {
141 		    cur_joyx = event.jaxis.value;
142 		  }
143 		else
144 		  cur_joyx = 0;
145 	      }
146 
147 	    if (event.jaxis.axis == 1)
148 	      {
149 		/* Ignore noise from joystick */
150 		if ((event.jaxis.value < -3276 ) || (event.jaxis.value > 3276))
151 		  {
152 		    cur_joyy = event.jaxis.value;
153 		  }
154 		else
155 		  cur_joyy = 0;
156 	      }
157 
158  	    break;
159 
160 	  case SDL_JOYBUTTONDOWN:  /* Joystick button pressed */
161 	    printf("Button %d pressed\n", event.jbutton.button);
162 	    if (event.jbutton.button == 3)
163 	    {
164  	      SDL_WM_ToggleFullScreen(screen);
165 	    }
166 	    else if (event.jbutton.button == 1)
167 	      {
168 		quit = 1;
169 	      }
170 	    else if (event.jbutton.button == 5)
171 	      {
172 		full_speed *= 3;
173 	      }
174 	    break;
175 
176 	  case SDL_JOYBUTTONUP:  /* Joystick button pressed */
177 	    if (event.jbutton.button == 5)
178 	      {
179 		full_speed /= 3;
180 	      }
181 	    break;
182 	  }
183       }
184 
185     {
186       SDL_Rect erase, update;
187       int prev_x, prev_y;
188       int update_p1_x, update_p1_y;
189       int update_p2_x, update_p2_y;
190       double dx = 0, dy = 0;
191       Uint32 dt;
192 
193       /* Check elapsed time since last frame */
194       dt = SDL_GetTicks() - last_update;
195       last_update = SDL_GetTicks();
196 
197 
198       /* Erase last position */
199       prev_x = dst.x;
200       prev_y = dst.y;
201       erase.x = prev_x;
202       erase.y = prev_y;
203       erase.w = pic->w;
204       erase.h = pic->h;
205       SDL_FillRect(screen, &erase,
206 		   SDL_MapRGB(screen->format, 0, 0, 255));
207 
208 
209       /* Update position */
210       /* dx/dy is the speed in pixels per second */
211       /* In one second, with full push (32767), I'll move full_speed (200) pixels */
212       dx = cur_joyx * (1.0 * full_speed / 32767) * dt/1000;
213       dy = cur_joyy * (1.0 * full_speed / 32767) * dt/1000;
214       px += dx;
215       py += dy;
216       dst.x = px;
217       dst.y = py;
218 
219 
220       /* Display new position */
221       SDL_BlitSurface(pic, NULL, screen, &dst);
222 
223 
224       /* What to refresh */
225       update_p1_x = IMIN(prev_x, dst.x);
226       update_p1_y = IMIN(prev_y, dst.y);
227       update_p2_x = IMAX(prev_x, dst.x) + pic->w;
228       update_p2_y = IMAX(prev_y, dst.y) + pic->h;
229 
230       /* Clipping */
231       update_p1_x = IMIN(IMAX(update_p1_x, 0), screen->w);
232       update_p1_y = IMIN(IMAX(update_p1_y, 0), screen->h);
233       update_p2_x = IMIN(IMAX(update_p2_x, 0), screen->w);
234       update_p2_y = IMIN(IMAX(update_p2_y, 0), screen->h);
235 
236       /* Refresh */
237       update.x = update_p1_x;
238       update.y = update_p1_y;
239       update.w = update_p2_x - update_p1_x;
240       update.h = update_p2_y - update_p1_y;
241       SDL_UpdateRects(screen, 1, &update);
242       /* printf("pos %f,%f\n", px, py); */
243     }
244   }
245   SDL_JoystickClose(joystick);
246   SDL_Quit();
247   return 0;
248 }
249