Added more strings to be translated.
[supertux.git] / src / title.cpp
1 //  $Id$
2 // 
3 //  SuperTux
4 //  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
5 //  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
6 //
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.
11 //
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.
16 // 
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., 59 Temple Place - Suite 330, Boston, MA
20 //  02111-1307, USA.
21
22 #include <iostream>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <SDL.h>
29 #include <SDL_image.h>
30
31 #ifndef WIN32
32 #include <sys/types.h>
33 #include <ctype.h>
34 #endif
35
36 #include "defines.h"
37 #include "globals.h"
38 #include "title.h"
39 #include "screen/screen.h"
40 #include "screen/texture.h"
41 #include "high_scores.h"
42 #include "menu.h"
43 #include "timer.h"
44 #include "setup.h"
45 #include "level.h"
46 #include "gameloop.h"
47 #include "leveleditor.h"
48 #include "scene.h"
49 #include "player.h"
50 #include "math.h"
51 #include "tile.h"
52 #include "sector.h"
53 #include "tilemap.h"
54 #include "resources.h"
55 #include "gettext.h"
56
57 static Surface* bkg_title;
58 static Surface* logo;
59 static Surface* img_choose_subset;
60
61 static bool walking;
62 static Timer random_timer;
63
64 static int frame;
65 static unsigned int last_update_time;
66 static unsigned int update_time;
67
68 static GameSession* titlesession;
69
70 static std::vector<LevelSubset*> contrib_subsets;
71 static LevelSubset* current_contrib_subset = 0;
72
73 static LevelEditor* leveleditor;
74
75 void free_contrib_menu()
76 {
77   for(std::vector<LevelSubset*>::iterator i = contrib_subsets.begin();
78       i != contrib_subsets.end(); ++i)
79     delete *i;
80
81   contrib_subsets.clear();
82   contrib_menu->clear();
83 }
84
85 void generate_contrib_menu()
86 {
87   string_list_type level_subsets = dsubdirs("/levels", "info");
88
89   free_contrib_menu();
90
91   contrib_menu->additem(MN_LABEL,_("Contrib Levels"),0,0);
92   contrib_menu->additem(MN_HL,"",0,0);
93
94   for (int i = 0; i < level_subsets.num_items; ++i)
95     {
96       LevelSubset* subset = new LevelSubset();
97       subset->load(level_subsets.item[i]);
98       contrib_menu->additem(MN_GOTO, subset->title.c_str(), i,
99           contrib_subset_menu, i+1);
100       contrib_subsets.push_back(subset);
101     }
102
103   contrib_menu->additem(MN_HL,"",0,0);
104   contrib_menu->additem(MN_BACK,_("Back"),0,0);
105
106   string_list_free(&level_subsets);
107 }
108
109 void check_contrib_menu()
110 {
111   static int current_subset = -1;
112
113   int index = contrib_menu->check();
114   if (index != -1)
115     {
116       index -= 1;
117       if (index >= 0 && index <= int(contrib_subsets.size()))
118         {
119           if (current_subset != index)
120             {
121               current_subset = index;
122               // FIXME: This shouln't be busy looping
123               LevelSubset& subset = * (contrib_subsets[index]);
124           
125               current_contrib_subset = &subset;
126
127               contrib_subset_menu->clear();
128
129               contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0);
130               contrib_subset_menu->additem(MN_HL,"",0,0);
131               
132               for (int i = 1; i <= subset.levels; ++i)
133                 {
134                   Level* level = new Level;
135                   level->load(subset.get_level_filename(i));
136                   contrib_subset_menu->additem(MN_ACTION, level->get_name(), 0, 0, i);
137                   delete level;
138                 }
139               
140               contrib_subset_menu->additem(MN_HL,"",0,0);      
141               contrib_subset_menu->additem(MN_BACK, _("Back"), 0, 0);
142
143               titlesession->get_current_sector()->activate();
144               titlesession->set_current();
145             }
146         }
147       else
148         {
149           // Back button
150         }
151     }
152 }
153
154 void check_contrib_subset_menu()
155 {
156   int index = contrib_subset_menu->check();
157   if (index != -1)
158     {
159       if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION)
160         {
161           std::cout << "Starting level: " << index << std::endl;
162           
163           GameSession session(
164               current_contrib_subset->get_level_filename(index), ST_GL_PLAY);
165           session.run();
166           player_status.reset();
167           Menu::set_current(main_menu);
168           titlesession->get_current_sector()->activate();
169           titlesession->set_current();
170         }
171     }  
172 }
173
174 void draw_demo(double frame_ratio)
175 {
176   Sector* world  = titlesession->get_current_sector();
177   Player* tux = world->player;
178
179   world->play_music(LEVEL_MUSIC);
180   
181   global_frame_counter++;
182   tux->key_event((SDLKey) keymap.right,DOWN);
183   
184   if(random_timer.check())
185     {
186       if(walking)
187         tux->key_event((SDLKey) keymap.jump,UP);
188       else
189         tux->key_event((SDLKey) keymap.jump,DOWN);
190     }
191   else
192     {
193       random_timer.start(rand() % 3000 + 3000);
194       walking = !walking;
195     }
196
197   // Wrap around at the end of the level back to the beginnig
198   if(world->solids->get_width() * 32 - 320 < tux->base.x)
199     {
200       tux->level_begin();
201     }
202
203   tux->can_jump = true;
204   float last_tux_x_pos = tux->base.x;
205   world->action(frame_ratio);
206   
207
208   // disabled for now, since with the new jump code we easily get deadlocks
209   // Jump if tux stays in the same position for one loop, ie. if he is
210   // stuck behind a wall
211   if (last_tux_x_pos == tux->base.x)
212     {
213       walking = false;
214     }
215
216   world->draw(*titlesession->context);
217 }
218
219 /* --- TITLE SCREEN --- */
220 void title(void)
221 {
222   random_timer.init(true);
223
224   walking = true;
225
226   st_pause_ticks_init();
227
228   titlesession = new GameSession(datadir + "/levels/misc/menu.stl", ST_GL_DEMO_GAME);
229
230   /* Load images: */
231   bkg_title = new Surface(datadir + "/images/background/arctis.jpg", IGNORE_ALPHA);
232   logo = new Surface(datadir + "/images/title/logo.png", USE_ALPHA);
233   img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", USE_ALPHA);
234
235   /* --- Main title loop: --- */
236   frame = 0;
237
238   update_time = st_get_ticks();
239   random_timer.start(rand() % 2000 + 2000);
240
241   Menu::set_current(main_menu);
242   DrawingContext& context = *titlesession->context;
243   while (Menu::current())
244     {
245       // if we spent to much time on a menu entry
246       if( (update_time - last_update_time) > 1000)
247         update_time = last_update_time = st_get_ticks();
248
249       // Calculate the movement-factor
250       double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
251       if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
252         frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
253       /* Lower the frame_ratio that Tux doesn't jump to hectically throught the demo. */
254       frame_ratio /= 2;
255
256       SDL_Event event;
257       while (SDL_PollEvent(&event))
258         {
259           if (Menu::current())
260             {
261               Menu::current()->event(event);
262             }
263          // FIXME: QUIT signal should be handled more generic, not locally
264           if (event.type == SDL_QUIT)
265             Menu::set_current(0);
266         }
267
268       /* Draw the background: */
269       draw_demo(frame_ratio);
270      
271       if (Menu::current() == main_menu)
272         context.draw_surface(logo, Vector(screen->w/2 - logo->w/2, 30),
273             LAYER_FOREGROUND1+1);
274
275       context.draw_text(white_small_text,
276           _(" SuperTux " VERSION "\n"
277           "Copyright (c) 2003 SuperTux Devel Team\n"
278           "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
279           "are welcome to redistribute it under certain conditions; see the file COPYING\n"
280           "for details.\n"), Vector(0, screen->h - 70), LAYER_FOREGROUND1);
281
282       /* Don't draw menu, if quit is true */
283       Menu* menu = Menu::current();
284       if(menu)
285         {
286           menu->draw(context);
287           menu->action();
288         
289           if(menu == main_menu)
290             {
291               switch (main_menu->check())
292                 {
293                 case MNID_STARTGAME:
294                   // Start Game, ie. goto the slots menu
295                   update_load_save_game_menu(load_game_menu);
296                   break;
297                 case MNID_CONTRIB:
298                   // Contrib Menu
299                   puts("Entering contrib menu");
300                   generate_contrib_menu();
301                   break;
302                 case MNID_LEVELEDITOR:
303                   leveleditor = new LevelEditor();
304                   leveleditor->run();
305                   delete leveleditor;
306                   Menu::set_current(main_menu);
307                   break;
308                 case MNID_CREDITS:
309                   display_text_file("CREDITS", bkg_title, SCROLL_SPEED_CREDITS);
310                   Menu::set_current(main_menu);
311                   break;
312                 case MNID_QUITMAINMENU:
313                   Menu::set_current(0);
314                   break;
315                 }
316             }
317           else if(menu == options_menu)
318             {
319               process_options_menu();
320             }
321           else if(menu == load_game_menu)
322             {
323               if(event.key.keysym.sym == SDLK_DELETE)
324                 {
325                 int slot = menu->get_active_item_id();
326                 char str[1024];
327                 sprintf(str,_("Are you sure you want to delete slot %d?"), slot);
328                 
329                 if(confirm_dialog(bkg_title, str))
330                   {
331                   sprintf(str,"%s/slot%d.stsg", st_save_dir, slot);
332                   printf("Removing: %s\n",str);
333                   remove(str);
334                   }
335
336                 update_load_save_game_menu(load_game_menu);
337                 Menu::set_current(main_menu);
338                 update_time = st_get_ticks();
339                 }
340               else if (process_load_game_menu())
341                 {
342                   // FIXME: shouldn't be needed if GameSession doesn't relay on global variables
343                   titlesession->get_current_sector()->activate();
344                   titlesession->set_current();
345                   //titletux.level_begin();
346                   update_time = st_get_ticks();
347                 }
348             }
349           else if(menu == contrib_menu)
350             {
351               check_contrib_menu();
352             }
353           else if (menu == contrib_subset_menu)
354             {
355               check_contrib_subset_menu();
356             }
357         }
358
359       mouse_cursor->draw(context);
360      
361       context.do_drawing();
362
363       /* Set the time of the last update and the time of the current update */
364       last_update_time = update_time;
365       update_time = st_get_ticks();
366
367       /* Pause: */
368       frame++;
369       SDL_Delay(25);
370     }
371   /* Free surfaces: */
372
373   free_contrib_menu();
374   delete titlesession;
375   delete bkg_title;
376   delete logo;
377   delete img_choose_subset;
378 }
379
380 // EOF //
381