1f7b699f85b04f456ae07bbcaa7f9d27c19afb15
[supertux.git] / src / title.cpp
1 /*
2   title.c
3   
4   Super Tux - Title Screen
5   
6   by Bill Kendrick
7   bill@newbreedsoftware.com
8   http://www.newbreedsoftware.com/supertux/
9   
10   April 11, 2000 - March 15, 2004
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <SDL.h>
19 #include <SDL_image.h>
20
21 #ifndef WIN32
22 #include <sys/types.h>
23 #include <ctype.h>
24 #endif
25
26 #include "defines.h"
27 #include "globals.h"
28 #include "title.h"
29 #include "screen.h"
30 #include "high_scores.h"
31 #include "menu.h"
32 #include "texture.h"
33 #include "timer.h"
34 #include "setup.h"
35 #include "level.h"
36 #include "gameloop.h"
37 #include "leveleditor.h"
38 #include "scene.h"
39 #include "player.h"
40 #include "math.h"
41
42 void loadshared(void);
43 void activate_particle_systems(void);
44
45 static texture_type bkg_title;
46 static texture_type logo;
47 static texture_type img_choose_subset;
48
49 static bool walking;
50 static Player titletux;
51 static timer_type random_timer;
52
53 static SDL_Event event;
54 static SDLKey key;
55 static int frame, i;
56 static unsigned int last_update_time;
57 static unsigned int update_time;
58
59 void display_credits();
60
61 void draw_background()
62 {
63   /* Draw the title background: */
64
65   texture_draw_bg(&bkg_title);
66 }
67
68 void draw_demo()
69 {
70   /* DEMO begin */
71   /* update particle systems */
72   std::vector<ParticleSystem*>::iterator p;
73   for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
74     {
75       (*p)->simulate(frame_ratio);
76     }
77
78   /* Draw particle systems (background) */
79   for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
80     {
81       (*p)->draw(scroll_x, 0, 0);
82     }
83
84   /* Draw interactive tiles: */
85
86   for (int y = 0; y < 15; ++y)
87     {
88       for (int x = 0; x < 21; ++x)
89         {
90           drawshape(32*x - fmodf(scroll_x, 32), y * 32,
91                     current_level.ia_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
92         }
93     }
94
95   global_frame_counter++;
96   titletux.key_event(SDLK_RIGHT,DOWN);
97   
98   if(timer_check(&random_timer))
99     {
100       if(walking)
101         titletux.key_event(SDLK_UP,UP);
102       else
103         titletux.key_event(SDLK_UP,DOWN);
104     }
105   else
106     {
107       timer_start(&random_timer, rand() % 3000 + 3000);
108       walking = !walking;
109     }
110
111   if(current_level.width * 32 - 320 < titletux.base.x)
112     {
113       titletux.base.x = 160;
114       scroll_x = 0;
115     }
116
117   titletux.action();
118   titletux.draw();
119
120   /* DEMO end */
121 }
122
123 /* --- TITLE SCREEN --- */
124
125 int title(void)
126 {
127   int done;
128   string_list_type level_subsets;
129   st_subset subset;
130   level_subsets = dsubdirs("/levels", "info");
131   timer_init(&random_timer, true);
132
133   walking = true;
134   titletux.init();
135
136   st_pause_ticks_init();
137
138   level_load(&current_level, (datadir + "/levels/misc/menu.stl").c_str());
139   loadshared();
140   activate_particle_systems();
141   /* Lower the gravity that tux doesn't jump to hectically through the demo */
142   //gravity = 5;
143
144   /* Reset menu variables */
145   menu_reset();
146   Menu::set_current(main_menu);
147
148   clearscreen(0, 0, 0);
149   updatescreen();
150
151   /* Load images: */
152
153   texture_load(&bkg_title,datadir + "/images/title/background.jpg", IGNORE_ALPHA);
154   texture_load(&logo,datadir + "/images/title/logo.png", USE_ALPHA);
155   texture_load(&img_choose_subset,datadir + "/images/status/choose-level-subset.png", USE_ALPHA);
156
157   /* --- Main title loop: --- */
158
159   done = 0;
160   quit = 0;
161   show_menu = 1;
162   frame = 0;
163
164   /* Draw the title background: */
165   texture_draw_bg(&bkg_title);
166   load_hs();
167
168   update_time = st_get_ticks();
169   timer_start(&random_timer, rand() % 2000 + 2000);
170
171   while (!done && !quit)
172     {
173
174       /* Calculate the movement-factor */
175       frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
176       if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
177         frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
178       /* Lower the frame_ratio that Tux doesn't jump to hectically throught the demo. */
179       frame_ratio /= 2;
180
181       /* Handle events: */
182
183       while (SDL_PollEvent(&event))
184         {
185         menu_event(event);
186           if (event.type == SDL_QUIT)
187             {
188               /* Quit event - quit: */
189               quit = 1;
190             }
191           else if (event.type == SDL_KEYDOWN)
192             {
193               /* Keypress... */
194
195               key = event.key.keysym.sym;
196
197               /* Check for menu events */
198               //menu_event(event);
199
200               if (key == SDLK_ESCAPE)
201                 {
202                   /* Escape: Quit: */
203
204                   quit = 1;
205                 }
206             }
207         }
208
209       /* Draw the background: */
210       draw_background();
211       draw_demo();
212       texture_draw(&logo, 160, 30);
213       text_draw(&white_small_text, 
214                 " SuperTux " VERSION "\n"
215                 "Copyright (c) 2003 SuperTux Devel Team\n"
216                 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
217                 "are welcome to redistribute it under certain conditions; see the file COPYING\n"
218                 "for details.\n",
219                 0, 420, 0);
220
221       /* Draw the high score: */
222       /*
223       sprintf(str, "High score: %d", hs_score);
224       text_drawf(&gold_text, str, 0, -40, A_HMIDDLE, A_BOTTOM, 1);
225       sprintf(str, "by %s", hs_name);
226       text_drawf(&gold_text, str, 0, -20, A_HMIDDLE, A_BOTTOM, 1);
227       */
228
229       /* Don't draw menu, if quit is true */
230       if(show_menu && !quit)
231         menu_process_current();
232
233       if(current_menu == main_menu)
234         {
235           switch (main_menu->check())
236             {
237             case 2:
238               done = 0;
239               i = 0;
240               if(level_subsets.num_items != 0)
241                 {
242                   subset.load(level_subsets.item[0]);
243                   while(!done)
244                     {
245                       texture_draw(&img_choose_subset,(screen->w - img_choose_subset.w) / 2, 0);
246                       if(level_subsets.num_items != 0)
247                         {
248                           texture_draw(&subset.image,(screen->w - subset.image.w) / 2 + 25,78);
249                           if(level_subsets.num_items > 1)
250                             {
251                               if(i > 0)
252                                 texture_draw(&arrow_left,(screen->w / 2) - ((subset.title.length()+2)*16)/2,20);
253                               if(i < level_subsets.num_items-1)
254                                 texture_draw(&arrow_right,(screen->w / 2) + ((subset.description.length())*16)/2,20);
255                             }
256                           text_drawf(&gold_text, subset.title.c_str(), 0, 20, A_HMIDDLE, A_TOP, 1);
257                           text_drawf(&gold_text, subset.description.c_str(), 20, -20, A_HMIDDLE, A_BOTTOM, 1);
258                         }
259                       updatescreen();
260                       SDL_Delay(50);
261                       while(SDL_PollEvent(&event) && !done)
262                         {
263                           switch(event.type)
264                             {
265                             case SDL_QUIT:
266                               done = 1;
267                               quit = 1;
268                               break;
269                             case SDL_KEYDOWN:           // key pressed
270                               /* Keypress... */
271
272                               key = event.key.keysym.sym;
273
274                               if(key == SDLK_LEFT)
275                                 {
276                                   if(i > 0)
277                                     {
278                                       --i;
279                                       subset.free();
280                                       subset.load(level_subsets.item[i]);
281                                     }
282                                 }
283                               else if(key == SDLK_RIGHT)
284                                 {
285                                   if(i < level_subsets.num_items -1)
286                                     {
287                                       ++i;
288                                       subset.free();
289                                       subset.load(level_subsets.item[i]);
290                                     }
291                                 }
292                               else if(key == SDLK_SPACE || key == SDLK_RETURN)
293                                 {
294                                   done = true;
295                                   quit = gameloop(subset.name.c_str(),1,ST_GL_PLAY);
296                                   subset.free();
297                                 }
298                               else if(key == SDLK_ESCAPE)
299                                 {
300                                   done = true;
301                                 }
302                               break;
303                             default:
304                               break;
305                             }
306                         }
307                     }
308                 }
309               // reset tux
310               scroll_x = 0;
311               titletux.level_begin();
312               update_time = st_get_ticks();
313               break;
314             case 3:
315               update_load_save_game_menu(load_game_menu, true);
316               break;
317             case 5:
318               done = 1;
319               quit = leveleditor(1);
320               break;
321             case 6:
322               display_credits();
323               break;
324             case 8:
325               quit = 1;
326               break;
327             }
328         }
329       else if(current_menu == options_menu)
330         {
331           process_options_menu();
332         }
333       else if(current_menu == load_game_menu)
334         {
335           process_save_load_game_menu(false);
336         }
337
338       mouse_cursor->draw();
339       
340       flipscreen();
341
342       /* Set the time of the last update and the time of the current update */
343       last_update_time = update_time;
344       update_time = st_get_ticks();
345
346       /* Pause: */
347       frame++;
348       SDL_Delay(25);
349
350     }
351   /* Free surfaces: */
352
353   texture_free(&bkg_title);
354   texture_free(&logo);
355   string_list_free(&level_subsets);
356
357   /* Return to main! */
358
359   return(quit);
360 }
361
362 #define MAX_VEL 10
363 #define SPEED   1
364 #define SCROLL  60
365
366 void display_credits()
367 {
368   int done;
369   int scroll, speed;
370   timer_type timer;
371   int n,d;
372   int length;
373   FILE* fi;
374   char temp[1024];
375   string_list_type names;
376   char filename[1024];
377   string_list_init(&names);
378   sprintf(filename,"%s/CREDITS", datadir.c_str());
379   if((fi = fopen(filename,"r")) != NULL)
380     {
381       while(fgets(temp, sizeof(temp), fi) != NULL)
382         {
383           temp[strlen(temp)-1]='\0';
384           string_list_add_item(&names,temp);
385         }
386       fclose(fi);
387     }
388   else
389     {
390       string_list_add_item(&names,"Credits were not found!");
391       string_list_add_item(&names,"Shame on the guy, who");
392       string_list_add_item(&names,"forgot to include them");
393       string_list_add_item(&names,"in your SuperTux distribution.");
394     }
395
396
397   timer_init(&timer, SDL_GetTicks());
398   timer_start(&timer, 50);
399
400   scroll = 0;
401   speed = 2;
402   done = 0;
403
404   n = d = 0;
405
406   length = names.num_items;
407
408   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
409
410   while(done == 0)
411     {
412       /* in case of input, exit */
413       while(SDL_PollEvent(&event))
414         switch(event.type)
415           {
416           case SDL_KEYDOWN:
417             switch(event.key.keysym.sym)
418               {
419               case SDLK_UP:
420                 speed -= SPEED;
421                 break;
422               case SDLK_DOWN:
423                 speed += SPEED;
424                 break;
425               case SDLK_SPACE:
426               case SDLK_RETURN:
427                 if(speed >= 0)
428                   scroll += SCROLL;
429                 break;
430               case SDLK_ESCAPE:
431                 done = 1;
432                 break;
433               default:
434                 break;
435               }
436             break;
437           case SDL_QUIT:
438             done = 1;
439             break;
440           default:
441             break;
442           }
443
444       if(speed > MAX_VEL)
445         speed = MAX_VEL;
446       else if(speed < -MAX_VEL)
447         speed = -MAX_VEL;
448
449       /* draw the credits */
450
451       draw_background();
452
453       text_drawf(&white_big_text, "- Credits -", 0, screen->h-scroll, A_HMIDDLE, A_TOP, 2);
454
455       for(i = 0, n = 0, d = 0; i < length; i++,n++,d++)
456         {
457           if(names.item[i] == "")
458             n--;
459           else
460             {
461               if(names.item[i][0] == ' ')
462                 text_drawf(&white_small_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll-10, A_HMIDDLE, A_TOP, 1);
463               else if(names.item[i][0] == '     ')
464                 text_drawf(&white_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll, A_HMIDDLE, A_TOP, 1);
465               else if(names.item[i+1][0] == '-' || names.item[i][0] == '-')
466                 text_drawf(&white_big_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll, A_HMIDDLE, A_TOP, 3);
467               else
468                 text_drawf(&blue_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll, A_HMIDDLE, A_TOP, 1);
469             }
470         }
471
472       flipscreen();
473
474       if(60+screen->h+(n*18)+(d*18)-scroll < 0 && 20+60+screen->h+(n*18)+(d*18)-scroll < 0)
475         done = 1;
476
477       scroll += speed;
478       if(scroll < 0)
479         scroll = 0;
480
481       SDL_Delay(35);
482
483       if(timer_get_left(&timer) < 0)
484         {
485           frame++;
486           timer_start(&timer, 50);
487         }
488     }
489   string_list_free(&names);
490
491   SDL_EnableKeyRepeat(0, 0);    // disables key repeating
492   show_menu = 1;
493   Menu::set_current(main_menu);
494 }