5 * Copyright (C) 2003, 2007, 2008, 2009 Thomas Perl <thp@thpinfo.com>
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,
44 /* IDs from the resource file */
45 #define START_BUTTON 1
46 #define CHECKBOX_FULLSCREEN 2
49 BOOL CALLBACK
ConfigDialogProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
51 static int checkbox_is_checked
;
55 EndDialog(hwndDlg
, IDCANCEL
);
60 EndDialog(hwndDlg
, (checkbox_is_checked
)?(IDYES
):(IDNO
));
63 EndDialog(hwndDlg
, IDCANCEL
);
65 case CHECKBOX_FULLSCREEN
:
66 checkbox_is_checked
^= 1;
78 int WINAPI
WinMain(HINSTANCE hInstance
, HINSTANCE hPrevInstance
,
79 LPSTR lpCmdLine
, int nCmdShow
) {
81 int main( int argc
, char** argv
) {
83 int i
, slide
, slide_direction
;
89 int sdl_flags
= SDL_SWSURFACE
;
90 int btn_hovering
= 0, btn_hovering_old
= 0;
92 bool mouse_pressed
= false;
94 bool benchmark
= false;
95 GameState
*current_game
= NULL
, *prepared_game
= NULL
;
97 MenuButton btn_back
= {
100 HEIGHT
-(MENU_OPTIONS_BORDER
+MENU_OPTIONS_BUTTON_HEIGHT
),
101 MENU_OPTIONS_BUTTON_WIDTH
, MENU_OPTIONS_BUTTON_HEIGHT
,
104 MenuButton btn_start
= {
106 WIDTH
-(MENU_OPTIONS_BORDER
+MENU_OPTIONS_BUTTON_WIDTH
),
107 HEIGHT
-(MENU_OPTIONS_BORDER
+MENU_OPTIONS_BUTTON_HEIGHT
),
108 MENU_OPTIONS_BUTTON_WIDTH
, MENU_OPTIONS_BUTTON_HEIGHT
,
111 MenuButton btn_court_change
= {
115 50, MENU_OPTIONS_BUTTON_HEIGHT
,
118 MenuButton btn_player1
= {
122 MENU_OPTIONS_BUTTON_WIDTH
, MENU_OPTIONS_BUTTON_HEIGHT
,
125 MenuButton btn_player2
= {
128 180+MENU_OPTIONS_BORDER
*2+MENU_OPTIONS_BUTTON_HEIGHT
,
129 MENU_OPTIONS_BUTTON_WIDTH
, MENU_OPTIONS_BUTTON_HEIGHT
,
133 const SDL_VideoInfo
* vi
= NULL
;
135 bool do_help
= false;
137 int state
= MENU_STATE_STARTED
;
139 #ifdef ENABLE_FPS_LIMIT
140 Uint32 ft
, frames
; /* frame timer and frames */
144 sdl_flags
|= SDL_FULLSCREEN
;
149 mb_result
= DialogBox(hInstance
, "CONFIG", 0, (DLGPROC
)ConfigDialogProc
);
153 sdl_flags
|= SDL_FULLSCREEN
;
162 fprintf(stderr
, "Tennix " VERSION
"\n" COPYRIGHT
"\n" URL
"\n\n");
166 /* A poor/lazy man's getopt */
167 #define OPTION_SET(longopt,shortopt) \
168 (strcmp(argv[i], longopt)==0 || strcmp(argv[i], shortopt)==0)
169 #define OPTION_VALUE \
170 ((i+1 < argc)?(argv[i+1]):(NULL))
171 #define OPTION_VALUE_PROCESSED \
173 if (OPTION_SET("--fullscreen", "-f")) {
174 sdl_flags
|= SDL_FULLSCREEN
;
176 else if (OPTION_SET("--help", "-h")) {
179 else if (OPTION_SET("--list-joysticks", "-J")) {
180 SDL_Init(SDL_INIT_JOYSTICK
);
184 else if (OPTION_SET("--benchmark", "-b")) {
187 else if (OPTION_SET("--joystick", "-j")) {
188 SDL_Init(SDL_INIT_JOYSTICK
);
189 if (OPTION_VALUE
== NULL
) {
190 fprintf(stderr
, "Error: You need to specify the name of the joystick as parameter.\n");
194 if (joystick_open(OPTION_VALUE
)==0) {
195 fprintf(stderr
, "Warning: Cannot find joystick \"%s\" - Ignored.\n", OPTION_VALUE
);
198 OPTION_VALUE_PROCESSED
;
201 fprintf(stderr
, "Ignoring unknown option: %s\n", argv
[i
]);
206 if (do_help
== true) {
207 fprintf(stderr
, "Usage: %s [--fullscreen|-f] [--help|-h] [--list-joysticks|-J] [--joystick|-j] [joystick name]\n", argv
[0]);
215 srand((unsigned)time(NULL
));
218 if (SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_JOYSTICK
) == -1) {
219 fprintf( stderr
, "Can't init SDL: %s\n", SDL_GetError());
223 vi
= SDL_GetVideoInfo();
224 if( (screen
= SDL_SetVideoMode( WIDTH
, HEIGHT
, vi
->vfmt
->BitsPerPixel
, sdl_flags
)) == NULL
) {
225 fprintf( stderr
, "Can't set video mode: %s\n", SDL_GetError());
229 SDL_WM_SetCaption( "Tennix " VERSION
, "Tennix");
230 SDL_ShowCursor( SDL_DISABLE
);
231 SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY
, 1);
237 #ifdef ENABLE_FPS_LIMIT
243 GameState
* g
= gamestate_new();
244 PLAYER(g
, 1).type
= PLAYER_TYPE_AI
;
245 PLAYER(g
, 2).type
= PLAYER_TYPE_AI
;
246 g
->timelimit
= BENCHMARK_TIMELIMIT
*1000;
253 /* Sliding initialization */
254 ticks
= SDL_GetTicks();
255 slide
= slide_start
= get_image_width(GR_SIDEBAR
);
258 /* State transitions */
260 case MENU_STATE_STARTED
:
261 state
= MENU_STATE_SLIDE_TO_MAINMENU
;
263 case MENU_STATE_SLIDE_TO_MAINMENU
:
265 slide_direction
= -1;
266 state
= MENU_STATE_SLIDE_TO_MAINMENU_IN_PROGRESS
;
268 case MENU_STATE_SLIDE_TO_MAINMENU_IN_PROGRESS
:
271 state
= MENU_STATE_MAINMENU
;
274 case MENU_STATE_MAINMENU
:
276 prepared_game
= NULL
;
278 case MENU_STATE_SLIDE_TO_OPTIONS
:
281 state
= MENU_STATE_SLIDE_TO_OPTIONS_IN_PROGRESS
;
283 case MENU_STATE_SLIDE_TO_OPTIONS_IN_PROGRESS
:
284 if (slide
== slide_start
) {
286 state
= MENU_STATE_OPTIONS
;
289 case MENU_STATE_OPTIONS
:
290 /* Prepare a new game */
291 if (prepared_game
== NULL
) {
292 prepared_game
= gamestate_new();
293 btn_player1
.text
= "Keyboard (W-S-D)";
294 btn_player2
.text
= "Computer (AI)";
297 case MENU_STATE_SLIDE_TO_GAME
:
300 state = MENU_STATE_SLIDE_TO_GAME_IN_PROGRESS;
302 case MENU_STATE_SLIDE_TO_GAME_IN_PROGRESS:
303 if (slide == slide_start) {
304 state = MENU_STATE_GAME;
306 state
= MENU_STATE_GAME
;
308 case MENU_STATE_SLIDE_TO_RESUME
:
311 state
= MENU_STATE_SLIDE_TO_RESUME_IN_PROGRESS
;
313 case MENU_STATE_SLIDE_TO_RESUME_IN_PROGRESS
:
314 if (slide
== slide_start
) {
315 state
= MENU_STATE_RESUME
;
318 case MENU_STATE_GAME
:
319 if (prepared_game
== NULL
) {
320 fprintf(stderr
, "Game not yet prepared!\n");
323 /* Cancel a possibly started game */
325 current_game
= prepared_game
;
326 prepared_game
= NULL
;
327 /* no break - we are continuing with "resume" */
328 case MENU_STATE_RESUME
:
329 if (current_game
== NULL
) {
330 fprintf(stderr
, "Cannot resume game!\n");
334 gameloop(current_game
);
336 while(SDL_PollEvent(&e
));
337 #ifdef ENABLE_FPS_LIMIT
342 state
= MENU_STATE_SLIDE_TO_MAINMENU
;
344 case MENU_STATE_SLIDE_TO_QUIT
:
347 state
= MENU_STATE_SLIDE_TO_QUIT_IN_PROGRESS
;
349 case MENU_STATE_SLIDE_TO_QUIT_IN_PROGRESS
:
350 if (slide
== slide_start
) {
351 state
= MENU_STATE_QUIT
;
354 case MENU_STATE_QUIT
:
358 fprintf(stderr
, "State error: %d\n", state
);
363 if (SDL_GetTicks() > ticks
+ 20) {
364 if (slide
>= 1 && slide
<= slide_start
) {
365 slide
+= slide_direction
+(slide_direction
*slide
/(sqrt(2*slide
)));
366 slide
= MAX(0, MIN(slide_start
, slide
));
367 } else if (slide_direction
!= 0) {
370 ticks
= SDL_GetTicks();
375 if (state
!= MENU_STATE_OPTIONS
) {
376 fill_image_offset(GR_FOG
, 0, 0, WIDTH
, HEIGHT
, -i
, 0);
379 show_image(GR_SIDEBAR
, WIDTH
-get_image_width(GR_SIDEBAR
)+slide
, 0, 255);
380 show_image(GR_TENNIXLOGO
, WIDTH
-get_image_width(GR_SIDEBAR
)-10, 20-slide
, 255);
381 if (state
!= MENU_STATE_OPTIONS
) {
383 show_image(GR_BTN_PLAY
, WIDTH
-get_image_width(GR_BTN_PLAY
)+slide
+(slide
/7)+3-(3*(btn_hovering
==MENU_START
)), 150, 255);
384 if (current_game
!= NULL
) {
385 show_image(GR_BTN_RESUME
, WIDTH
-get_image_width(GR_BTN_RESUME
)+slide
+(slide
/7)+3-(3*(btn_hovering
==MENU_RESUME
)), 230, 255);
386 font_draw_string(GR_DKC2_FONT
, "current match:", 10, 10, 0, 0);
387 font_draw_string(GR_DKC2_FONT
, current_game
->sets_score_str
, 10, 40, 0, 0);
389 font_draw_string(GR_DKC2_FONT
, "Tennix " VERSION
, 10, 10, 0, 0);
391 font_draw_string(GR_DKC2_FONT
, URL
, 10, HEIGHT
-10-get_image_height(GR_DKC2_FONT
), 0, 0);
392 show_image(GR_BTN_QUIT
, WIDTH
-get_image_width(GR_BTN_QUIT
)+slide
+(slide
/7)+3-(3*(btn_hovering
==MENU_QUIT
)), 350, 255);
395 show_image(GR_TENNIXLOGO
, WIDTH
-get_image_width(GR_SIDEBAR
)-10, 20, 255);
396 draw_button_object(btn_back
, mx
, my
);
397 draw_button_object(btn_start
, mx
, my
);
398 if (prepared_game
!= NULL
) {
399 fill_image(prepared_game
->court_type
, MENU_OPTIONS_BORDER
, MENU_OPTIONS_BORDER
*2, get_image_width(GR_STADIUM
), get_image_height(GR_STADIUM
));
400 show_image(GR_STADIUM
, MENU_OPTIONS_BORDER
, MENU_OPTIONS_BORDER
*2, 255);
401 draw_button_object(btn_court_change
, mx
, my
);
402 font_draw_string(GR_DKC2_FONT
, "Location", MENU_OPTIONS_BORDER
, MENU_OPTIONS_BORDER
, 0, 0);
403 draw_button_object(btn_player1
, mx
, my
);
404 draw_button_object(btn_player2
, mx
, my
);
405 font_draw_string(GR_DKC2_FONT
, "Player 1", btn_player1
.x
, btn_player1
.y
-MENU_OPTIONS_BORDER
, 0, 0);
406 font_draw_string(GR_DKC2_FONT
, "Player 2", btn_player2
.x
, btn_player2
.y
-MENU_OPTIONS_BORDER
, 0, 0);
411 if( e
.type
== SDL_QUIT
) {
412 state
= MENU_STATE_SLIDE_TO_QUIT
;
416 keys
= SDL_GetKeyState( NULL
);
417 mb
= SDL_GetMouseState( &mx
, &my
);
419 btn_hovering_old
= btn_hovering
;
420 if (state
== MENU_STATE_MAINMENU
) {
421 btn_hovering
= M_POS_DECODE(mx
, my
);
422 if (current_game
== NULL
) {
423 btn_hovering
&= ~MENU_RESUME
;
425 } else if (state
== MENU_STATE_OPTIONS
) {
426 if (M_POS_BUTTON(btn_back
, mx
, my
)) {
427 btn_hovering
= MENU_QUIT
;
428 } else if (M_POS_BUTTON(btn_start
, mx
, my
)) {
429 btn_hovering
= MENU_START
;
430 } else if (M_POS_BUTTON(btn_court_change
, mx
, my
)) {
431 btn_hovering
= MENU_COURT_CHANGE
;
432 } else if (M_POS_BUTTON(btn_player1
, mx
, my
)) {
433 btn_hovering
= MENU_PLAYER1
;
434 } else if (M_POS_BUTTON(btn_player2
, mx
, my
)) {
435 btn_hovering
= MENU_PLAYER2
;
440 /* No menu screen - no hovering. */
443 #ifndef MAEMO /* On Maemo, we cannot really "hover" (touchscreen!) */
444 if (btn_hovering_old
!= btn_hovering
&& btn_hovering
!= 0) {
445 #ifdef HAVE_VOICE_FILES
446 if (btn_hovering
== MENU_QUIT
) {
447 play_sample(VOICE_QUIT_IT
);
448 } else if (btn_hovering
== MENU_START
) {
449 play_sample(VOICE_NEW_GAME
);
451 play_sample(SOUND_MOUSEOVER
);
454 play_sample(SOUND_MOUSEOVER
);
459 if( keys
[SDLK_ESCAPE
] || keys
['q']) {
460 /* FIXME: do the state thingie! */
465 SDL_WM_ToggleFullScreen( screen
);
468 #ifndef MAEMO /* No mouse cursor on Maemo (we have a touchscreen) */
469 if (state
== MENU_STATE_MAINMENU
|| state
== MENU_STATE_OPTIONS
) {
470 show_sprite( GR_RACKET
, ((mb
&SDL_BUTTON( SDL_BUTTON_LEFT
))>0)+(((mb
&SDL_BUTTON( SDL_BUTTON_RIGHT
))>0)*2), 4, mx
, my
, 255);
474 /* Draw the "real" mouse coordinates */
475 /*rectangle(mx-1, my-1, 2, 2, 255, 255, 255);*/
477 /* Store the screen, because we are fading after this screen update */
478 /*if (!(mb & SDL_BUTTON(SDL_BUTTON_LEFT)) && btn_hovering != MENU_NONE && mouse_pressed == true) store_screen();*/
482 if( mb
& SDL_BUTTON(SDL_BUTTON_LEFT
)) {
483 mouse_pressed
= true;
484 } else if (mouse_pressed
== true) {
485 /* Mouse button released */
486 if (state
== MENU_STATE_MAINMENU
|| state
== MENU_STATE_OPTIONS
) {
487 #ifdef HAVE_VOICE_FILES
488 if (btn_hovering
== MENU_START
) {
489 play_sample(VOICE_LETS_GO
);
491 play_sample(SOUND_MOUSECLICK
);
494 play_sample(SOUND_MOUSECLICK
);
497 if (state
== MENU_STATE_MAINMENU
) {
498 switch (btn_hovering
) {
500 state
= MENU_STATE_SLIDE_TO_OPTIONS
;
503 state
= MENU_STATE_SLIDE_TO_RESUME
;
506 state
= MENU_STATE_SLIDE_TO_QUIT
;
509 } else if (state
== MENU_STATE_OPTIONS
) {
510 switch (btn_hovering
) {
512 state
= MENU_STATE_SLIDE_TO_GAME
;
515 state
= MENU_STATE_SLIDE_TO_MAINMENU
;
517 case MENU_COURT_CHANGE
:
518 prepared_game
->court_type
++;
519 if (prepared_game
->court_type
> GR_CTT_LAST
) {
520 prepared_game
->court_type
= GR_CTT_FIRST
;
524 switch (PLAYER(prepared_game
, 1).type
) {
525 case PLAYER_TYPE_HUMAN
:
526 PLAYER(prepared_game
, 1).type
= PLAYER_TYPE_AI
;
527 btn_player1
.text
= "Computer (AI)";
530 PLAYER(prepared_game
, 1).type
= PLAYER_TYPE_HUMAN
;
531 btn_player1
.text
= "Keyboard (W-S-D)";
536 switch (PLAYER(prepared_game
, 2).type
) {
537 case PLAYER_TYPE_HUMAN
:
538 PLAYER(prepared_game
, 2).type
= PLAYER_TYPE_AI
;
539 btn_player2
.text
= "Computer (AI)";
542 PLAYER(prepared_game
, 2).type
= PLAYER_TYPE_HUMAN
;
543 btn_player2
.text
= "Keyboard (O-L-K)";
549 mouse_pressed
= false;
552 #ifdef ENABLE_FPS_LIMIT
553 while (frames
*1000.0/((float)(SDL_GetTicks()-ft
+1))>(float)(DEFAULT_FPS
)) {