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;
56 static Surface* img_choose_subset;
59 static Timer random_timer;
62 static unsigned int last_update_time;
63 static unsigned int update_time;
65 std::vector<LevelSubset*> contrib_subsets;
66 std::string current_contrib_subset;
68 void free_contrib_menu()
70 for(std::vector<LevelSubset*>::iterator i = contrib_subsets.begin();
71 i != contrib_subsets.end(); ++i)
74 contrib_subsets.clear();
75 contrib_menu->clear();
78 void generate_contrib_menu()
80 string_list_type level_subsets = dsubdirs("/levels", "info");
84 contrib_menu->additem(MN_LABEL,"Contrib Levels",0,0);
85 contrib_menu->additem(MN_HL,"",0,0);
87 for (int i = 0; i < level_subsets.num_items; ++i)
89 LevelSubset* subset = new LevelSubset();
90 subset->load(level_subsets.item[i]);
91 contrib_menu->additem(MN_GOTO, subset->title.c_str(), i,
92 contrib_subset_menu, i+1);
93 contrib_subsets.push_back(subset);
96 contrib_menu->additem(MN_HL,"",0,0);
97 contrib_menu->additem(MN_BACK,"Back",0,0);
99 string_list_free(&level_subsets);
102 void check_contrib_menu()
104 static int current_subset = -1;
106 int index = contrib_menu->check();
110 if (index >= 0 && index <= int(contrib_subsets.size()))
112 if (current_subset != index)
114 current_subset = index;
115 // FIXME: This shouln't be busy looping
116 LevelSubset& subset = * (contrib_subsets[index]);
118 current_contrib_subset = subset.name;
120 std::cout << "Updating the contrib subset menu..." << subset.levels << std::endl;
122 contrib_subset_menu->clear();
124 contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0);
125 contrib_subset_menu->additem(MN_HL,"",0,0);
126 for (int i = 1; i <= subset.levels; ++i)
129 level.load(subset.name, i);
130 contrib_subset_menu->additem(MN_ACTION, level.name, 0, 0, i);
132 contrib_subset_menu->additem(MN_HL,"",0,0);
133 contrib_subset_menu->additem(MN_BACK, "Back", 0, 0);
143 void check_contrib_subset_menu()
145 int index = contrib_subset_menu->check();
148 if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION)
150 std::cout << "Sarting level: " << index << std::endl;
151 GameSession session(current_contrib_subset, index, ST_GL_PLAY);
153 player_status.reset();
154 Menu::set_current(main_menu);
159 void draw_background()
161 /* Draw the title background: */
163 bkg_title->draw_bg();
166 void draw_demo(GameSession* session, double frame_ratio)
168 World* world = session->get_world();
169 World::set_current(world);
170 Level* plevel = session->get_level();
171 Player* tux = world->get_tux();
173 world->play_music(LEVEL_MUSIC);
175 global_frame_counter++;
176 tux->key_event((SDLKey) keymap.right,DOWN);
178 if(random_timer.check())
181 tux->key_event((SDLKey) keymap.jump,UP);
183 tux->key_event((SDLKey) keymap.jump,DOWN);
187 random_timer.start(rand() % 3000 + 3000);
191 // Wrap around at the end of the level back to the beginnig
192 if(plevel->width * 32 - 320 < tux->base.x)
194 tux->base.x = tux->base.x - (plevel->width * 32 - 640);
195 scroll_x = tux->base.x - 320;
198 tux->can_jump = true;
199 float last_tux_x_pos = tux->base.x;
200 world->action(frame_ratio);
203 // disabled for now, since with the new jump code we easily get deadlocks
204 // Jump if tux stays in the same position for one loop, ie. if he is
205 // stuck behind a wall
206 if (last_tux_x_pos == tux->base.x)
214 /* --- TITLE SCREEN --- */
217 random_timer.init(true);
221 st_pause_ticks_init();
223 GameSession session(datadir + "/levels/misc/menu.stl", 0, ST_GL_DEMO_GAME);
225 clearscreen(0, 0, 0);
229 bkg_title = new Surface(datadir + "/images/title/background.jpg", IGNORE_ALPHA);
230 logo = new Surface(datadir + "/images/title/logo.png", USE_ALPHA);
231 img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", USE_ALPHA);
233 /* --- Main title loop: --- */
236 /* Draw the title background: */
237 bkg_title->draw_bg();
239 update_time = st_get_ticks();
240 random_timer.start(rand() % 2000 + 2000);
242 Menu::set_current(main_menu);
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(&session, frame_ratio);
271 if (Menu::current() == main_menu)
272 logo->draw( 160, 30);
274 white_small_text->draw(" SuperTux " VERSION "\n"
275 "Copyright (c) 2003 SuperTux Devel Team\n"
276 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
277 "are welcome to redistribute it under certain conditions; see the file COPYING\n"
281 /* Don't draw menu, if quit is true */
282 Menu* menu = Menu::current();
288 if(menu == main_menu)
290 switch (main_menu->check())
293 // Start Game, ie. goto the slots menu
294 update_load_save_game_menu(load_game_menu);
298 puts("Entering contrib menu");
299 generate_contrib_menu();
301 case MNID_LEVELEDITOR:
303 Menu::set_current(main_menu);
306 display_text_file("CREDITS", bkg_title, SCROLL_SPEED_CREDITS);
307 Menu::set_current(main_menu);
309 case MNID_QUITMAINMENU:
310 Menu::set_current(0);
314 else if(menu == options_menu)
316 process_options_menu();
318 else if(menu == load_game_menu)
320 if(event.key.keysym.sym == SDLK_DELETE)
322 int slot = menu->get_active_item_id();
324 sprintf(str,"Are you sure you want to delete slot %d?", slot);
328 if(confirm_dialog(str))
330 sprintf(str,"%s/slot%d.stsg", st_save_dir, slot);
331 printf("Removing: %s\n",str);
335 update_load_save_game_menu(load_game_menu);
336 update_time = st_get_ticks();
338 else if (process_load_game_menu())
340 // FIXME: shouldn't be needed if GameSession doesn't relay on global variables
343 //titletux.level_begin();
344 update_time = st_get_ticks();
347 else if(menu == contrib_menu)
349 check_contrib_menu();
351 else if (menu == contrib_subset_menu)
353 check_contrib_subset_menu();
357 mouse_cursor->draw();
361 /* Set the time of the last update and the time of the current update */
362 last_update_time = update_time;
363 update_time = st_get_ticks();
374 delete img_choose_subset;