Handle the default case more robustly when parsing events
[experiments/SDL.git] / scrolling / sdl-scrolling.c
1 /* 
2  * sdl-scrolling - Example program for scrolling images in SDL
3  *
4  * Copyright (C) 2013  Antonio Ospite <ospite@studenti.unina.it>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <SDL.h>
26 #include <SDL_image.h>
27
28 #define WIDTH 800
29 #define HEIGHT 480
30
31 #define FPS 30
32
33 static int mod(int a, int b)
34 {
35         int c = a % b;
36         return (c < 0) ? c + b : c;
37 }
38
39 static SDL_Surface *load_image(const char *filename)
40 {
41         SDL_Surface *image = NULL;
42         SDL_Surface *optimized_image = NULL;
43
44         image = IMG_Load(filename);
45         if (!image) {
46                 fprintf(stderr, "IMG_Load: %s\n", IMG_GetError());
47                 return NULL;
48         }
49
50         optimized_image = SDL_DisplayFormat(image);
51         if (!optimized_image) {
52                 fprintf(stderr, "erro whan calling SDL_DisplayFormat().\n");
53                 return NULL;
54         }
55         SDL_FreeSurface(image);
56
57         return optimized_image;
58 }
59
60 int main(int argc, char *argv[])
61 {
62         int ret;
63         SDL_Surface* screen = NULL;
64         SDL_Surface* map = NULL;
65         SDL_Rect viewport = {0 , 0, WIDTH, HEIGHT};
66         SDL_Event event;
67         SDL_Joystick *joystick = NULL;
68
69         int running = 1;
70
71         Sint16 y_offset = 0;
72         Sint16 y = 0;
73         Sint16 lastframe_limit;
74         Uint32 time_start;
75         Uint32 time_end;
76
77         int output_fd = -1;
78
79         if (argc < 2) {
80                 fprintf(stderr, "usage: %s <image> [<output file>]\n", argv[0]);
81                 return -EINVAL;
82         }
83
84         SDL_Init(SDL_INIT_TIMER | SDL_INIT_JOYSTICK);
85
86         screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_HWSURFACE);
87         if (!screen) {
88                 fprintf(stderr, "Cannot set video mode\n");
89                 ret = -EINVAL;
90                 goto out;
91         }
92
93         map = load_image(argv[1]);
94         if (!map) {
95                 ret = -EINVAL;
96                 goto out;
97         }
98
99         /* Set up the output file */
100         if (argc >= 3) {
101                 if (strncmp(argv[2], "-", 1) == 0) {
102                         output_fd = STDOUT_FILENO;
103                 } else {
104                         output_fd = open(argv[2], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
105                         if (output_fd < 0) {
106                                 perror("open");
107                                 ret = output_fd;
108                                 goto out;
109                         }
110                 }
111         }
112
113         lastframe_limit = (map->h - HEIGHT);
114
115         if (SDL_NumJoysticks() > 0)
116                 joystick = SDL_JoystickOpen(0);
117
118         SDL_JoystickEventState(SDL_ENABLE);
119         SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
120
121         while (running) {
122                 time_start = SDL_GetTicks();
123
124                 while(SDL_PollEvent(&event)) {
125                         switch(event.type) {
126                         case SDL_QUIT:
127                                 running = 0;
128                                 break;
129
130                         case SDL_KEYDOWN:
131                                 switch(event.key.keysym.sym) {
132                                 case SDLK_ESCAPE:
133                                 case SDLK_q:
134                                         running = 0;
135                                         break;
136
137                                 case SDLK_UP:
138                                         y_offset += 1;
139                                         break;
140
141                                 case SDLK_DOWN:
142                                         y_offset -= 1;
143                                         break;
144
145                                 default:
146                                         printf("key: '%s' keysym: %d\n",
147                                                SDL_GetKeyName(event.key.keysym.sym),
148                                                event.key.keysym.sym);
149                                         break;
150                                 }
151                                 break;
152
153                         case SDL_JOYAXISMOTION:
154                                 fprintf(stderr, "Joystick which: %d, axis: %d, value: %d\n",
155                                         event.jaxis.which, event.jaxis.axis, event.jaxis.value);
156                                 if (event.jaxis.which == 0) {
157                                         if (event.jaxis.axis == 0)
158                                                 /* TODO: improve scaling here */
159                                                 y_offset = event.jaxis.value;
160                                 }
161                                 break;
162
163                         default:
164                                 /* ignore other events */
165                                 break;
166                         }
167                 }
168
169                 y += y_offset;
170                 y = mod(y, lastframe_limit);
171
172                 viewport.y = y;
173                 SDL_BlitSurface(map, &viewport, screen, NULL);
174                 SDL_Flip(screen);
175
176                 if (output_fd >= 0) {
177                         int len = screen->w * screen->h * screen->format->BytesPerPixel;
178
179                         ret = write(output_fd, screen->pixels, len);
180                         if (ret != len) {
181                                 fprintf(stderr, "invalid write\n");
182                                 running = 0;
183                         }
184                 }
185
186                 time_end = SDL_GetTicks();
187                 if (time_end - time_start < 1000 / FPS)
188                         SDL_Delay((1000 / FPS) - (time_end - time_start));
189         }
190
191         ret = 0;
192
193         if (output_fd >= 0)
194                 close(output_fd);
195
196         if (SDL_JoystickOpened(0))
197                 SDL_JoystickClose(joystick);
198
199         SDL_FreeSurface(map);
200 out:
201         SDL_Quit();
202         return ret;
203 }