4 // Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
5 // Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
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.
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.
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
29 #include <SDL_image.h>
32 #include <sys/types.h>
39 #include "screen/screen.h"
40 #include "screen/texture.h"
41 #include "high_scores.h"
47 #include "leveleditor.h"
54 #include "resources.h"
57 static Surface* bkg_title;
59 static Surface* img_choose_subset;
62 static Timer random_timer;
65 static unsigned int last_update_time;
66 static unsigned int update_time;
68 static GameSession* titlesession;
70 static std::vector<LevelSubset*> contrib_subsets;
71 static LevelSubset* current_contrib_subset = 0;
73 static LevelEditor* leveleditor;
75 void free_contrib_menu()
77 for(std::vector<LevelSubset*>::iterator i = contrib_subsets.begin();
78 i != contrib_subsets.end(); ++i)
81 contrib_subsets.clear();
82 contrib_menu->clear();
85 void generate_contrib_menu()
87 string_list_type level_subsets = dsubdirs("/levels", "info");
91 contrib_menu->additem(MN_LABEL,_("Contrib Levels"),0,0);
92 contrib_menu->additem(MN_HL,"",0,0);
94 for (int i = 0; i < level_subsets.num_items; ++i)
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);
103 contrib_menu->additem(MN_HL,"",0,0);
104 contrib_menu->additem(MN_BACK,_("Back"),0,0);
106 string_list_free(&level_subsets);
109 void check_contrib_menu()
111 static int current_subset = -1;
113 int index = contrib_menu->check();
117 if (index >= 0 && index <= int(contrib_subsets.size()))
119 if (current_subset != index)
121 current_subset = index;
122 // FIXME: This shouln't be busy looping
123 LevelSubset& subset = * (contrib_subsets[index]);
125 current_contrib_subset = ⊂
127 contrib_subset_menu->clear();
129 contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0);
130 contrib_subset_menu->additem(MN_HL,"",0,0);
132 for (int i = 1; i <= subset.levels; ++i)
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);
140 contrib_subset_menu->additem(MN_HL,"",0,0);
141 contrib_subset_menu->additem(MN_BACK, _("Back"), 0, 0);
143 titlesession->get_current_sector()->activate();
144 titlesession->set_current();
154 void check_contrib_subset_menu()
156 int index = contrib_subset_menu->check();
159 if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION)
161 std::cout << "Starting level: " << index << std::endl;
164 current_contrib_subset->get_level_filename(index), ST_GL_PLAY);
166 player_status.reset();
167 Menu::set_current(main_menu);
168 titlesession->get_current_sector()->activate();
169 titlesession->set_current();
174 void draw_demo(double frame_ratio)
176 Sector* world = titlesession->get_current_sector();
177 Player* tux = world->player;
179 world->play_music(LEVEL_MUSIC);
181 global_frame_counter++;
182 tux->key_event((SDLKey) keymap.right,DOWN);
184 if(random_timer.check())
187 tux->key_event((SDLKey) keymap.jump,UP);
189 tux->key_event((SDLKey) keymap.jump,DOWN);
193 random_timer.start(rand() % 3000 + 3000);
197 // Wrap around at the end of the level back to the beginnig
198 if(world->solids->get_width() * 32 - 320 < tux->base.x)
203 tux->can_jump = true;
204 float last_tux_x_pos = tux->base.x;
205 world->action(frame_ratio);
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)
216 world->draw(*titlesession->context);
219 /* --- TITLE SCREEN --- */
222 random_timer.init(true);
226 st_pause_ticks_init();
228 titlesession = new GameSession(datadir + "/levels/misc/menu.stl", ST_GL_DEMO_GAME);
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);
235 /* --- Main title loop: --- */
238 update_time = st_get_ticks();
239 random_timer.start(rand() % 2000 + 2000);
241 Menu::set_current(main_menu);
242 DrawingContext& context = *titlesession->context;
243 while (Menu::current())
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();
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. */
257 while (SDL_PollEvent(&event))
261 Menu::current()->event(event);
263 // FIXME: QUIT signal should be handled more generic, not locally
264 if (event.type == SDL_QUIT)
265 Menu::set_current(0);
268 /* Draw the background: */
269 draw_demo(frame_ratio);
271 if (Menu::current() == main_menu)
272 context.draw_surface(logo, Vector(screen->w/2 - logo->w/2, 30),
273 LAYER_FOREGROUND1+1);
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);
282 /* Don't draw menu, if quit is true */
283 Menu* menu = Menu::current();
289 if(menu == main_menu)
291 switch (main_menu->check())
294 // Start Game, ie. goto the slots menu
295 update_load_save_game_menu(load_game_menu);
299 puts("Entering contrib menu");
300 generate_contrib_menu();
302 case MNID_LEVELEDITOR:
303 leveleditor = new LevelEditor();
306 Menu::set_current(main_menu);
309 display_text_file("CREDITS", bkg_title, SCROLL_SPEED_CREDITS);
310 Menu::set_current(main_menu);
312 case MNID_QUITMAINMENU:
313 Menu::set_current(0);
317 else if(menu == options_menu)
319 process_options_menu();
321 else if(menu == load_game_menu)
323 if(event.key.keysym.sym == SDLK_DELETE)
325 int slot = menu->get_active_item_id();
327 sprintf(str,_("Are you sure you want to delete slot %d?"), slot);
329 if(confirm_dialog(bkg_title, str))
331 sprintf(str,"%s/slot%d.stsg", st_save_dir, slot);
332 printf("Removing: %s\n",str);
336 update_load_save_game_menu(load_game_menu);
337 Menu::set_current(main_menu);
338 update_time = st_get_ticks();
340 else if (process_load_game_menu())
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();
349 else if(menu == contrib_menu)
351 check_contrib_menu();
353 else if (menu == contrib_subset_menu)
355 check_contrib_subset_menu();
359 mouse_cursor->draw(context);
361 context.do_drawing();
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();
377 delete img_choose_subset;