6 by Bill Kendrick & Tobias Glaesser
7 bill@newbreedsoftware.com
8 http://www.newbreedsoftware.com/supertux/
10 April 11, 2000 - March 15, 2004
25 #include <sys/types.h>
34 #include "high_scores.h"
42 #include "collision.h"
44 #include "particlesystem.h"
46 /* extern variables */
48 int game_started = false;
50 /* Local variables: */
52 static texture_type img_waves[3], img_water, img_pole, img_poletop, img_flag[2];
53 static texture_type img_cloud[2][4];
54 static SDL_Event event;
56 static char level_subset[100];
58 static int st_gl_mode;
59 static unsigned int last_update_time;
60 static unsigned int update_time;
61 static int pause_menu_frame;
64 GameSession* GameSession::current_ = 0;
66 /* Local function prototypes: */
67 void levelintro(void);
68 void loadshared(void);
69 void unloadshared(void);
70 void drawstatus(void);
71 void drawendscreen(void);
72 void drawresultscreen(void);
74 GameSession::GameSession()
80 GameSession::GameSession(const std::string& filename)
84 timer_init(&fps_timer, true);
85 timer_init(&frame_timer, true);
87 current_level.load(filename);
90 GameSession::GameSession(const std::string& subset, int levelnb, int mode)
94 timer_init(&fps_timer, true);
95 timer_init(&frame_timer, true);
106 strcpy(level_subset, subset.c_str());
108 if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
110 if (current_level.load(level_subset))
115 if(current_level.load(level_subset, level) != 0)
119 current_level.load_gfx();
121 activate_bad_guys(¤t_level);
122 activate_particle_systems();
123 current_level.load_song();
127 if(st_gl_mode != ST_GL_TEST)
130 if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
133 timer_init(&time_left,true);
136 if(st_gl_mode == ST_GL_LOAD_GAME)
141 GameSession::levelintro(void)
145 clearscreen(0, 0, 0);
147 sprintf(str, "LEVEL %d", level);
148 text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1);
150 sprintf(str, "%s", current_level.name.c_str());
151 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
153 sprintf(str, "TUX x %d", tux.lives);
154 text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
159 wait_for_event(event,1000,3000,true);
164 GameSession::start_timers()
166 timer_start(&time_left,current_level.time_left*1000);
167 st_pause_ticks_init();
168 update_time = st_get_ticks();
171 void activate_bad_guys(Level* plevel)
173 for (std::vector<BadGuyData>::iterator i = plevel->badguy_data.begin();
174 i != plevel->badguy_data.end();
177 add_bad_guy(i->x, i->y, i->kind);
182 GameSession::activate_particle_systems()
184 if(current_level.particle_system == "clouds")
186 particle_systems.push_back(new CloudParticleSystem);
188 else if(current_level.particle_system == "snow")
190 particle_systems.push_back(new SnowParticleSystem);
192 else if(current_level.particle_system != "")
194 st_abort("unknown particle system specified in level", "");
199 GameSession::process_events()
201 while (SDL_PollEvent(&event))
203 /* Check for menu-events, if the menu is shown */
208 case SDL_QUIT: /* Quit event - quit: */
211 case SDL_KEYDOWN: /* A keypress! */
212 key = event.key.keysym.sym;
214 if(tux.key_event(key,DOWN))
219 case SDLK_ESCAPE: /* Escape: Open/Close the menu: */
222 if(st_gl_mode == ST_GL_TEST)
226 Menu::set_current(game_menu);
228 st_pause_ticks_stop();
232 Menu::set_current(game_menu);
234 st_pause_ticks_start();
242 case SDL_KEYUP: /* A keyrelease! */
243 key = event.key.keysym.sym;
245 if(tux.key_event(key, UP))
256 st_pause_ticks_stop();
261 st_pause_ticks_start();
268 tux.size = !tux.size;
271 tux.base.height = 64;
274 tux.base.height = 32;
291 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
311 case SDL_JOYAXISMOTION:
312 switch(event.jaxis.axis)
315 if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
317 tux.input.left = DOWN;
318 tux.input.right = UP;
320 else if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
323 tux.input.right = DOWN;
327 tux.input.left = DOWN;
328 tux.input.right = DOWN;
332 if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
333 tux.input.down = DOWN;
334 else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
344 case SDL_JOYBUTTONDOWN:
345 if (event.jbutton.button == JOY_A)
347 else if (event.jbutton.button == JOY_B)
348 tux.input.fire = DOWN;
350 case SDL_JOYBUTTONUP:
351 if (event.jbutton.button == JOY_A)
353 else if (event.jbutton.button == JOY_B)
367 GameSession::action()
369 if (tux.is_dead() || next_level)
371 /* Tux either died, or reached the end of a level! */
378 /* End of a level! */
381 if(st_gl_mode != ST_GL_TEST)
388 current_level.cleanup();
400 /* No more lives!? */
404 if(st_gl_mode != ST_GL_TEST)
407 if(st_gl_mode != ST_GL_TEST)
409 if (score > hs_score)
413 current_level.cleanup();
418 } /* if (lives < 0) */
421 /* Either way, (re-)load the (next) level... */
425 current_level.cleanup();
427 if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
429 if(current_level.load(level_subset) != 0)
434 if(current_level.load(level_subset,level) != 0)
439 activate_bad_guys(¤t_level);
440 activate_particle_systems();
442 current_level.load_gfx();
444 current_level.load_song();
445 if(st_gl_mode != ST_GL_TEST)
449 play_current_music();
454 /* Handle bouncy distros: */
455 for (unsigned int i = 0; i < bouncy_distros.size(); i++)
456 bouncy_distro_action(&bouncy_distros[i]);
458 /* Handle broken bricks: */
459 for (unsigned int i = 0; i < broken_bricks.size(); i++)
460 broken_brick_action(&broken_bricks[i]);
462 /* Handle distro counting: */
463 if (counting_distros)
467 if (distro_counter <= 0)
468 counting_distros = -1;
471 // Handle all kinds of game objects
472 for (unsigned int i = 0; i < bouncy_bricks.size(); i++)
473 bouncy_brick_action(&bouncy_bricks[i]);
475 for (unsigned int i = 0; i < floating_scores.size(); i++)
476 floating_score_action(&floating_scores[i]);
478 for (unsigned int i = 0; i < bullets.size(); ++i)
479 bullet_action(&bullets[i]);
481 for (unsigned int i = 0; i < upgrades.size(); i++)
482 upgrade_action(&upgrades[i]);
484 for (unsigned int i = 0; i < bad_guys.size(); i++)
485 bad_guys[i].action();
487 /* update particle systems */
488 std::vector<ParticleSystem*>::iterator p;
489 for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
491 (*p)->simulate(frame_ratio);
494 /* Handle all possible collisions. */
500 /* --- GAME DRAW! --- */
508 if(timer_check(&super_bkgd_timer))
509 texture_draw(&img_super_bkgd, 0, 0);
512 /* Draw the real background */
513 if(current_level.bkgd_image[0] != '\0')
515 int s = (int)scroll_x / 30;
516 texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h);
517 texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h);
521 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
525 /* Draw particle systems (background) */
526 std::vector<ParticleSystem*>::iterator p;
527 for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
529 (*p)->draw(scroll_x, 0, 0);
532 /* Draw background: */
534 for (y = 0; y < 15; ++y)
536 for (x = 0; x < 21; ++x)
538 drawshape(32*x - fmodf(scroll_x, 32), y * 32,
539 current_level.bg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
543 /* Draw interactive tiles: */
544 for (y = 0; y < 15; ++y)
546 for (x = 0; x < 21; ++x)
548 drawshape(32*x - fmodf(scroll_x, 32), y * 32,
549 current_level.ia_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
553 /* (Bouncy bricks): */
554 for (unsigned int i = 0; i < bouncy_bricks.size(); ++i)
555 bouncy_brick_draw(&bouncy_bricks[i]);
557 for (unsigned int i = 0; i < bad_guys.size(); ++i)
562 for (unsigned int i = 0; i < bullets.size(); ++i)
563 bullet_draw(&bullets[i]);
565 for (unsigned int i = 0; i < floating_scores.size(); ++i)
566 floating_score_draw(&floating_scores[i]);
568 for (unsigned int i = 0; i < upgrades.size(); ++i)
569 upgrade_draw(&upgrades[i]);
571 for (unsigned int i = 0; i < bouncy_distros.size(); ++i)
572 bouncy_distro_draw(&bouncy_distros[i]);
574 for (unsigned int i = 0; i < broken_bricks.size(); ++i)
575 broken_brick_draw(&broken_bricks[i]);
577 /* Draw foreground: */
578 for (y = 0; y < 15; ++y)
580 for (x = 0; x < 21; ++x)
582 drawshape(32*x - fmodf(scroll_x, 32), y * 32,
583 current_level.fg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
587 /* Draw particle systems (foreground) */
588 for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
590 (*p)->draw(scroll_x, 0, 1);
597 int x = screen->h / 20;
598 for(int i = 0; i < x; ++i)
600 fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1);
602 fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
603 text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1);
608 menu_process_current();
609 mouse_cursor->draw();
612 /* (Update it all!) */
626 /* --- MAIN GAME LOOP!!! --- */
630 global_frame_counter = 0;
632 timer_init(&fps_timer,true);
633 timer_init(&frame_timer,true);
634 last_update_time = st_get_ticks();
638 clearscreen(0, 0, 0);
642 play_current_music();
644 while (SDL_PollEvent(&event))
652 /* Calculate the movement-factor */
653 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
654 if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
655 frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
657 if(!timer_check(&frame_timer))
659 timer_start(&frame_timer,25);
660 ++global_frame_counter;
665 tux.input.old_fire = tux.input.fire;
671 if(current_menu == game_menu)
673 switch (game_menu->check())
676 st_pause_ticks_stop();
679 update_load_save_game_menu(save_game_menu, false);
682 update_load_save_game_menu(load_game_menu, true);
685 st_pause_ticks_stop();
690 else if(current_menu == options_menu)
692 process_options_menu();
694 else if(current_menu == save_game_menu )
696 process_save_game_menu();
698 else if(current_menu == load_game_menu )
700 process_load_game_menu();
705 /* Handle actions: */
707 if(!game_pause && !show_menu)
709 /*float z = frame_ratio;
715 /* == 0: no more lives */
716 /* == -1: continues */
728 if(debug_mode && debug_fps)
731 /*Draw the current scene to the screen */
732 /*If the machine running the game is too slow
733 skip the drawing of the frame (so the calculations are more precise and
734 the FPS aren't affected).*/
735 /*if( ! fps_fps < 50.0 )
738 jump = true;*/ /*FIXME: Implement this tweak right.*/
741 /* Time stops in pause mode */
742 if(game_pause || show_menu )
747 /* Set the time of the last update and the time of the current update */
748 last_update_time = update_time;
749 update_time = st_get_ticks();
751 /* Pause till next frame, if the machine running the game is too fast: */
752 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
753 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
754 if(last_update_time >= update_time - 12 && !jump) {
756 update_time = st_get_ticks();
758 /*if((update_time - last_update_time) < 10)
759 SDL_Delay((11 - (update_time - last_update_time))/2);*/
765 if (timer_check(&time_left))
767 /* are we low on time ? */
768 if ((timer_get_left(&time_left) < TIME_WARNING)
769 && (get_current_music() != HURRYUP_MUSIC)) /* play the fast music */
771 set_current_music(HURRYUP_MUSIC);
772 play_current_music();
780 /* Calculate frames per second */
784 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
786 if(!timer_check(&fps_timer))
788 timer_start(&fps_timer,1000);
794 while (!done && !quit);
799 current_level.cleanup();
804 game_started = false;
809 /* Load graphics/sounds shared between all levels: */
815 texture_load(&smalltux_stand_left, datadir + "/images/shared/smalltux-left-6.png", USE_ALPHA);
816 texture_load(&smalltux_stand_right, datadir + "/images/shared/smalltux-right-6.png", USE_ALPHA);
818 texture_load(&smalltux_jump_left, datadir + "/images/shared/smalltux-jump-left.png", USE_ALPHA);
819 texture_load(&smalltux_jump_right, datadir + "/images/shared/smalltux-jump-right.png", USE_ALPHA);
822 texture_load(&tux_right[0], datadir + "/images/shared/smalltux-right-1.png", USE_ALPHA);
823 texture_load(&tux_right[1], datadir + "/images/shared/smalltux-right-2.png", USE_ALPHA);
824 texture_load(&tux_right[2], datadir + "/images/shared/smalltux-right-3.png", USE_ALPHA);
825 texture_load(&tux_right[3], datadir + "/images/shared/smalltux-right-4.png", USE_ALPHA);
826 texture_load(&tux_right[4], datadir + "/images/shared/smalltux-right-5.png", USE_ALPHA);
827 texture_load(&tux_right[5], datadir + "/images/shared/smalltux-right-6.png", USE_ALPHA);
828 texture_load(&tux_right[6], datadir + "/images/shared/smalltux-right-7.png", USE_ALPHA);
829 texture_load(&tux_right[7], datadir + "/images/shared/smalltux-right-8.png", USE_ALPHA);
832 texture_load(&tux_left[0], datadir + "/images/shared/smalltux-left-1.png", USE_ALPHA);
833 texture_load(&tux_left[1], datadir + "/images/shared/smalltux-left-2.png", USE_ALPHA);
834 texture_load(&tux_left[2], datadir + "/images/shared/smalltux-left-3.png", USE_ALPHA);
835 texture_load(&tux_left[3], datadir + "/images/shared/smalltux-left-4.png", USE_ALPHA);
836 texture_load(&tux_left[4], datadir + "/images/shared/smalltux-left-5.png", USE_ALPHA);
837 texture_load(&tux_left[5], datadir + "/images/shared/smalltux-left-6.png", USE_ALPHA);
838 texture_load(&tux_left[6], datadir + "/images/shared/smalltux-left-7.png", USE_ALPHA);
839 texture_load(&tux_left[7], datadir + "/images/shared/smalltux-left-8.png", USE_ALPHA);
841 texture_load(&firetux_right[0], datadir + "/images/shared/firetux-right-0.png", USE_ALPHA);
842 texture_load(&firetux_right[1], datadir + "/images/shared/firetux-right-1.png", USE_ALPHA);
843 texture_load(&firetux_right[2], datadir + "/images/shared/firetux-right-2.png", USE_ALPHA);
845 texture_load(&firetux_left[0], datadir + "/images/shared/firetux-left-0.png", USE_ALPHA);
846 texture_load(&firetux_left[1], datadir + "/images/shared/firetux-left-1.png", USE_ALPHA);
847 texture_load(&firetux_left[2], datadir + "/images/shared/firetux-left-2.png", USE_ALPHA);
850 texture_load(&cape_right[0], datadir + "/images/shared/cape-right-0.png",
853 texture_load(&cape_right[1], datadir + "/images/shared/cape-right-1.png",
856 texture_load(&cape_left[0], datadir + "/images/shared/cape-left-0.png",
859 texture_load(&cape_left[1], datadir + "/images/shared/cape-left-1.png",
862 texture_load(&bigtux_right[0], datadir + "/images/shared/bigtux-right-0.png",
865 texture_load(&bigtux_right[1], datadir + "/images/shared/bigtux-right-1.png",
868 texture_load(&bigtux_right[2], datadir + "/images/shared/bigtux-right-2.png",
871 texture_load(&bigtux_right_jump, datadir + "/images/shared/bigtux-right-jump.png", USE_ALPHA);
873 texture_load(&bigtux_left[0], datadir + "/images/shared/bigtux-left-0.png",
876 texture_load(&bigtux_left[1], datadir + "/images/shared/bigtux-left-1.png",
879 texture_load(&bigtux_left[2], datadir + "/images/shared/bigtux-left-2.png",
882 texture_load(&bigtux_left_jump, datadir + "/images/shared/bigtux-left-jump.png", USE_ALPHA);
884 texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
887 texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
890 texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
893 texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
896 texture_load(&bigfiretux_right[0], datadir + "/images/shared/bigfiretux-right-0.png",
899 texture_load(&bigfiretux_right[1], datadir + "/images/shared/bigfiretux-right-1.png",
902 texture_load(&bigfiretux_right[2], datadir + "/images/shared/bigfiretux-right-2.png",
905 texture_load(&bigfiretux_right_jump, datadir + "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
907 texture_load(&bigfiretux_left[0], datadir + "/images/shared/bigfiretux-left-0.png",
910 texture_load(&bigfiretux_left[1], datadir + "/images/shared/bigfiretux-left-1.png",
913 texture_load(&bigfiretux_left[2], datadir + "/images/shared/bigfiretux-left-2.png",
916 texture_load(&bigfiretux_left_jump, datadir + "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
918 texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
921 texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
924 texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
927 texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
931 texture_load(&ducktux_right, datadir +
932 "/images/shared/ducktux-right.png",
935 texture_load(&ducktux_left, datadir +
936 "/images/shared/ducktux-left.png",
939 texture_load(&skidtux_right, datadir +
940 "/images/shared/skidtux-right.png",
943 texture_load(&skidtux_left, datadir +
944 "/images/shared/skidtux-left.png",
947 texture_load(&duckfiretux_right, datadir +
948 "/images/shared/duckfiretux-right.png",
951 texture_load(&duckfiretux_left, datadir +
952 "/images/shared/duckfiretux-left.png",
955 texture_load(&skidfiretux_right, datadir +
956 "/images/shared/skidfiretux-right.png",
959 texture_load(&skidfiretux_left, datadir +
960 "/images/shared/skidfiretux-left.png",
966 texture_load(&img_box_full, datadir + "/images/shared/box-full.png",
968 texture_load(&img_box_empty, datadir + "/images/shared/box-empty.png",
975 texture_load(&img_water, datadir + "/images/shared/water.png", IGNORE_ALPHA);
977 texture_load(&img_waves[0], datadir + "/images/shared/waves-0.png",
980 texture_load(&img_waves[1], datadir + "/images/shared/waves-1.png",
983 texture_load(&img_waves[2], datadir + "/images/shared/waves-2.png",
989 texture_load(&img_pole, datadir + "/images/shared/pole.png", USE_ALPHA);
990 texture_load(&img_poletop, datadir + "/images/shared/poletop.png",
996 texture_load(&img_flag[0], datadir + "/images/shared/flag-0.png",
998 texture_load(&img_flag[1], datadir + "/images/shared/flag-1.png",
1004 texture_load(&img_cloud[0][0], datadir + "/images/shared/cloud-00.png",
1007 texture_load(&img_cloud[0][1], datadir + "/images/shared/cloud-01.png",
1010 texture_load(&img_cloud[0][2], datadir + "/images/shared/cloud-02.png",
1013 texture_load(&img_cloud[0][3], datadir + "/images/shared/cloud-03.png",
1017 texture_load(&img_cloud[1][0], datadir + "/images/shared/cloud-10.png",
1020 texture_load(&img_cloud[1][1], datadir + "/images/shared/cloud-11.png",
1023 texture_load(&img_cloud[1][2], datadir + "/images/shared/cloud-12.png",
1026 texture_load(&img_cloud[1][3], datadir + "/images/shared/cloud-13.png",
1035 texture_load(&img_mints, datadir + "/images/shared/mints.png", USE_ALPHA);
1036 texture_load(&img_coffee, datadir + "/images/shared/coffee.png", USE_ALPHA);
1041 texture_load(&img_bullet, datadir + "/images/shared/bullet.png", USE_ALPHA);
1043 texture_load(&img_red_glow, datadir + "/images/shared/red-glow.png",
1050 texture_load(&img_distro[0], datadir + "/images/shared/distro-0.png",
1053 texture_load(&img_distro[1], datadir + "/images/shared/distro-1.png",
1056 texture_load(&img_distro[2], datadir + "/images/shared/distro-2.png",
1059 texture_load(&img_distro[3], datadir + "/images/shared/distro-3.png",
1065 texture_load(&tux_life, datadir + "/images/shared/tux-life.png",
1070 texture_load(&img_golden_herring, datadir + "/images/shared/golden-herring.png",
1074 /* Super background: */
1076 texture_load(&img_super_bkgd, datadir + "/images/shared/super-bkgd.png",
1080 /* Sound effects: */
1082 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1083 // initialize sounds[i] with the correct pointer's value:
1084 // NULL or something else. And it will be dangerous to
1085 // play with not-initialized pointers.
1086 // This is also true with if (use_music)
1087 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1089 for (i = 0; i < NUM_SOUNDS; i++)
1090 sounds[i] = load_sound(datadir + soundfilenames[i]);
1093 herring_song = load_song(datadir + "/music/SALCON.MOD");
1097 /* Free shared data: */
1099 void unloadshared(void)
1103 for (i = 0; i < 3; i++)
1105 texture_free(&tux_right[i]);
1106 texture_free(&tux_left[i]);
1107 texture_free(&bigtux_right[i]);
1108 texture_free(&bigtux_left[i]);
1111 texture_free(&bigtux_right_jump);
1112 texture_free(&bigtux_left_jump);
1114 for (i = 0; i < 2; i++)
1116 texture_free(&cape_right[i]);
1117 texture_free(&cape_left[i]);
1118 texture_free(&bigcape_right[i]);
1119 texture_free(&bigcape_left[i]);
1122 texture_free(&ducktux_left);
1123 texture_free(&ducktux_right);
1125 texture_free(&skidtux_left);
1126 texture_free(&skidtux_right);
1130 texture_free(&img_box_full);
1131 texture_free(&img_box_empty);
1133 texture_free(&img_water);
1134 for (i = 0; i < 3; i++)
1135 texture_free(&img_waves[i]);
1137 texture_free(&img_pole);
1138 texture_free(&img_poletop);
1140 for (i = 0; i < 2; i++)
1141 texture_free(&img_flag[i]);
1143 texture_free(&img_mints);
1144 texture_free(&img_coffee);
1146 for (i = 0; i < 4; i++)
1148 texture_free(&img_distro[i]);
1149 texture_free(&img_cloud[0][i]);
1150 texture_free(&img_cloud[1][i]);
1153 texture_free(&img_golden_herring);
1155 for (i = 0; i < NUM_SOUNDS; i++)
1156 free_chunk(sounds[i]);
1158 /* free the herring song */
1159 free_music( herring_song );
1163 /* Draw a tile on the screen: */
1165 void drawshape(float x, float y, unsigned int c, Uint8 alpha)
1169 Tile* ptile = TileManager::instance()->get(c);
1172 if(ptile->images.size() > 1)
1174 texture_draw(&ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))],x,y, alpha);
1176 else if (ptile->images.size() == 1)
1178 texture_draw(&ptile->images[0],x,y, alpha);
1182 //printf("Tile not dravable %u\n", c);
1188 /* Bounce a brick: */
1189 void bumpbrick(float x, float y)
1191 add_bouncy_brick(((int)(x + 1) / 32) * 32,
1192 (int)(y / 32) * 32);
1194 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1198 void drawstatus(void)
1202 sprintf(str, "%d", score);
1203 text_draw(&white_text, "SCORE", 0, 0, 1);
1204 text_draw(&gold_text, str, 96, 0, 1);
1206 if(st_gl_mode != ST_GL_TEST)
1208 sprintf(str, "%d", hs_score);
1209 text_draw(&white_text, "HIGH", 0, 20, 1);
1210 text_draw(&gold_text, str, 96, 20, 1);
1214 text_draw(&white_text,"Press ESC To Return",0,20,1);
1217 if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
1219 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1220 text_draw(&white_text, "TIME", 224, 0, 1);
1221 text_draw(&gold_text, str, 304, 0, 1);
1224 sprintf(str, "%d", distros);
1225 text_draw(&white_text, "DISTROS", screen->h, 0, 1);
1226 text_draw(&gold_text, str, 608, 0, 1);
1228 text_draw(&white_text, "LIVES", screen->h, 20, 1);
1232 sprintf(str, "%2.1f", fps_fps);
1233 text_draw(&white_text, "FPS", screen->h, 40, 1);
1234 text_draw(&gold_text, str, screen->h + 60, 40, 1);
1237 for(int i=0; i < tux.lives; ++i)
1239 texture_draw(&tux_life,565+(18*i),20);
1244 void drawendscreen(void)
1248 clearscreen(0, 0, 0);
1250 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
1252 sprintf(str, "SCORE: %d", score);
1253 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1255 sprintf(str, "DISTROS: %d", distros);
1256 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1261 wait_for_event(event,2000,5000,true);
1264 void drawresultscreen(void)
1268 clearscreen(0, 0, 0);
1270 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
1272 sprintf(str, "SCORE: %d", score);
1273 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1275 sprintf(str, "DISTROS: %d", distros);
1276 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1281 wait_for_event(event,2000,5000,true);
1285 GameSession::savegame(int slot)
1287 char savefile[1024];
1291 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1293 fi = fopen(savefile, "wb");
1297 fprintf(stderr, "Warning: I could not open the slot file ");
1301 fputs(level_subset, fi);
1303 fwrite(&level,sizeof(int),1,fi);
1304 fwrite(&score,sizeof(int),1,fi);
1305 fwrite(&distros,sizeof(int),1,fi);
1306 fwrite(&scroll_x,sizeof(float),1,fi);
1307 fwrite(&tux,sizeof(Player),1,fi);
1308 timer_fwrite(&tux.invincible_timer,fi);
1309 timer_fwrite(&tux.skidding_timer,fi);
1310 timer_fwrite(&tux.safe_timer,fi);
1311 timer_fwrite(&tux.frame_timer,fi);
1312 timer_fwrite(&time_left,fi);
1313 ui = st_get_ticks();
1314 fwrite(&ui,sizeof(int),1,fi);
1321 GameSession::loadgame(int slot)
1323 char savefile[1024];
1328 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1330 fi = fopen(savefile, "rb");
1334 fprintf(stderr, "Warning: I could not open the slot file ");
1339 fgets(str, 100, fi);
1340 strcpy(level_subset, str);
1341 level_subset[strlen(level_subset)-1] = '\0';
1342 fread(&level,sizeof(int),1,fi);
1345 current_level.cleanup();
1346 if(current_level.load(level_subset,level) != 0)
1349 activate_bad_guys(¤t_level);
1350 activate_particle_systems();
1352 current_level.load_gfx();
1354 current_level.load_song();
1356 update_time = st_get_ticks();
1358 fread(&score, sizeof(int),1,fi);
1359 fread(&distros, sizeof(int),1,fi);
1360 fread(&scroll_x,sizeof(float),1,fi);
1361 fread(&tux, sizeof(Player), 1, fi);
1362 timer_fread(&tux.invincible_timer,fi);
1363 timer_fread(&tux.skidding_timer,fi);
1364 timer_fread(&tux.safe_timer,fi);
1365 timer_fread(&tux.frame_timer,fi);
1366 timer_fread(&time_left,fi);
1367 fread(&ui,sizeof(int),1,fi);
1373 std::string slotinfo(int slot)
1376 char slotfile[1024];
1380 sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1382 fi = fopen(slotfile, "rb");
1384 sprintf(tmp,"Slot %d - ",slot);
1392 fgets(str, 100, fi);
1393 str[strlen(str)-1] = '\0';
1395 strcat(tmp, " / Level:");
1396 fread(&slot_level,sizeof(int),1,fi);
1397 sprintf(str,"%d",slot_level);