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"
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 contrib_subset_menu->clear();
122 contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0);
123 contrib_subset_menu->additem(MN_HL,"",0,0);
124 for (int i = 1; i <= subset.levels; ++i)
127 level.load(subset.name, i, 0);
128 contrib_subset_menu->additem(MN_ACTION, level.name, 0, 0, i);
130 contrib_subset_menu->additem(MN_HL,"",0,0);
131 contrib_subset_menu->additem(MN_BACK, "Back", 0, 0);
141 void check_contrib_subset_menu()
143 int index = contrib_subset_menu->check();
146 if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION)
148 std::cout << "Starting level: " << index << std::endl;
149 GameSession session(current_contrib_subset, index, ST_GL_PLAY);
151 player_status.reset();
152 Menu::set_current(main_menu);
157 void draw_demo(GameSession* session, double frame_ratio)
159 World* world = session->get_world();
160 World::set_current(world);
161 Level* plevel = session->get_level();
162 Player* tux = world->get_tux();
164 world->play_music(LEVEL_MUSIC);
166 global_frame_counter++;
167 tux->key_event((SDLKey) keymap.right,DOWN);
169 if(random_timer.check())
172 tux->key_event((SDLKey) keymap.jump,UP);
174 tux->key_event((SDLKey) keymap.jump,DOWN);
178 random_timer.start(rand() % 3000 + 3000);
182 // Wrap around at the end of the level back to the beginnig
183 if(plevel->width * 32 - 320 < tux->base.x)
188 tux->can_jump = true;
189 float last_tux_x_pos = tux->base.x;
190 world->action(frame_ratio);
193 // disabled for now, since with the new jump code we easily get deadlocks
194 // Jump if tux stays in the same position for one loop, ie. if he is
195 // stuck behind a wall
196 if (last_tux_x_pos == tux->base.x)
204 /* --- TITLE SCREEN --- */
207 random_timer.init(true);
211 st_pause_ticks_init();
213 GameSession session(datadir + "/levels/misc/menu.stl", 0, ST_GL_DEMO_GAME);
216 bkg_title = new Surface(datadir + "/images/background/arctis.jpg", IGNORE_ALPHA);
217 logo = new Surface(datadir + "/images/title/logo.png", USE_ALPHA);
218 img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", USE_ALPHA);
220 /* --- Main title loop: --- */
223 update_time = st_get_ticks();
224 random_timer.start(rand() % 2000 + 2000);
226 Menu::set_current(main_menu);
227 DrawingContext& context = World::current()->context;
228 while (Menu::current())
230 // if we spent to much time on a menu entry
231 if( (update_time - last_update_time) > 1000)
232 update_time = last_update_time = st_get_ticks();
234 // Calculate the movement-factor
235 double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
236 if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
237 frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
238 /* Lower the frame_ratio that Tux doesn't jump to hectically throught the demo. */
242 while (SDL_PollEvent(&event))
246 Menu::current()->event(event);
248 // FIXME: QUIT signal should be handled more generic, not locally
249 if (event.type == SDL_QUIT)
250 Menu::set_current(0);
253 /* Draw the background: */
254 draw_demo(&session, frame_ratio);
256 context.push_transform();
257 context.set_translation(Vector(0, 0));
258 if (Menu::current() == main_menu)
259 context.draw_surface(logo, Vector(screen->w/2 - logo->w/2, 30),
260 LAYER_FOREGROUND1+1);
262 context.draw_text(white_small_text,
263 " SuperTux " VERSION "\n"
264 "Copyright (c) 2003 SuperTux Devel Team\n"
265 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
266 "are welcome to redistribute it under certain conditions; see the file COPYING\n"
267 "for details.\n", Vector(0, screen->h - 70), LAYER_FOREGROUND1);
268 context.pop_transform();
270 /* Don't draw menu, if quit is true */
271 Menu* menu = Menu::current();
277 if(menu == main_menu)
279 switch (main_menu->check())
282 // Start Game, ie. goto the slots menu
283 update_load_save_game_menu(load_game_menu);
287 puts("Entering contrib menu");
288 generate_contrib_menu();
290 case MNID_LEVELEDITOR:
293 Menu::set_current(main_menu);
296 display_text_file("CREDITS", bkg_title, SCROLL_SPEED_CREDITS);
297 Menu::set_current(main_menu);
299 case MNID_QUITMAINMENU:
300 Menu::set_current(0);
304 else if(menu == options_menu)
306 process_options_menu();
308 else if(menu == load_game_menu)
310 if(event.key.keysym.sym == SDLK_DELETE)
312 int slot = menu->get_active_item_id();
314 sprintf(str,"Are you sure you want to delete slot %d?", slot);
316 if(confirm_dialog(str))
318 sprintf(str,"%s/slot%d.stsg", st_save_dir, slot);
319 printf("Removing: %s\n",str);
323 update_load_save_game_menu(load_game_menu);
324 Menu::set_current(main_menu);
325 update_time = st_get_ticks();
327 else if (process_load_game_menu())
329 // FIXME: shouldn't be needed if GameSession doesn't relay on global variables
330 //titletux.level_begin();
331 update_time = st_get_ticks();
334 else if(menu == contrib_menu)
336 check_contrib_menu();
338 else if (menu == contrib_subset_menu)
340 check_contrib_subset_menu();
344 mouse_cursor->draw(context);
346 context.do_drawing();
348 /* Set the time of the last update and the time of the current update */
349 last_update_time = update_time;
350 update_time = st_get_ticks();
361 delete img_choose_subset;