1 /*
2 * Copyright (c) 2008,2009 Bertrand Janin <tamentis@neopulsar.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27
28 /*
29 * Event handling during game play.
30 */
31
32
33 #include <stdio.h>
34
35 #include "SDL.h"
36 #include "rezerwar.h"
37
38
39 extern Board *board;
40 extern Configuration *conf;
41 SDL_Surface *screen;
42 Cube *speedy; // currently accelerated cube
43
44
45 /**
46 * Keyboard up (stop moving one side or stop accelerating).
47 */
48 enum mtype
handle_events_keyup(SDL_Event * event)49 handle_events_keyup(SDL_Event *event)
50 {
51 switch ((int)event->key.keysym.sym) {
52 case SDLK_DOWN:
53 case SDLK_j:
54 if (board->current_cube == speedy) {
55 speedy->speed *= 8;
56 speedy = NULL;
57 }
58 break;
59 case SDLK_RIGHT:
60 case SDLK_l:
61 board->moving_right = 0;
62 break;
63 case SDLK_LEFT:
64 case SDLK_h:
65 board->moving_left = 0;
66 break;
67 default:
68 break;
69 }
70
71 return MTYPE_NOP;
72 }
73
74
75 /**
76 * Keydown.
77 */
78 enum mtype
handle_events_keydown(SDL_Event * event)79 handle_events_keydown(SDL_Event *event)
80 {
81 enum {
82 nothing,
83 menu,
84 fps,
85 rotate_cw,
86 pause,
87 left,
88 right,
89 leftonce,
90 rightonce,
91 down,
92 center,
93 hold,
94 fall,
95 fullscreen
96 } action = nothing;
97
98 if (event->type == SDL_JOYHATMOTION) {
99 if (event->jhat.value & SDL_HAT_LEFT)
100 action = leftonce;
101 else if (event->jhat.value & SDL_HAT_RIGHT)
102 action = rightonce;
103 else if (event->jhat.value & SDL_HAT_UP)
104 action = fall;
105 }
106
107 #ifdef __WII__
108 if (event->type == SDL_JOYBUTTONDOWN) {
109 switch (event->jbutton.button) {
110 case WPAD_BUTTON_HOME:
111 action = menu;
112 break;
113 case WPAD_BUTTON_PLUS:
114 case WPAD_BUTTON_MINUS:
115 action = pause;
116 break;
117 case WPAD_BUTTON_1:
118 case WPAD_BUTTON_2:
119 action = rotate_cw;
120 break;
121 case WPAD_BUTTON_B:
122 action = hold;
123 break;
124 default:
125 break;
126 }
127 }
128 #endif
129
130 if (event->type == SDL_KEYDOWN) {
131 switch ((int)event->key.keysym.sym) {
132 case SDLK_ESCAPE:
133 case SDLK_q:
134 board->gameover = true;
135 if (board->modal)
136 action = menu;
137 break;
138 case SDLK_F12:
139 action = fps;
140 break;
141 case SDLK_F11:
142 board_spawn_mole(board);
143 board_dump_cube_map(board);
144 break;
145 case SDLK_LEFT:
146 case SDLK_h:
147 action = left;
148 break;
149 case SDLK_RIGHT:
150 case SDLK_l:
151 action = right;
152 break;
153 case SDLK_UP:
154 case SDLK_k:
155 action = fall;
156 break;
157 case SDLK_DOWN:
158 case SDLK_j:
159 action = down;
160 break;
161 case SDLK_a:
162 case SDLK_SPACE:
163 action = rotate_cw;
164 break;
165 case SDLK_p:
166 case SDLK_RETURN:
167 action = pause;
168 break;
169 case SDLK_f:
170 action = fullscreen;
171 break;
172 case SDLK_TAB:
173 action = hold;
174 break;
175 default:
176 break;
177 }
178 }
179
180 /* If a modal is present, ignore everything but menu and pause. */
181 if (board->modal == true && action != menu && action != pause)
182 return MTYPE_NOP;
183
184 switch (action) {
185 case menu:
186 return MTYPE_SUBMENU;
187 break;
188 case fps:
189 board->show_fps = !board->show_fps;
190 break;
191 case left:
192 board_move_current_cube_left(board);
193 board_render(board);
194 board->lateral_tick = 0;
195 board->moving_left = 4;
196 break;
197 case right:
198 board_move_current_cube_right(board);
199 board_render(board);
200 board->lateral_tick = 0;
201 board->moving_right = 4;
202 break;
203 case leftonce:
204 board_move_current_cube_left(board);
205 board_render(board);
206 break;
207 case rightonce:
208 board_move_current_cube_right(board);
209 board_render(board);
210 break;
211 case down:
212 if (board->current_cube != NULL) {
213 speedy = board->current_cube;
214 speedy->speed /= 8;
215 }
216 break;
217 case fall:
218 board_cube_fall(board);
219 break;
220 case rotate_cw:
221 board_rotate_cw(board);
222 break;
223 case pause:
224 board_toggle_pause(board);
225 break;
226 case hold:
227 board_hold(board);
228 break;
229 case fullscreen:
230 /* SDL on win32 is unable to toggle video mode... */
231 conf->fullscreen = !conf->fullscreen;
232 #ifdef _WIN32
233 gfx_init();
234 #else
235 if (SDL_WM_ToggleFullScreen(screen) == 0)
236 fatal("Unable to toggle fullscreen/windowed mode.");
237 #endif
238 break;
239 default:
240 break;
241 }
242
243 return MTYPE_NOP;
244 }
245
246
247 /**
248 * Usually returns NOP unless SQL_QUIT (window close) is triggered, it gets
249 * its mtypes from the sub-routines.
250 */
251 enum mtype
handle_events(SDL_Event * event)252 handle_events(SDL_Event *event)
253 {
254 switch (event->type) {
255 case SDL_KEYDOWN:
256 case SDL_JOYBUTTONDOWN:
257 case SDL_JOYHATMOTION:
258 return handle_events_keydown(event);
259 break;
260 case SDL_KEYUP:
261 return handle_events_keyup(event);
262 break;
263 case SDL_QUIT:
264 return MTYPE_QUIT;
265 break;
266 default:
267 break;
268 }
269
270 return MTYPE_NOP;
271 }
272
273
274 void
wait_for_keymouse(void)275 wait_for_keymouse(void)
276 {
277 SDL_Event event;
278
279 while (1) {
280 SDL_WaitEvent(&event);
281 switch (event.type) {
282 case SDL_MOUSEBUTTONDOWN:
283 case SDL_JOYBUTTONDOWN:
284 case SDL_KEYDOWN:
285 return;
286 break;
287 case SDL_QUIT:
288 exit(0);
289 }
290 }
291 }
292
293
294
295 /**
296 * Create a delay of 'sec' seconds that can be cancelled by hitting any key
297 */
298 int
cancellable_delay(int sec)299 cancellable_delay(int sec)
300 {
301 int i;
302 SDL_Event event;
303
304 for (i = 0; i < sec * 100; i++) {
305 if (SDL_PollEvent(&event) && event.type == SDL_KEYDOWN)
306 return 1;
307
308 SDL_Delay(10);
309 }
310
311 return 0;
312 }
313
314
315