New input system with automatic joystick detection
[tennix.git] / tennix.c
blobdae89ec48b6abc1327e3721860795655e11fbd0c
2 /**
4 * Tennix! SDL Port
5 * Copyright (C) 2003, 2007, 2008, 2009 Thomas Perl <thp@thpinfo.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
22 **/
24 #include <stdio.h>
25 #include <time.h>
26 #include <libgen.h>
27 #include <string.h>
28 #include <stdlib.h>
30 #ifdef WIN32
31 #include <windows.h>
32 #endif
34 #include "tennix.h"
35 #include "game.h"
36 #include "graphics.h"
37 #include "sound.h"
38 #include "input.h"
39 #include "util.h"
41 #include "locations.h"
43 SDL_Surface *screen;
45 #ifdef WIN32
47 /* IDs from the resource file */
48 #define START_BUTTON 1
49 #define CHECKBOX_FULLSCREEN 2
50 #define QUIT_BUTTON 3
52 BOOL CALLBACK ConfigDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
54 static int checkbox_is_checked;
56 switch (uMsg) {
57 case WM_CLOSE:
58 EndDialog(hwndDlg, IDCANCEL);
59 break;
60 case WM_COMMAND:
61 switch (wParam) {
62 case START_BUTTON:
63 EndDialog(hwndDlg, (checkbox_is_checked)?(IDYES):(IDNO));
64 break;
65 case QUIT_BUTTON:
66 EndDialog(hwndDlg, IDCANCEL);
67 break;
68 case CHECKBOX_FULLSCREEN:
69 checkbox_is_checked ^= 1;
70 break;
72 break;
73 default:
74 return FALSE;
76 return TRUE;
78 #endif
80 #ifdef WIN32
81 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
82 LPSTR lpCmdLine, int nCmdShow) {
83 #else
84 int main( int argc, char** argv) {
85 #endif
86 int i, slide, slide_direction;
87 unsigned int x;
88 Uint32 ticks;
89 int mx, my;
90 unsigned int worldmap_xpos, worldmap_ypos;
91 Uint8 *keys;
92 Uint8 mb;
93 SDL_Event e;
94 int sdl_flags = SDL_SWSURFACE;
95 int btn_hovering = 0, btn_hovering_old = 0;
96 int slide_start;
97 bool mouse_pressed = false;
98 bool quit = false;
99 bool benchmark = false;
100 unsigned int night_start, night_end;
101 GameState *current_game = NULL, *prepared_game = NULL;
102 InputDevice* input_devices;
103 unsigned int input_device_count;
105 MenuButton btn_back = {
106 "Back to main menu",
107 MENU_OPTIONS_BORDER,
108 HEIGHT-(MENU_OPTIONS_BORDER+MENU_OPTIONS_BUTTON_HEIGHT),
109 MENU_OPTIONS_BUTTON_WIDTH, MENU_OPTIONS_BUTTON_HEIGHT,
110 255, 0, 0
112 MenuButton btn_start = {
113 "Start new game",
114 WIDTH-(MENU_OPTIONS_BORDER+MENU_OPTIONS_BUTTON_WIDTH),
115 HEIGHT-(MENU_OPTIONS_BORDER+MENU_OPTIONS_BUTTON_HEIGHT),
116 MENU_OPTIONS_BUTTON_WIDTH, MENU_OPTIONS_BUTTON_HEIGHT,
117 0, 255, 0
119 MenuButton btn_player1 = {
120 NULL,
121 WIDTH/2-150,
122 180,
123 300, MENU_OPTIONS_BUTTON_HEIGHT,
124 50, 50, 255
126 MenuButton btn_player2 = {
127 NULL,
128 WIDTH/2-150,
129 180+MENU_OPTIONS_BORDER*2+MENU_OPTIONS_BUTTON_HEIGHT,
130 300, MENU_OPTIONS_BUTTON_HEIGHT,
131 255, 50, 50
134 int current_location = -1;
135 int highlight_location = -1;
136 float highlight_location_distance = 0.0;
137 float new_location_distance = 0.0;
138 bool location_info_visible = false;
139 unsigned int location_info_xpos = 0, location_info_ypos = 0;
141 const SDL_VideoInfo* vi = NULL;
143 bool do_help = false;
145 int state = MENU_STATE_STARTED;
147 #ifdef ENABLE_FPS_LIMIT
148 Uint32 ft, frames; /* frame timer and frames */
149 #endif
151 #ifdef MAEMO
152 sdl_flags |= SDL_FULLSCREEN;
153 #endif
155 #ifdef WIN32
156 int mb_result;
157 mb_result = DialogBox(hInstance, "CONFIG", 0, (DLGPROC)ConfigDialogProc);
159 switch (mb_result) {
160 case IDYES:
161 sdl_flags |= SDL_FULLSCREEN;
162 break;
163 case IDCANCEL:
164 return 0;
165 break;
166 default:
167 break;
169 #else
170 fprintf(stderr, "Tennix " VERSION "\n" COPYRIGHT "\n" URL "\n\n");
172 i = 1;
173 while (i < argc) {
174 /* A poor/lazy man's getopt */
175 #define OPTION_SET(longopt,shortopt) \
176 (strcmp(argv[i], longopt)==0 || strcmp(argv[i], shortopt)==0)
177 #define OPTION_VALUE \
178 ((i+1 < argc)?(argv[i+1]):(NULL))
179 #define OPTION_VALUE_PROCESSED \
180 (i++)
181 if (OPTION_SET("--fullscreen", "-f")) {
182 sdl_flags |= SDL_FULLSCREEN;
184 else if (OPTION_SET("--help", "-h")) {
185 do_help = true;
187 else if (OPTION_SET("--benchmark", "-b")) {
188 benchmark = true;
190 else {
191 fprintf(stderr, "Ignoring unknown option: %s\n", argv[i]);
193 i++;
196 if (do_help == true) {
197 fprintf(stderr, "Usage: %s [--fullscreen|-f] [--help|-h]\n", argv[0]);
198 return 0;
200 #endif
202 if (benchmark) {
203 srand(100);
204 } else {
205 srand((unsigned)time(NULL));
208 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) == -1) {
209 fprintf( stderr, "Can't init SDL: %s\n", SDL_GetError());
210 exit( 1);
213 vi = SDL_GetVideoInfo();
214 if( (screen = SDL_SetVideoMode( WIDTH, HEIGHT, vi->vfmt->BitsPerPixel, sdl_flags)) == NULL) {
215 fprintf( stderr, "Can't set video mode: %s\n", SDL_GetError());
216 exit( 1);
219 SDL_WM_SetCaption( "Tennix " VERSION, "Tennix");
220 SDL_ShowCursor( SDL_DISABLE);
221 SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, 1);
223 init_graphics();
224 init_sound();
225 init_input();
227 input_devices = find_input_devices(&input_device_count);
229 #ifdef ENABLE_FPS_LIMIT
230 frames = 0;
231 ft = SDL_GetTicks();
232 #endif
234 if (benchmark) {
235 GameState* g = gamestate_new();
236 PLAYER(g, 1).type = PLAYER_TYPE_AI;
237 PLAYER(g, 2).type = PLAYER_TYPE_AI;
238 g->timelimit = BENCHMARK_TIMELIMIT*1000;
239 g->location = &(locations[0]);
240 gameloop(g);
241 free(g);
242 exit(0);
245 worldmap_xpos = (WIDTH-get_image_width(GR_WORLDMAP))/2;
246 worldmap_ypos = (HEIGHT-get_image_height(GR_WORLDMAP))/2;
248 i = 0;
249 /* Sliding initialization */
250 ticks = SDL_GetTicks();
251 slide = slide_start = get_image_width(GR_SIDEBAR);
252 slide_direction = 0;
253 while(!quit) {
254 /* State transitions */
255 switch (state) {
256 case MENU_STATE_STARTED:
257 state = MENU_STATE_SLIDE_TO_MAINMENU;
258 break;
259 case MENU_STATE_SLIDE_TO_MAINMENU:
260 clear_screen();
261 store_screen();
262 slide = slide_start;
263 slide_direction = -1;
264 state = MENU_STATE_SLIDE_TO_MAINMENU_IN_PROGRESS;
265 break;
266 case MENU_STATE_SLIDE_TO_MAINMENU_IN_PROGRESS:
267 if (slide == 0) {
268 slide_direction = 0;
269 state = MENU_STATE_MAINMENU;
271 break;
272 case MENU_STATE_MAINMENU:
273 free(prepared_game);
274 prepared_game = NULL;
275 break;
276 case MENU_STATE_SLIDE_TO_LOCATION:
277 slide = 1;
278 slide_direction = 3;
279 state = MENU_STATE_SLIDE_TO_LOCATION_IN_PROGRESS;
280 break;
281 case MENU_STATE_SLIDE_TO_LOCATION_IN_PROGRESS:
282 if (slide == slide_start) {
283 state = MENU_STATE_FADE_TO_LOCATION;
285 break;
286 case MENU_STATE_FADE_TO_LOCATION:
287 start_fade();
288 state = MENU_STATE_LOCATION;
289 clear_screen();
291 /* Draw and store the worldmap with day/night times */
292 show_image(GR_WORLDMAP, WIDTH/2-get_image_width(GR_WORLDMAP)/2, HEIGHT/2-get_image_height(GR_WORLDMAP)/2, 255);
293 day_night(get_image_width(GR_WORLDMAP), &night_start, &night_end);
294 if (night_start > night_end) {
295 rectangle_alpha(worldmap_xpos, worldmap_ypos, night_end, get_image_height(GR_WORLDMAP), 0, 0, 0, 150);
296 rectangle_alpha(worldmap_xpos+night_start, worldmap_ypos, get_image_width(GR_WORLDMAP)-night_start, 10, 0, 0, 0, 150);
297 } else {
298 rectangle_alpha(worldmap_xpos+night_start, worldmap_ypos, night_end-night_start, get_image_height(GR_WORLDMAP), 0, 0, 0, 150);
301 /* add misc items to screen */
302 show_image(GR_TENNIXLOGO, WIDTH-get_image_width(GR_SIDEBAR)-10, 20, 255);
303 font_draw_string(GR_DKC2_FONT, "Where do you want to play?", MENU_OPTIONS_BORDER, MENU_OPTIONS_BORDER, 0, 0);
305 store_screen();
306 break;
307 case MENU_STATE_FADE_TO_OPTIONS:
308 clear_screen();
309 store_screen();
310 start_fade();
311 state = MENU_STATE_OPTIONS;
312 break;
313 case MENU_STATE_LOCATION:
314 case MENU_STATE_OPTIONS:
315 /* Prepare a new game */
316 if (prepared_game == NULL) {
317 prepared_game = gamestate_new();
318 prepared_game->location = NULL;
319 btn_player1.text = "computer (AI)";
320 btn_player2.text = "computer (AI)";
321 location_info_visible = false;
322 current_location = -1;
323 highlight_location = -1;
325 break;
326 case MENU_STATE_SLIDE_TO_GAME:
327 /*slide = 1;
328 slide_direction = 2;
329 state = MENU_STATE_SLIDE_TO_GAME_IN_PROGRESS;
330 break;
331 case MENU_STATE_SLIDE_TO_GAME_IN_PROGRESS:
332 if (slide == slide_start) {
333 state = MENU_STATE_GAME;
335 state = MENU_STATE_GAME;
336 break;
337 case MENU_STATE_SLIDE_TO_RESUME:
338 slide = 1;
339 slide_direction = 2;
340 state = MENU_STATE_SLIDE_TO_RESUME_IN_PROGRESS;
341 break;
342 case MENU_STATE_SLIDE_TO_RESUME_IN_PROGRESS:
343 if (slide == slide_start) {
344 state = MENU_STATE_RESUME;
346 break;
347 case MENU_STATE_GAME:
348 if (prepared_game == NULL) {
349 fprintf(stderr, "Game not yet prepared!\n");
350 exit(EXIT_FAILURE);
352 /* Set the day/night status */
353 if (night_start < night_end) {
354 prepared_game->night = (prepared_game->location->worldmap_x > night_start && prepared_game->location->worldmap_x < night_end);
355 } else {
356 prepared_game->night = (prepared_game->location->worldmap_x < night_end || prepared_game->location->worldmap_x > night_start);
359 /* Cancel a possibly started game */
360 free(current_game);
361 current_game = prepared_game;
362 prepared_game = NULL;
363 /* no break - we are continuing with "resume" */
364 case MENU_STATE_RESUME:
365 if (current_game == NULL) {
366 fprintf(stderr, "Cannot resume game!\n");
367 exit(EXIT_FAILURE);
369 start_fade();
370 gameloop(current_game);
371 SDL_Delay(150);
372 while(SDL_PollEvent(&e));
373 #ifdef ENABLE_FPS_LIMIT
374 frames = 0;
375 ft = SDL_GetTicks();
376 #endif
377 start_fade();
378 state = MENU_STATE_SLIDE_TO_MAINMENU;
379 break;
380 case MENU_STATE_SLIDE_TO_QUIT:
381 slide = 1;
382 slide_direction = 3;
383 state = MENU_STATE_SLIDE_TO_QUIT_IN_PROGRESS;
384 break;
385 case MENU_STATE_SLIDE_TO_QUIT_IN_PROGRESS:
386 if (slide == slide_start) {
387 state = MENU_STATE_QUIT;
389 break;
390 case MENU_STATE_QUIT:
391 quit = true;
392 break;
393 default:
394 fprintf(stderr, "State error: %d\n", state);
395 exit(EXIT_FAILURE);
398 /* Sliding */
399 if (SDL_GetTicks() > ticks + 20) {
400 if (slide >= 1 && slide <= slide_start) {
401 slide += slide_direction+(slide_direction*slide/(sqrt(2*slide)));
402 slide = MAX(0, MIN(slide_start, slide));
403 } else if (slide_direction != 0) {
404 slide_direction = 0;
406 ticks = SDL_GetTicks();
409 /* Graphics */
410 #ifdef DEBUG
411 if (state != MENU_STATE_OPTIONS) {
412 fill_image_offset(GR_FOG, 0, 0, WIDTH, HEIGHT, -i, 0);
414 #endif
415 show_image(GR_SIDEBAR, WIDTH-get_image_width(GR_SIDEBAR)+slide, 0, 255);
416 show_image(GR_TENNIXLOGO, WIDTH-get_image_width(GR_SIDEBAR)-10, 20-slide, 255);
417 if (state != MENU_STATE_OPTIONS && state != MENU_STATE_LOCATION) {
418 /* Main Menu */
419 show_image(GR_BTN_PLAY, WIDTH-get_image_width(GR_BTN_PLAY)+slide+(slide/7)+3-(3*(btn_hovering==MENU_START)), 150, 255);
420 if (current_game != NULL) {
421 show_image(GR_BTN_RESUME, WIDTH-get_image_width(GR_BTN_RESUME)+slide+(slide/7)+3-(3*(btn_hovering==MENU_RESUME)), 230, 255);
422 font_draw_string(GR_DKC2_FONT, "current match:", 10, 10, 0, 0);
423 font_draw_string(GR_DKC2_FONT, current_game->sets_score_str, 10, 40, 0, 0);
424 } else {
425 font_draw_string(GR_DKC2_FONT, "Tennix " VERSION, 10, 10, 0, 0);
427 font_draw_string(GR_DKC2_FONT, URL, 10, HEIGHT-10-get_image_height(GR_DKC2_FONT), 0, 0);
428 show_image(GR_BTN_QUIT, WIDTH-get_image_width(GR_BTN_QUIT)+slide+(slide/7)+3-(3*(btn_hovering==MENU_QUIT)), 350, 255);
429 } else if (state == MENU_STATE_OPTIONS) {
430 /* Options screen */
431 show_image(GR_TENNIXLOGO, WIDTH-get_image_width(GR_SIDEBAR)-10, 20, 255);
432 draw_button_object(btn_back, mx, my);
433 draw_button_object(btn_start, mx, my);
434 draw_button_object(btn_player1, mx, my);
435 draw_button_object(btn_player2, mx, my);
436 font_draw_string(GR_DKC2_FONT, "Player 1", btn_player1.x, btn_player1.y-MENU_OPTIONS_BORDER, 0, 0);
437 font_draw_string(GR_DKC2_FONT, "Player 2", btn_player2.x, btn_player2.y-MENU_OPTIONS_BORDER, 0, 0);
438 } else if (state == MENU_STATE_LOCATION) {
439 /* Location selection screen */
440 for (x=0; x<location_count(); x++) {
441 new_location_distance = SQUARE_DISTANCE(mx-worldmap_xpos-locations[x].worldmap_x,
442 my-worldmap_ypos-locations[x].worldmap_y);
443 if (highlight_location == -1) {
444 if (new_location_distance < 20*20) {
445 highlight_location = x;
447 } else {
448 highlight_location_distance = SQUARE_DISTANCE(mx-worldmap_xpos-locations[highlight_location].worldmap_x,
449 my-worldmap_ypos-locations[highlight_location].worldmap_y);
450 if (highlight_location_distance > 20*20) {
451 highlight_location = -1;
453 if (highlight_location_distance > new_location_distance && new_location_distance < 20*20) {
454 highlight_location = x;
458 if (!location_info_visible) {
459 for (x=0; x<location_count(); x++) {
460 /* draw rectangle for location at "x"*/
461 if (highlight_location != -1 && (unsigned int)highlight_location == x) {
462 rectangle(worldmap_xpos + locations[x].worldmap_x-3, worldmap_ypos + locations[x].worldmap_y-3, 7, 7, 255*((i/10)%2), 0, 255*((i/10)%2));
465 rectangle(worldmap_xpos + locations[x].worldmap_x-2, worldmap_ypos + locations[x].worldmap_y-2, 5, 5, 255, 255*(current_location != -1 && x==(unsigned int)current_location), 0);
468 if (prepared_game != NULL) {
469 if (location_info_visible) {
470 show_sprite(prepared_game->location->photo, (i/1000)%(prepared_game->location->photo_frames), prepared_game->location->photo_frames, location_info_xpos, location_info_ypos, 255);
471 font_draw_string(GR_DKC2_FONT, prepared_game->location->name, location_info_xpos+MENU_OPTIONS_BORDER, location_info_ypos+MENU_OPTIONS_BORDER+200, 0, 0);
472 font_draw_string(GR_DKC2_FONT, prepared_game->location->area, location_info_xpos+MENU_OPTIONS_BORDER, location_info_ypos+MENU_OPTIONS_BORDER+200+get_image_height(GR_DKC2_FONT), 0, 0);
473 font_draw_string(GR_DKC2_FONT, prepared_game->location->city, location_info_xpos+MENU_OPTIONS_BORDER, location_info_ypos+MENU_OPTIONS_BORDER+200+2*get_image_height(GR_DKC2_FONT), 0, 0);
474 font_draw_string(GR_DKC2_FONT, prepared_game->location->court_type_name, location_info_xpos+MENU_OPTIONS_BORDER, location_info_ypos+MENU_OPTIONS_BORDER+200+4*get_image_height(GR_DKC2_FONT), 0, 0);
476 if (prepared_game->location != NULL) {
477 draw_button_object(btn_start, mx, my);
480 draw_button_object(btn_back, mx, my);
483 SDL_PollEvent( &e);
484 if( e.type == SDL_QUIT) {
485 state = MENU_STATE_SLIDE_TO_QUIT;
486 /*break;*/
489 keys = SDL_GetKeyState( NULL);
490 mb = SDL_GetMouseState( &mx, &my);
492 btn_hovering_old = btn_hovering;
493 if (state == MENU_STATE_MAINMENU) {
494 btn_hovering = M_POS_DECODE(mx, my);
495 if (current_game == NULL) {
496 btn_hovering &= ~MENU_RESUME;
498 } else if (state == MENU_STATE_LOCATION) {
499 if (M_POS_BUTTON(btn_back, mx, my)) {
500 btn_hovering = MENU_QUIT;
501 } else if (M_POS_BUTTON(btn_start, mx, my)) {
502 btn_hovering = MENU_START;
503 } else {
504 btn_hovering = 0;
506 } else if (state == MENU_STATE_OPTIONS) {
507 if (M_POS_BUTTON(btn_back, mx, my)) {
508 btn_hovering = MENU_QUIT;
509 } else if (M_POS_BUTTON(btn_start, mx, my)) {
510 btn_hovering = MENU_START;
511 } else if (M_POS_BUTTON(btn_player1, mx, my)) {
512 btn_hovering = MENU_PLAYER1;
513 } else if (M_POS_BUTTON(btn_player2, mx, my)) {
514 btn_hovering = MENU_PLAYER2;
515 } else {
516 btn_hovering = 0;
518 } else {
519 /* No menu screen - no hovering. */
520 btn_hovering = 0;
522 #ifndef MAEMO /* On Maemo, we cannot really "hover" (touchscreen!) */
523 if (btn_hovering_old != btn_hovering && btn_hovering != 0) {
524 #ifdef HAVE_VOICE_FILES
525 if (btn_hovering == MENU_QUIT) {
526 play_sample(VOICE_QUIT_IT);
527 } else if (btn_hovering == MENU_START) {
528 play_sample(VOICE_NEW_GAME);
529 } else {
530 play_sample(SOUND_MOUSEOVER);
532 #else
533 play_sample(SOUND_MOUSEOVER);
534 #endif
536 #endif
538 if( keys[SDLK_ESCAPE] || keys['q']) {
539 /* FIXME: do the state thingie! */
540 break;
543 if( keys['f']) {
544 SDL_WM_ToggleFullScreen( screen);
547 #ifndef MAEMO /* No mouse cursor on Maemo (we have a touchscreen) */
548 if (state == MENU_STATE_MAINMENU || state == MENU_STATE_OPTIONS || state == MENU_STATE_LOCATION) {
549 show_image(GR_CURSOR, mx-2, my-1, 255);
551 #endif
553 /* Draw the "real" mouse coordinates */
554 /*rectangle(mx-1, my-1, 2, 2, 255, 255, 255);*/
556 /* Store the screen, because we are fading after this screen update */
557 /*if (!(mb & SDL_BUTTON(SDL_BUTTON_LEFT)) && btn_hovering != MENU_NONE && mouse_pressed == true) store_screen();*/
559 updatescr();
561 if( mb & SDL_BUTTON(SDL_BUTTON_LEFT)) {
562 mouse_pressed = true;
563 } else if (mouse_pressed == true) {
564 /* Mouse button released */
565 if (state == MENU_STATE_MAINMENU || state == MENU_STATE_OPTIONS || state == MENU_STATE_LOCATION) {
566 #ifdef HAVE_VOICE_FILES
567 if (btn_hovering == MENU_START) {
568 play_sample(VOICE_LETS_GO);
569 } else {
570 play_sample(SOUND_MOUSECLICK);
572 #else
573 play_sample(SOUND_MOUSECLICK);
574 #endif
576 if (state == MENU_STATE_MAINMENU) {
577 switch (btn_hovering) {
578 case MENU_START:
579 state = MENU_STATE_SLIDE_TO_LOCATION;
580 break;
581 case MENU_RESUME:
582 state = MENU_STATE_SLIDE_TO_RESUME;
583 break;
584 case MENU_QUIT:
585 state = MENU_STATE_SLIDE_TO_QUIT;
586 break;
588 } else if (state == MENU_STATE_LOCATION) {
589 switch (btn_hovering) {
590 case MENU_START:
591 if (prepared_game->location != NULL) {
592 state = MENU_STATE_FADE_TO_OPTIONS;
594 break;
595 case MENU_QUIT:
596 state = MENU_STATE_SLIDE_TO_MAINMENU;
597 break;
598 default:
599 if (!location_info_visible && highlight_location != -1) {
600 current_location = highlight_location;
601 prepared_game->location = &(locations[current_location]);
602 location_info_xpos = MAX(0, MIN(WIDTH-320-50, mx-320/2));
603 location_info_ypos = MAX(0, MIN(HEIGHT-200-160, my-200/2));
604 location_info_visible = true;
605 } else {
606 location_info_visible = false;
607 current_location = -1;
608 highlight_location = -1;
609 prepared_game->location = NULL;
611 break;
613 } else if (state == MENU_STATE_OPTIONS) {
614 switch (btn_hovering) {
615 case MENU_START:
616 state = MENU_STATE_SLIDE_TO_GAME;
617 break;
618 case MENU_QUIT:
619 state = MENU_STATE_FADE_TO_LOCATION;
620 break;
621 case MENU_PLAYER1:
622 /* advance the input device index */
623 PLAYER(prepared_game, 1).input_device_index++;
624 if (PLAYER(prepared_game, 1).input_device_index == (signed int)input_device_count) {
625 PLAYER(prepared_game, 1).input_device_index = -1;
628 /* determine the selected input device */
629 if (PLAYER(prepared_game, 1).input_device_index == -1) {
630 PLAYER(prepared_game, 1).type = PLAYER_TYPE_AI;
631 PLAYER(prepared_game, 1).input = NULL;
632 btn_player1.text = "Computer (AI)";
633 } else {
634 PLAYER(prepared_game, 1).type = PLAYER_TYPE_HUMAN;
635 PLAYER(prepared_game, 1).input = &(input_devices[PLAYER(prepared_game, 1).input_device_index]);
636 btn_player1.text = input_device_get_name(PLAYER(prepared_game, 1).input);
638 break;
639 case MENU_PLAYER2:
640 /* advance the input device index */
641 PLAYER(prepared_game, 2).input_device_index++;
642 if (PLAYER(prepared_game, 2).input_device_index == (signed int)input_device_count) {
643 PLAYER(prepared_game, 2).input_device_index = -1;
646 /* determine the selected input device */
647 if (PLAYER(prepared_game, 2).input_device_index == -1) {
648 PLAYER(prepared_game, 2).type = PLAYER_TYPE_AI;
649 PLAYER(prepared_game, 2).input = NULL;
650 btn_player2.text = "Computer (AI)";
651 } else {
652 PLAYER(prepared_game, 2).type = PLAYER_TYPE_HUMAN;
653 PLAYER(prepared_game, 2).input = &(input_devices[PLAYER(prepared_game, 2).input_device_index]);
654 btn_player2.text = input_device_get_name(PLAYER(prepared_game, 2).input);
656 break;
659 mouse_pressed = false;
661 i++;
662 #ifdef ENABLE_FPS_LIMIT
663 while (frames*1000.0/((float)(SDL_GetTicks()-ft+1))>(float)(DEFAULT_FPS)) {
664 SDL_Delay(10);
666 frames++;
667 #endif
670 uninit_graphics();
671 uninit_input();
673 SDL_Quit();
674 return 0;