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::set_current(session->get_world());
169 //World* world = session->get_world();
170 Level* plevel = session->get_level();
171 Player* tux = session->get_world()->get_tux();
173 session->get_world()->play_music(LEVEL_MUSIC);
176 // update particle systems
177 std::vector<ParticleSystem*>::iterator p;
178 for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
180 (*p)->simulate(frame_ratio);
183 // Draw particle systems (background)
184 for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
186 (*p)->draw(scroll_x, 0, 0);
190 // Draw interactive tiles:
191 for (int y = 0; y < 15; ++y)
193 for (int x = 0; x < 21; ++x)
195 Tile::draw(32*x - fmodf(scroll_x, 32), y * 32,
196 plevel->ia_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
200 global_frame_counter++;
201 tux->key_event((SDLKey) keymap.right,DOWN);
203 if(random_timer.check())
206 tux->key_event((SDLKey) keymap.jump,UP);
208 tux->key_event((SDLKey) keymap.jump,DOWN);
212 random_timer.start(rand() % 3000 + 3000);
216 // Wrap around at the end of the level back to the beginnig
217 if(plevel->width * 32 - 320 < tux->base.x)
219 tux->base.x = tux->base.x - (plevel->width * 32 - 640);
220 scroll_x = tux->base.x - 320;
223 tux->can_jump = true;
224 float last_tux_x_pos = tux->base.x;
225 tux->action(frame_ratio);
227 // disabled for now, since with the new jump code we easily get deadlocks
228 // Jump if tux stays in the same position for one loop, ie. if he is
229 // stuck behind a wall
230 if (last_tux_x_pos == tux->base.x)
238 /* --- TITLE SCREEN --- */
241 random_timer.init(true);
245 st_pause_ticks_init();
247 GameSession session(datadir + "/levels/misc/menu.stl", 0, ST_GL_DEMO_GAME);
249 clearscreen(0, 0, 0);
253 bkg_title = new Surface(datadir + "/images/title/background.jpg", IGNORE_ALPHA);
254 logo = new Surface(datadir + "/images/title/logo.png", USE_ALPHA);
255 img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", USE_ALPHA);
257 /* --- Main title loop: --- */
260 /* Draw the title background: */
261 bkg_title->draw_bg();
263 update_time = st_get_ticks();
264 random_timer.start(rand() % 2000 + 2000);
266 Menu::set_current(main_menu);
267 while (Menu::current())
269 // if we spent to much time on a menu entry
270 if( (update_time - last_update_time) > 1000)
271 update_time = last_update_time = st_get_ticks();
273 // Calculate the movement-factor
274 double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
275 if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
276 frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
277 /* Lower the frame_ratio that Tux doesn't jump to hectically throught the demo. */
281 while (SDL_PollEvent(&event))
285 Menu::current()->event(event);
287 // FIXME: QUIT signal should be handled more generic, not locally
288 if (event.type == SDL_QUIT)
289 Menu::set_current(0);
292 /* Draw the background: */
294 draw_demo(&session, frame_ratio);
296 if (Menu::current() == main_menu)
297 logo->draw( 160, 30);
299 white_small_text->draw(" SuperTux " VERSION "\n"
300 "Copyright (c) 2003 SuperTux Devel Team\n"
301 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
302 "are welcome to redistribute it under certain conditions; see the file COPYING\n"
306 /* Don't draw menu, if quit is true */
307 Menu* menu = Menu::current();
313 if(menu == main_menu)
315 switch (main_menu->check())
318 // Start Game, ie. goto the slots menu
319 update_load_save_game_menu(load_game_menu);
323 puts("Entering contrib menu");
324 generate_contrib_menu();
326 case MNID_LEVELEDITOR:
328 Menu::set_current(main_menu);
331 display_text_file("CREDITS", bkg_title, SCROLL_SPEED_CREDITS);
332 Menu::set_current(main_menu);
334 case MNID_QUITMAINMENU:
335 Menu::set_current(0);
339 else if(menu == options_menu)
341 process_options_menu();
343 else if(menu == load_game_menu)
345 if(event.key.keysym.sym == SDLK_DELETE)
347 int slot = menu->get_active_item_id();
349 sprintf(str,"Are you sure you want to delete slot %d?", slot);
353 if(confirm_dialog(str))
355 sprintf(str,"%s/slot%d.stsg", st_save_dir, slot);
356 printf("Removing: %s\n",str);
360 update_load_save_game_menu(load_game_menu);
361 update_time = st_get_ticks();
363 else if (process_load_game_menu())
365 // FIXME: shouldn't be needed if GameSession doesn't relay on global variables
368 //titletux.level_begin();
369 update_time = st_get_ticks();
372 else if(menu == contrib_menu)
374 check_contrib_menu();
376 else if (menu == contrib_subset_menu)
378 check_contrib_subset_menu();
382 mouse_cursor->draw();
386 /* Set the time of the last update and the time of the current update */
387 last_update_time = update_time;
388 update_time = st_get_ticks();
399 delete img_choose_subset;