Yet another huge code merge representing the current status of my rewrite. It include...
[supertux.git] / src / menu.c
1 /*
2   menu.c
3   
4   Super Tux - Menu
5   
6   by Tobias Glaesser
7   tobi.web@gmx.de
8   http://www.newbreedsoftware.com/supertux/
9   
10   December 20, 2003 - December 30, 2003
11 */
12
13 #ifdef LINUX
14 #include <pwd.h>
15 #include <sys/types.h>
16 #include <ctype.h>
17 #endif
18
19 #include <string.h>
20
21 #include "defines.h"
22 #include "globals.h"
23 #include "menu.h"
24 #include "screen.h"
25 #include "setup.h"
26 #include "sound.h"
27 #include "leveleditor.h"
28 #include "gameloop.h"
29 #include "timer.h"
30 #include "high_scores.h"
31
32 /* Set defaults */
33 void initmenu(void)
34 {
35   menu_change = NO;
36   show_menu = NO;
37   menuitem = 0;
38   menumenu = 0;
39   menuaction = -1;
40
41   delete_character = 0;
42   strcpy(input_string, "");
43 }
44
45 /* ---- Menu Options - Item Sound On/off ----*/
46 void menu_option_sound()
47 {
48   if (audio_device == YES)
49     {
50       if(menuitem == 1)
51         {
52           if(use_sound == YES)
53             {
54             text_drawf(&red_text, "Sound ON", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
55             }
56           else
57             {
58             text_drawf(&red_text, "Sound OFF", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
59             }
60
61           if(menuaction == MN_HIT)
62             { /* Disable/Enable sound */
63               if(use_sound == YES)
64                 {
65                   use_sound = NO;
66                 }
67               else
68                 {
69                   use_sound = YES;
70                 }
71               menu_change = YES;
72             }
73         }
74       else
75         {
76           if(use_sound == YES)
77             text_drawf(&blue_text, "Sound ON", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
78           else
79             text_drawf(&blue_text, "Sound OFF", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
80         }
81     }
82   else
83     { /* if audio_device != YES */
84       /* let the user move over the deactivated option */
85       if (menuitem == 1)
86         {
87           text_drawf(&red_text, "Sound OFF", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
88         }
89       else
90         {
91           text_drawf(&red_text, "Sound OFF", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
92         }
93     }
94 }
95
96
97 /* ---- Menu Options - Item Music On/off ----*/
98 void menu_option_music()
99 {
100   if (audio_device == YES)
101     {
102       if(menuitem == 2)
103         {
104           if(use_music == YES)
105             {
106               text_drawf(&red_text, "Music ON", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
107             }
108           else
109             {
110               text_drawf(&red_text, "Music OFF", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
111             }
112           if(menuaction == MN_HIT)
113             { /* Disable/Enable music */
114               if(use_music == YES)
115                 {  /* In the menu no music is played, so we have to check only use_music */
116                   if(playing_music())
117                     halt_music();
118                   use_music = NO;
119                 }
120               else
121                 {
122                   use_music = YES;
123                   if (!playing_music())
124                     {
125                       play_current_music();
126                     }
127                 }
128               menu_change = YES;
129             }
130         } /* if menuitem != 2 : print normal blue font */
131       else
132         {
133           if(use_music == YES)
134             {
135               text_drawf(&blue_text, "Music ON", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
136             }
137           else
138             {
139               text_drawf(&blue_text, "Music OFF", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
140             }
141         }
142     }
143   else
144     { /* if audio_device != YES */
145       /* let the user move over the deactivated option */
146       if (menuitem == 2)
147         {
148           text_drawf(&red_text, "Music OFF", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
149         }
150       else
151         {
152           text_drawf(&black_text, "Music OFF", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
153         }
154     }
155 }
156
157 int menu_main(void)
158 {
159   /* Does the menu item exist? If not, we reset to the most down item */
160   if(menuitem > MENU_MAIN_ITEM_MAX)
161     menuitem =0;
162   else if(menuitem < 0)
163     menuitem = MENU_MAIN_ITEM_MAX;
164
165   /*The menu looks different, when the game is started */
166   if(menuitem == 0)
167     {
168       text_drawf(&red_text, "Start Game", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
169       if(menuaction == MN_HIT) /* we are ready to start the game, if this item got hit */
170         {
171           game_started = 1;
172           show_menu = 0;
173         }
174     }
175   else
176     text_drawf(&blue_text, "Start Game", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
177
178   if(menuitem == 1)
179     {
180           text_drawf(&red_text, "Options", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
181       if(menuaction == MN_HIT) /* Switch to the 'Options' menu */
182         {
183           menumenu = MENU_OPTIONS;
184           menu_change = YES;
185         }
186     }
187   else
188         text_drawf(&blue_text, "Options", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
189
190   if(menuitem == 2)
191     {
192           text_drawf(&red_text, "Level editor", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
193       if(menuaction == MN_HIT) /* Set variables, so that the level editor is executed */
194         {
195           level_editor_started = YES;
196           show_menu = 0;
197         }
198     }
199   else
200           text_drawf(&blue_text, "Level editor", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
201
202   if(menuitem == 3)
203     {
204           text_drawf(&red_text, "Quit", 0, 288, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
205       if(menuaction == MN_HIT) /* Quit a running game or the application */
206         {
207           return 1;
208         }
209     }
210   else
211     {
212               text_drawf(&blue_text, "Quit", 0, 288, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
213     }
214
215   return 0;
216 }
217
218 int menu_game(void)
219 {
220   /* Does the menu item exist? If not, we reset to the most down item */
221   if(menuitem > MENU_GAME_ITEM_MAX)
222     menuitem = 0;
223   else if(menuitem < 0)
224     menuitem = MENU_GAME_ITEM_MAX;
225
226   /*The menu looks different, when the game is started */
227   if(menuitem == 0)
228     {
229           text_drawf(&red_text, "Return To Game", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
230       if(menuaction == MN_HIT) /* Don't show the menu anymore, if this item got hit */
231         {
232           show_menu = 0;
233           st_pause_ticks_stop();
234         }
235     }
236   else
237           text_drawf(&blue_text, "Return To Game", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
238
239   if(menuitem == 1)
240     {
241           text_drawf(&red_text, "Save Game", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
242       if(menuaction == MN_HIT) /* Don't show the menu anymore, if this item got hit */
243         {
244           show_menu = 0;
245           savegame();
246         }
247     }
248   else
249   text_drawf(&blue_text, "Save Game", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
250
251   if(menuitem == 2)
252     {
253     text_drawf(&red_text, "Load Game", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
254       if(menuaction == MN_HIT) /* Don't show the menu anymore, if this item got hit */
255         {
256           char *x = NULL;  /* In C, you can do this... */
257
258           show_menu = 0;
259           loadgame(x);
260         }
261     }
262   else
263       text_drawf(&blue_text, "Load Game", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
264
265   if(menuitem == 3)
266     {
267         text_drawf(&red_text, "Options", 0, 288, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
268       if(menuaction == MN_HIT) /* Switch to the 'Options' menu */
269         {
270           menumenu = MENU_OPTIONS;
271           menu_change = YES;
272         }
273     }
274   else
275           text_drawf(&blue_text, "Options", 0, 288, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
276
277   if(menuitem == 4)
278     {
279             text_drawf(&red_text, "Quit Game", 0, 320, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
280       if(menuaction == MN_HIT) /* Quit a running game */
281         return 1;
282     }
283   else
284     {
285             text_drawf(&blue_text, "Quit Game", 0, 320, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
286     }
287
288   return 0;
289 }
290
291 int menu_options(void)
292 {
293   if(menuitem > MENU_OPTIONS_ITEM_MAX )
294     menuitem = 0;
295   else if(menuitem < 0)
296     menuitem = MENU_OPTIONS_ITEM_MAX;
297
298   if(menuitem == 0)
299     {
300       if(use_fullscreen)
301       text_drawf(&red_text, "Fullscreen ON", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
302       else
303       text_drawf(&red_text, "Fullscreen OFF", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
304       if(menuaction == MN_HIT) /* Disable/Enable fullscreen */
305         {
306           if(use_fullscreen)
307             use_fullscreen = 0;
308           else
309             use_fullscreen = 1;
310           st_video_setup();
311           menu_change = YES;
312         }
313     }
314   else
315     {
316       if(use_fullscreen)
317       text_drawf(&blue_text, "Fullscreen ON", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
318       else
319       text_drawf(&blue_text, "Fullscreen OFF", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
320     }
321
322   /* handle menu sound on/off option */
323   menu_option_sound();
324
325   /* handle menu music on/off option */
326   menu_option_music();
327
328   if(menuitem == 3)
329     {
330     text_drawf(&red_text, "Back", 0, 288, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
331       if(menuaction == MN_HIT) /* Go back to main menu. */
332         {
333           if(game_started)
334             menumenu = MENU_GAME;
335           else
336             menumenu = MENU_MAIN;
337           menu_change = YES;
338         }
339     }
340   else
341     text_drawf(&blue_text, "Back", 0, 288, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
342
343   return 0;
344 }
345
346 /* Menu LevelEditor */
347 int menu_leveleditor(void)
348 {
349   if(menuitem > MENU_LEVELEDITOR_ITEM_MAX )
350     menuitem = 0;
351   else if(menuitem < 0)
352     menuitem = MENU_LEVELEDITOR_ITEM_MAX;
353
354   if(menuitem == 0)
355     {
356         text_drawf(&red_text, "Return To Level Editor", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
357       if(menuaction == MN_HIT) /* Don't show the menu anymore, if this item got hit */
358         show_menu = 0;
359     }
360   else
361   text_drawf(&blue_text, "Return To Level Editor", 0, 192, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
362
363   if(menuitem == 1)
364     {
365     text_drawf(&red_text, "New Level", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
366       if(menuaction == MN_HIT) /* Don't show the menu anymore, if this item got hit */
367         {
368           show_menu = 0;
369           newlevel();
370         }
371     }
372   else
373   text_drawf(&blue_text, "New Level", 0, 224, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
374   
375   if(menuitem == 2)
376     {
377     text_drawf(&red_text, "Load Level", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
378       if(menuaction == MN_HIT) /* Create a new Level and load it into the level-editor. */
379         {
380           show_menu = 0;
381           selectlevel();
382         }
383     }
384   else
385   text_drawf(&blue_text, "Load Level", 0, 256, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
386
387   if(menuitem == 3)
388     {
389    text_drawf(&red_text, "Save Level", 0, 288, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
390       if(menuaction == MN_HIT) /* Save the current level in the level-editor. */
391         {
392           show_menu = 0;
393           savelevel();
394         }
395     }
396   else
397   text_drawf(&blue_text, "Save Level", 0, 288, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
398
399   if(menuitem == 4)
400     {
401     text_drawf(&red_text, "Quit Level Editor", 0, 320, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
402       if(menuaction == MN_HIT) /* Quit the level-editor. (to the main-menu) */
403         {
404           return 1;
405         }
406     }
407   else
408   text_drawf(&blue_text, "Quit Level Editor", 0, 320, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
409
410   return 0;
411 }
412
413 /* Menu HighScore (ask for player's name) */
414 int menu_highscore()
415 {
416 while(delete_character > 0)     /* remove charactes */
417         {
418         hs_name[strlen(hs_name)-1] = '\0';
419         delete_character--;
420         }
421
422 char str[60];
423 strcat(hs_name, input_string);
424
425 text_drawf(&red_text, "Congratulations", 0, 130, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
426 text_draw(&red_text, "Your score:", 30, 250, 1, NO_UPDATE);
427 sprintf(str, "%d", hs_score);
428 text_draw(&blue_text, str, 350, 250, 1, NO_UPDATE);
429
430 text_draw(&red_text, "Enter your name:", 30, 280, 1, NO_UPDATE);
431 text_draw(&blue_text, hs_name, 350, 280, 1, NO_UPDATE);
432
433 strcpy(input_string, "");
434
435 if(menuaction == MN_HIT)    /* name written */
436   show_menu = 0;
437
438 return 0;
439 }
440
441 /* --- MENU --- */
442 /* Draw the menu and execute the (menu)events */
443 int drawmenu(void)
444 {
445   int quit = 0;
446
447   menu_change = NO;
448
449
450   if(menuaction == MN_UP)
451       --menuitem;   /* Go one menu-item up */
452   else if(menuaction == MN_DOWN)
453     ++menuitem;     /* Go one menu-item down */
454
455
456   switch(menumenu)
457   {
458   case MENU_MAIN:
459       quit = menu_main();
460     break;
461   case MENU_GAME:
462       quit = menu_game();
463     break;
464   case MENU_OPTIONS:
465       quit = menu_options();
466     break;
467   case MENU_LEVELEDITOR:
468       quit = menu_leveleditor();
469     break;
470   case MENU_HIGHSCORE:
471       quit = menu_highscore();
472     break;
473   default:
474     break;
475   }
476
477   menuaction = -1;
478
479   return quit;
480 }
481
482 /* Check for menu event */
483 void menu_event(SDL_keysym* keysym)
484 {
485 SDLKey key = keysym->sym;
486 SDLMod keymod;
487 keymod = SDL_GetModState();
488 char ch[2];
489
490 /* If the current unicode character is an ASCII character,
491    assign it to ch. */
492 if ( (keysym->unicode & 0xFF80) == 0 ) {
493   ch[0] = keysym->unicode & 0x7F;
494   ch[1] = '\0';
495 }
496 else {
497   /* An International Character. */
498 }
499
500 switch(key)
501         {
502         case SDLK_UP:           /* Menu Up */
503                 menuaction = MN_UP;
504                 menu_change = YES;
505                 break;
506         case SDLK_DOWN:         /* Menu Down */
507                 menuaction = MN_DOWN;
508                 menu_change = YES;
509                 break;
510         case SDLK_SPACE:                /* Menu Hit */
511         case SDLK_RETURN:
512                 menuaction = MN_HIT;
513                 menu_change = YES;
514                 break;
515
516         case SDLK_DELETE:
517         case SDLK_BACKSPACE:
518                 delete_character++;
519                 break;
520         default:
521                 if( key >= SDLK_0 && key <= SDLK_9)
522                  strcat( input_string, /* (key - SDLK_0) */ ch);
523                 else if( key >= SDLK_a && SDLK_z )
524                 {
525                  strcat( input_string, ch);
526                 }
527                 break;
528         }
529
530
531   /* FIXME: NO JOYSTICK SUPPORT */
532   /*#ifdef JOY_YES
533   else if (event.type == SDL_JOYBUTTONDOWN)
534    {
535       Joystick button: Continue:
536
537      done = 1;
538    }
539   #endif*/
540 }
541