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