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 void display_credits();
67 std::vector<st_subset> contrib_subsets;
68 std::string current_contrib_subset;
70 void generate_contrib_menu()
72 string_list_type level_subsets = dsubdirs("/levels", "info");
74 contrib_menu->clear();
75 contrib_menu->additem(MN_LABEL,"Contrib Levels",0,0);
76 contrib_menu->additem(MN_HL,"",0,0);
78 for (int i = 0; i < level_subsets.num_items; ++i)
81 subset.load(level_subsets.item[i]);
82 contrib_menu->additem(MN_GOTO, subset.title.c_str(), i, contrib_subset_menu);
83 contrib_subsets.push_back(subset);
86 contrib_menu->additem(MN_HL,"",0,0);
87 contrib_menu->additem(MN_BACK,"Back",0,0);
89 string_list_free(&level_subsets);
92 void check_contrib_menu()
94 static int current_subset = -1;
96 int index = contrib_menu->check();
99 index -= 2; // FIXME: Hack
100 if (index >= 0 && index <= int(contrib_subsets.size()))
102 if (current_subset != index)
104 current_subset = index;
105 // FIXME: This shouln't be busy looping
106 st_subset& subset = contrib_subsets[index];
108 current_contrib_subset = subset.name;
110 std::cout << "Updating the contrib subset menu..." << subset.levels << std::endl;
112 contrib_subset_menu->clear();
114 contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0);
115 contrib_subset_menu->additem(MN_HL,"",0,0);
116 for (int i = 1; i <= subset.levels; ++i)
119 level.load(subset.name, i);
120 contrib_subset_menu->additem(MN_ACTION, level.name, 0, 0);
122 contrib_subset_menu->additem(MN_HL,"",0,0);
123 contrib_subset_menu->additem(MN_BACK, "Back", 0, 0);
133 void check_contrib_subset_menu()
135 int index = contrib_subset_menu->check();
138 if (contrib_subset_menu->get_item(index).kind == MN_ACTION)
140 index -= 1; // FIXME: Hack
141 std::cout << "Sarting level: " << index << std::endl;
143 GameSession session(current_contrib_subset, index, ST_GL_PLAY);
145 Menu::set_current(main_menu);
150 void draw_background()
152 /* Draw the title background: */
154 bkg_title->draw_bg();
157 void draw_demo(GameSession* session, double frame_ratio)
159 World::set_current(session->get_world());
160 //World* world = session->get_world();
161 Level* plevel = session->get_level();
162 Player* tux = session->get_world()->get_tux();
164 session->get_world()->play_music(LEVEL_MUSIC);
167 // update particle systems
168 std::vector<ParticleSystem*>::iterator p;
169 for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
171 (*p)->simulate(frame_ratio);
174 // Draw particle systems (background)
175 for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
177 (*p)->draw(scroll_x, 0, 0);
181 // Draw interactive tiles:
182 for (int y = 0; y < 15; ++y)
184 for (int x = 0; x < 21; ++x)
186 Tile::draw(32*x - fmodf(scroll_x, 32), y * 32,
187 plevel->ia_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
191 global_frame_counter++;
192 tux->key_event((SDLKey) keymap.right,DOWN);
194 if(random_timer.check())
197 tux->key_event((SDLKey) keymap.jump,UP);
199 tux->key_event((SDLKey) keymap.jump,DOWN);
203 random_timer.start(rand() % 3000 + 3000);
207 // Wrap around at the end of the level back to the beginnig
208 if(plevel->width * 32 - 320 < tux->base.x)
210 tux->base.x = tux->base.x - (plevel->width * 32 - 640);
211 scroll_x = tux->base.x - 320;
214 float last_tux_x_pos = tux->base.x;
215 tux->action(frame_ratio);
217 // Jump if tux stays in the same position for one loop, ie. if he is
218 // stuck behind a wall
219 if (last_tux_x_pos == tux->base.x)
225 /* --- TITLE SCREEN --- */
229 random_timer.init(true);
233 st_pause_ticks_init();
235 GameSession session(datadir + "/levels/misc/menu.stl", 0, ST_GL_DEMO_GAME);
237 clearscreen(0, 0, 0);
241 bkg_title = new Surface(datadir + "/images/title/background.jpg", IGNORE_ALPHA);
242 logo = new Surface(datadir + "/images/title/logo.png", USE_ALPHA);
243 img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", USE_ALPHA);
245 /* --- Main title loop: --- */
248 /* Draw the title background: */
249 bkg_title->draw_bg();
251 update_time = st_get_ticks();
252 random_timer.start(rand() % 2000 + 2000);
254 Menu::set_current(main_menu);
255 while (Menu::current())
257 // Calculate the movement-factor
258 double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
259 if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
260 frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
261 /* Lower the frame_ratio that Tux doesn't jump to hectically throught the demo. */
265 while (SDL_PollEvent(&event))
269 Menu::current()->event(event);
271 // FIXME: QUIT signal should be handled more generic, not locally
272 if (event.type == SDL_QUIT)
273 Menu::set_current(0);
276 /* Draw the background: */
278 draw_demo(&session, frame_ratio);
280 if (Menu::current() == main_menu)
281 logo->draw( 160, 30);
283 white_small_text->draw(" SuperTux " VERSION "\n"
284 "Copyright (c) 2003 SuperTux Devel Team\n"
285 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
286 "are welcome to redistribute it under certain conditions; see the file COPYING\n"
290 /* Don't draw menu, if quit is true */
291 Menu* menu = Menu::current();
297 if(menu == main_menu)
299 switch (main_menu->check())
302 // Start Game, ie. goto the slots menu
303 update_load_save_game_menu(load_game_menu);
307 puts("Entering contrib menu");
308 generate_contrib_menu();
313 Menu::set_current(main_menu);
317 Menu::set_current(main_menu);
320 Menu::set_current(0);
324 else if(menu == options_menu)
326 process_options_menu();
328 else if(menu == load_game_menu)
330 if (process_load_game_menu())
332 // FIXME: shouldn't be needed if GameSession doesn't relay on global variables
335 //titletux.level_begin();
336 update_time = st_get_ticks();
339 else if(menu == contrib_menu)
341 check_contrib_menu();
343 else if (menu == contrib_subset_menu)
345 check_contrib_subset_menu();
349 mouse_cursor->draw();
353 /* Set the time of the last update and the time of the current update */
354 last_update_time = update_time;
355 update_time = st_get_ticks();
370 #define ITEMS_SPACE 4
372 void display_credits()
381 string_list_type names;
383 string_list_init(&names);
384 sprintf(filename,"%s/CREDITS", datadir.c_str());
385 if((fi = fopen(filename,"r")) != NULL)
387 while(fgets(temp, sizeof(temp), fi) != NULL)
389 temp[strlen(temp)-1]='\0';
390 string_list_add_item(&names,temp);
396 string_list_add_item(&names,"Credits were not found!");
397 string_list_add_item(&names,"Shame on the guy, who");
398 string_list_add_item(&names,"forgot to include them");
399 string_list_add_item(&names,"in your SuperTux distribution.");
403 timer.init(SDL_GetTicks());
410 length = names.num_items;
412 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
416 /* in case of input, exit */
418 while(SDL_PollEvent(&event))
422 switch(event.key.keysym.sym)
451 else if(speed < -MAX_VEL)
454 /* draw the credits */
458 white_big_text->drawf("- Credits -", 0, screen->h-scroll, A_HMIDDLE, A_TOP, 2);
461 for(int i = 0; i < length; i++)
463 switch(names.item[i][0])
466 white_small_text->drawf(names.item[i], 0, 60+screen->h+y-scroll, A_HMIDDLE, A_TOP, 1);
467 y += white_small_text->h+ITEMS_SPACE;
470 white_text->drawf(names.item[i], 0, 60+screen->h+y-scroll, A_HMIDDLE, A_TOP, 1);
471 y += white_text->h+ITEMS_SPACE;
474 white_big_text->drawf(names.item[i], 0, 60+screen->h+y-scroll, A_HMIDDLE, A_TOP, 3);
475 y += white_big_text->h+ITEMS_SPACE;
478 blue_text->drawf(names.item[i], 0, 60+screen->h+y-scroll, A_HMIDDLE, A_TOP, 1);
479 y += blue_text->h+ITEMS_SPACE;
486 if(60+screen->h+y-scroll < 0 && 20+60+screen->h+y-scroll < 0)
495 if(timer.get_left() < 0)
501 string_list_free(&names);
503 SDL_EnableKeyRepeat(0, 0); // disables key repeating
504 Menu::set_current(main_menu);