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 static LevelEditor* leveleditor;
74 void free_contrib_menu()
76 for(std::vector<LevelSubset*>::iterator i = contrib_subsets.begin();
77 i != contrib_subsets.end(); ++i)
80 contrib_subsets.clear();
81 contrib_menu->clear();
84 void generate_contrib_menu()
86 string_list_type level_subsets = dsubdirs("/levels", "info");
90 contrib_menu->additem(MN_LABEL,"Contrib Levels",0,0);
91 contrib_menu->additem(MN_HL,"",0,0);
93 for (int i = 0; i < level_subsets.num_items; ++i)
95 LevelSubset* subset = new LevelSubset();
96 subset->load(level_subsets.item[i]);
97 contrib_menu->additem(MN_GOTO, subset->title.c_str(), i,
98 contrib_subset_menu, i+1);
99 contrib_subsets.push_back(subset);
102 contrib_menu->additem(MN_HL,"",0,0);
103 contrib_menu->additem(MN_BACK,"Back",0,0);
105 string_list_free(&level_subsets);
108 void check_contrib_menu()
110 static int current_subset = -1;
112 int index = contrib_menu->check();
116 if (index >= 0 && index <= int(contrib_subsets.size()))
118 if (current_subset != index)
120 current_subset = index;
121 // FIXME: This shouln't be busy looping
122 LevelSubset& subset = * (contrib_subsets[index]);
124 current_contrib_subset = ⊂
126 contrib_subset_menu->clear();
128 contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0);
129 contrib_subset_menu->additem(MN_HL,"",0,0);
131 for (int i = 1; i <= subset.levels; ++i)
133 Level* level = new Level;
134 level->load(subset.get_level_filename(i));
135 contrib_subset_menu->additem(MN_ACTION, level->get_name(), 0, 0, i);
139 contrib_subset_menu->additem(MN_HL,"",0,0);
140 contrib_subset_menu->additem(MN_BACK, "Back", 0, 0);
142 titlesession->get_current_sector()->activate();
143 titlesession->set_current();
153 void check_contrib_subset_menu()
155 int index = contrib_subset_menu->check();
158 if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION)
160 std::cout << "Starting level: " << index << std::endl;
163 current_contrib_subset->get_level_filename(index), ST_GL_PLAY);
165 player_status.reset();
166 Menu::set_current(main_menu);
167 titlesession->get_current_sector()->activate();
168 titlesession->set_current();
173 void draw_demo(double frame_ratio)
175 Sector* world = titlesession->get_current_sector();
176 Player* tux = world->player;
178 world->play_music(LEVEL_MUSIC);
180 global_frame_counter++;
181 tux->key_event((SDLKey) keymap.right,DOWN);
183 if(random_timer.check())
186 tux->key_event((SDLKey) keymap.jump,UP);
188 tux->key_event((SDLKey) keymap.jump,DOWN);
192 random_timer.start(rand() % 3000 + 3000);
196 // Wrap around at the end of the level back to the beginnig
197 if(world->solids->get_width() * 32 - 320 < tux->base.x)
202 tux->can_jump = true;
203 float last_tux_x_pos = tux->base.x;
204 world->action(frame_ratio);
207 // disabled for now, since with the new jump code we easily get deadlocks
208 // Jump if tux stays in the same position for one loop, ie. if he is
209 // stuck behind a wall
210 if (last_tux_x_pos == tux->base.x)
215 world->draw(*titlesession->context);
218 /* --- TITLE SCREEN --- */
221 random_timer.init(true);
225 st_pause_ticks_init();
227 titlesession = new GameSession(datadir + "/levels/misc/menu.stl", ST_GL_DEMO_GAME);
230 bkg_title = new Surface(datadir + "/images/background/arctis.jpg", IGNORE_ALPHA);
231 logo = new Surface(datadir + "/images/title/logo.png", USE_ALPHA);
232 img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", USE_ALPHA);
234 /* --- Main title loop: --- */
237 update_time = st_get_ticks();
238 random_timer.start(rand() % 2000 + 2000);
240 Menu::set_current(main_menu);
241 DrawingContext& context = *titlesession->context;
242 while (Menu::current())
244 // if we spent to much time on a menu entry
245 if( (update_time - last_update_time) > 1000)
246 update_time = last_update_time = st_get_ticks();
248 // Calculate the movement-factor
249 double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
250 if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
251 frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
252 /* Lower the frame_ratio that Tux doesn't jump to hectically throught the demo. */
256 while (SDL_PollEvent(&event))
260 Menu::current()->event(event);
262 // FIXME: QUIT signal should be handled more generic, not locally
263 if (event.type == SDL_QUIT)
264 Menu::set_current(0);
267 /* Draw the background: */
268 draw_demo(frame_ratio);
270 if (Menu::current() == main_menu)
271 context.draw_surface(logo, Vector(screen->w/2 - logo->w/2, 30),
272 LAYER_FOREGROUND1+1);
274 context.draw_text(white_small_text,
275 " SuperTux " VERSION "\n"
276 "Copyright (c) 2003 SuperTux Devel Team\n"
277 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
278 "are welcome to redistribute it under certain conditions; see the file COPYING\n"
279 "for details.\n", Vector(0, screen->h - 70), LAYER_FOREGROUND1);
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:
302 leveleditor = new LevelEditor();
305 Menu::set_current(main_menu);
308 display_text_file("CREDITS", bkg_title, 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);
328 if(confirm_dialog(bkg_title, 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 Menu::set_current(main_menu);
337 update_time = st_get_ticks();
339 else if (process_load_game_menu())
341 // FIXME: shouldn't be needed if GameSession doesn't relay on global variables
342 titlesession->get_current_sector()->activate();
343 titlesession->set_current();
344 //titletux.level_begin();
345 update_time = st_get_ticks();
348 else if(menu == contrib_menu)
350 check_contrib_menu();
352 else if (menu == contrib_subset_menu)
354 check_contrib_subset_menu();
358 mouse_cursor->draw(context);
360 context.do_drawing();
362 /* Set the time of the last update and the time of the current update */
363 last_update_time = update_time;
364 update_time = st_get_ticks();
376 delete img_choose_subset;