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"
56 static Surface* bkg_title;
58 static Surface* img_choose_subset;
61 static Timer random_timer;
64 static unsigned int last_update_time;
65 static unsigned int update_time;
67 static GameSession* titlesession;
69 static std::vector<LevelSubset*> contrib_subsets;
70 static LevelSubset* current_contrib_subset = 0;
72 void free_contrib_menu()
74 for(std::vector<LevelSubset*>::iterator i = contrib_subsets.begin();
75 i != contrib_subsets.end(); ++i)
78 contrib_subsets.clear();
79 contrib_menu->clear();
82 void generate_contrib_menu()
84 string_list_type level_subsets = dsubdirs("/levels", "info");
88 contrib_menu->additem(MN_LABEL,"Contrib Levels",0,0);
89 contrib_menu->additem(MN_HL,"",0,0);
91 for (int i = 0; i < level_subsets.num_items; ++i)
93 LevelSubset* subset = new LevelSubset();
94 subset->load(level_subsets.item[i]);
95 contrib_menu->additem(MN_GOTO, subset->title.c_str(), i,
96 contrib_subset_menu, i+1);
97 contrib_subsets.push_back(subset);
100 contrib_menu->additem(MN_HL,"",0,0);
101 contrib_menu->additem(MN_BACK,"Back",0,0);
103 string_list_free(&level_subsets);
106 void check_contrib_menu()
108 static int current_subset = -1;
110 int index = contrib_menu->check();
114 if (index >= 0 && index <= int(contrib_subsets.size()))
116 if (current_subset != index)
118 current_subset = index;
119 // FIXME: This shouln't be busy looping
120 LevelSubset& subset = * (contrib_subsets[index]);
122 current_contrib_subset = ⊂
124 contrib_subset_menu->clear();
126 contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0);
127 contrib_subset_menu->additem(MN_HL,"",0,0);
129 for (int i = 1; i <= subset.levels; ++i)
131 Level* level = new Level;
132 level->load(subset.get_level_filename(i));
133 contrib_subset_menu->additem(MN_ACTION, level->get_name(), 0, 0, i);
137 contrib_subset_menu->additem(MN_HL,"",0,0);
138 contrib_subset_menu->additem(MN_BACK, "Back", 0, 0);
140 titlesession->get_current_sector()->activate();
141 titlesession->set_current();
151 void check_contrib_subset_menu()
153 int index = contrib_subset_menu->check();
156 if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION)
158 std::cout << "Starting level: " << index << std::endl;
161 current_contrib_subset->get_level_filename(index), ST_GL_PLAY);
163 player_status.reset();
164 Menu::set_current(main_menu);
165 titlesession->get_current_sector()->activate();
166 titlesession->set_current();
171 void draw_demo(double frame_ratio)
173 Sector* world = titlesession->get_current_sector();
174 Player* tux = world->player;
176 world->play_music(LEVEL_MUSIC);
178 global_frame_counter++;
179 tux->key_event((SDLKey) keymap.right,DOWN);
181 if(random_timer.check())
184 tux->key_event((SDLKey) keymap.jump,UP);
186 tux->key_event((SDLKey) keymap.jump,DOWN);
190 random_timer.start(rand() % 3000 + 3000);
194 // Wrap around at the end of the level back to the beginnig
195 if(world->solids->get_width() * 32 - 320 < tux->base.x)
200 tux->can_jump = true;
201 float last_tux_x_pos = tux->base.x;
202 world->action(frame_ratio);
205 // disabled for now, since with the new jump code we easily get deadlocks
206 // Jump if tux stays in the same position for one loop, ie. if he is
207 // stuck behind a wall
208 if (last_tux_x_pos == tux->base.x)
213 world->draw(*titlesession->context);
216 /* --- TITLE SCREEN --- */
219 random_timer.init(true);
223 st_pause_ticks_init();
225 titlesession = new GameSession(datadir + "/levels/misc/menu.stl", ST_GL_DEMO_GAME);
228 bkg_title = new Surface(datadir + "/images/background/arctis.jpg", IGNORE_ALPHA);
229 logo = new Surface(datadir + "/images/title/logo.png", USE_ALPHA);
230 img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", USE_ALPHA);
232 /* --- Main title loop: --- */
235 update_time = st_get_ticks();
236 random_timer.start(rand() % 2000 + 2000);
238 Menu::set_current(main_menu);
239 DrawingContext& context = *titlesession->context;
240 while (Menu::current())
242 // if we spent to much time on a menu entry
243 if( (update_time - last_update_time) > 1000)
244 update_time = last_update_time = st_get_ticks();
246 // Calculate the movement-factor
247 double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
248 if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
249 frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
250 /* Lower the frame_ratio that Tux doesn't jump to hectically throught the demo. */
254 while (SDL_PollEvent(&event))
258 Menu::current()->event(event);
260 // FIXME: QUIT signal should be handled more generic, not locally
261 if (event.type == SDL_QUIT)
262 Menu::set_current(0);
265 /* Draw the background: */
266 draw_demo(frame_ratio);
268 if (Menu::current() == main_menu)
269 context.draw_surface(logo, Vector(screen->w/2 - logo->w/2, 30),
270 LAYER_FOREGROUND1+1);
272 context.draw_text(white_small_text,
273 " SuperTux " VERSION "\n"
274 "Copyright (c) 2003 SuperTux Devel Team\n"
275 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
276 "are welcome to redistribute it under certain conditions; see the file COPYING\n"
277 "for details.\n", Vector(0, screen->h - 70), LAYER_FOREGROUND1);
279 /* Don't draw menu, if quit is true */
280 Menu* menu = Menu::current();
286 if(menu == main_menu)
288 switch (main_menu->check())
291 // Start Game, ie. goto the slots menu
292 update_load_save_game_menu(load_game_menu);
296 puts("Entering contrib menu");
297 generate_contrib_menu();
299 case MNID_LEVELEDITOR:
301 Menu::set_current(main_menu);
304 display_text_file("CREDITS", bkg_title, SCROLL_SPEED_CREDITS);
305 Menu::set_current(main_menu);
307 case MNID_QUITMAINMENU:
308 Menu::set_current(0);
312 else if(menu == options_menu)
314 process_options_menu();
316 else if(menu == load_game_menu)
318 if(event.key.keysym.sym == SDLK_DELETE)
320 int slot = menu->get_active_item_id();
322 sprintf(str,"Are you sure you want to delete slot %d?", slot);
324 if(confirm_dialog(bkg_title, str))
326 sprintf(str,"%s/slot%d.stsg", st_save_dir, slot);
327 printf("Removing: %s\n",str);
331 update_load_save_game_menu(load_game_menu);
332 Menu::set_current(main_menu);
333 update_time = st_get_ticks();
335 else if (process_load_game_menu())
337 // FIXME: shouldn't be needed if GameSession doesn't relay on global variables
338 titlesession->get_current_sector()->activate();
339 titlesession->set_current();
340 //titletux.level_begin();
341 update_time = st_get_ticks();
344 else if(menu == contrib_menu)
346 check_contrib_menu();
348 else if (menu == contrib_subset_menu)
350 check_contrib_subset_menu();
354 mouse_cursor->draw(context);
356 context.do_drawing();
358 /* Set the time of the last update and the time of the current update */
359 last_update_time = update_time;
360 update_time = st_get_ticks();
372 delete img_choose_subset;