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