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>
40 #include "high_scores.h"
47 #include "leveleditor.h"
52 #include "resources.h"
54 static Surface* bkg_title;
55 static Surface* bkg_credits;
57 static Surface* img_choose_subset;
60 static Timer random_timer;
63 static unsigned int last_update_time;
64 static unsigned int update_time;
66 std::vector<LevelSubset*> contrib_subsets;
67 std::string current_contrib_subset;
69 void free_contrib_menu()
71 for(std::vector<LevelSubset*>::iterator i = contrib_subsets.begin();
72 i != contrib_subsets.end(); ++i)
75 contrib_subsets.clear();
76 contrib_menu->clear();
79 void generate_contrib_menu()
81 string_list_type level_subsets = dsubdirs("/levels", "info");
85 contrib_menu->additem(MN_LABEL,"Contrib Levels",0,0);
86 contrib_menu->additem(MN_HL,"",0,0);
88 for (int i = 0; i < level_subsets.num_items; ++i)
90 LevelSubset* subset = new LevelSubset();
91 subset->load(level_subsets.item[i]);
92 contrib_menu->additem(MN_GOTO, subset->title.c_str(), i,
93 contrib_subset_menu, i+1);
94 contrib_subsets.push_back(subset);
97 contrib_menu->additem(MN_HL,"",0,0);
98 contrib_menu->additem(MN_BACK,"Back",0,0);
100 string_list_free(&level_subsets);
103 void check_contrib_menu()
105 static int current_subset = -1;
107 int index = contrib_menu->check();
111 if (index >= 0 && index <= int(contrib_subsets.size()))
113 if (current_subset != index)
115 current_subset = index;
116 // FIXME: This shouln't be busy looping
117 LevelSubset& subset = * (contrib_subsets[index]);
119 current_contrib_subset = subset.name;
121 std::cout << "Updating the contrib subset menu..." << subset.levels << std::endl;
123 contrib_subset_menu->clear();
125 contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0);
126 contrib_subset_menu->additem(MN_HL,"",0,0);
127 for (int i = 1; i <= subset.levels; ++i)
130 level.load(subset.name, i);
131 contrib_subset_menu->additem(MN_ACTION, level.name, 0, 0, i);
133 contrib_subset_menu->additem(MN_HL,"",0,0);
134 contrib_subset_menu->additem(MN_BACK, "Back", 0, 0);
144 void check_contrib_subset_menu()
146 int index = contrib_subset_menu->check();
149 if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION)
151 std::cout << "Starting level: " << index << std::endl;
152 GameSession session(current_contrib_subset, index, ST_GL_PLAY);
154 player_status.reset();
155 Menu::set_current(main_menu);
160 void draw_background()
162 /* Draw the title background: */
164 bkg_title->draw_bg();
167 void draw_demo(GameSession* session, double frame_ratio)
169 World* world = session->get_world();
170 World::set_current(world);
171 Level* plevel = session->get_level();
172 Player* tux = world->get_tux();
174 world->play_music(LEVEL_MUSIC);
176 global_frame_counter++;
177 tux->key_event((SDLKey) keymap.right,DOWN);
179 if(random_timer.check())
182 tux->key_event((SDLKey) keymap.jump,UP);
184 tux->key_event((SDLKey) keymap.jump,DOWN);
188 random_timer.start(rand() % 3000 + 3000);
192 // Wrap around at the end of the level back to the beginnig
193 if(plevel->width * 32 - 320 < tux->base.x)
199 tux->can_jump = true;
200 float last_tux_x_pos = tux->base.x;
201 world->action(frame_ratio);
204 // disabled for now, since with the new jump code we easily get deadlocks
205 // Jump if tux stays in the same position for one loop, ie. if he is
206 // stuck behind a wall
207 if (last_tux_x_pos == tux->base.x)
215 /* --- TITLE SCREEN --- */
218 random_timer.init(true);
222 st_pause_ticks_init();
224 GameSession session(datadir + "/levels/misc/menu.stl", 0, ST_GL_DEMO_GAME);
226 clearscreen(0, 0, 0);
230 bkg_title = new Surface(datadir + "/images/title/background.jpg", IGNORE_ALPHA);
231 bkg_credits = new Surface(datadir + "/images/background/oiltux.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 /* Draw the title background: */
239 bkg_title->draw_bg();
241 update_time = st_get_ticks();
242 random_timer.start(rand() % 2000 + 2000);
244 Menu::set_current(main_menu);
245 while (Menu::current())
247 // if we spent to much time on a menu entry
248 if( (update_time - last_update_time) > 1000)
249 update_time = last_update_time = st_get_ticks();
251 // Calculate the movement-factor
252 double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
253 if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
254 frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
255 /* Lower the frame_ratio that Tux doesn't jump to hectically throught the demo. */
259 while (SDL_PollEvent(&event))
263 Menu::current()->event(event);
265 // FIXME: QUIT signal should be handled more generic, not locally
266 if (event.type == SDL_QUIT)
267 Menu::set_current(0);
270 /* Draw the background: */
271 draw_demo(&session, frame_ratio);
273 if (Menu::current() == main_menu)
274 logo->draw(screen->w/2 - logo->w/2, 30);
276 white_small_text->draw(" 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"
283 /* Don't draw menu, if quit is true */
284 Menu* menu = Menu::current();
290 if(menu == main_menu)
292 switch (main_menu->check())
295 // Start Game, ie. goto the slots menu
296 update_load_save_game_menu(load_game_menu);
300 puts("Entering contrib menu");
301 generate_contrib_menu();
303 case MNID_LEVELEDITOR:
305 Menu::set_current(main_menu);
308 display_text_file("CREDITS", bkg_credits, SCROLL_SPEED_CREDITS);
309 Menu::set_current(main_menu);
311 case MNID_QUITMAINMENU:
312 Menu::set_current(0);
316 else if(menu == options_menu)
318 process_options_menu();
320 else if(menu == load_game_menu)
322 if(event.key.keysym.sym == SDLK_DELETE)
324 int slot = menu->get_active_item_id();
326 sprintf(str,"Are you sure you want to delete slot %d?", slot);
330 if(confirm_dialog(str))
332 sprintf(str,"%s/slot%d.stsg", st_save_dir, slot);
333 printf("Removing: %s\n",str);
337 update_load_save_game_menu(load_game_menu);
338 Menu::set_current(main_menu);
339 update_time = st_get_ticks();
341 else if (process_load_game_menu())
343 // FIXME: shouldn't be needed if GameSession doesn't relay on global variables
346 //titletux.level_begin();
347 update_time = st_get_ticks();
350 else if(menu == contrib_menu)
352 check_contrib_menu();
354 else if (menu == contrib_subset_menu)
356 check_contrib_subset_menu();
360 mouse_cursor->draw();
364 /* Set the time of the last update and the time of the current update */
365 last_update_time = update_time;
366 update_time = st_get_ticks();
378 delete img_choose_subset;