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