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 world.add_bad_guy(i->x, i->y, i->kind);
182 GameSession::activate_particle_systems()
184 if(current_level.particle_system == "clouds")
186 world.particle_systems.push_back(new CloudParticleSystem);
188 else if(current_level.particle_system == "snow")
190 world.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();
456 /* update particle systems */
457 std::vector<ParticleSystem*>::iterator p;
458 for(p = world.particle_systems.begin(); p != world.particle_systems.end(); ++p)
460 (*p)->simulate(frame_ratio);
463 /* Handle all possible collisions. */
475 if(timer_check(&super_bkgd_timer))
476 texture_draw(&img_super_bkgd, 0, 0);
479 /* Draw the real background */
480 if(current_level.bkgd_image[0] != '\0')
482 int s = (int)scroll_x / 30;
483 texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h);
484 texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h);
488 clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
492 /* Draw particle systems (background) */
493 std::vector<ParticleSystem*>::iterator p;
494 for(p = world.particle_systems.begin(); p != world.particle_systems.end(); ++p)
496 (*p)->draw(scroll_x, 0, 0);
499 /* Draw background: */
500 for (y = 0; y < 15; ++y)
502 for (x = 0; x < 21; ++x)
504 drawshape(32*x - fmodf(scroll_x, 32), y * 32,
505 current_level.bg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
509 /* Draw interactive tiles: */
510 for (y = 0; y < 15; ++y)
512 for (x = 0; x < 21; ++x)
514 drawshape(32*x - fmodf(scroll_x, 32), y * 32,
515 current_level.ia_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
521 for (unsigned int i = 0; i < world.broken_bricks.size(); ++i)
522 broken_brick_draw(&world.broken_bricks[i]);
524 /* Draw foreground: */
525 for (y = 0; y < 15; ++y)
527 for (x = 0; x < 21; ++x)
529 drawshape(32*x - fmodf(scroll_x, 32), y * 32,
530 current_level.fg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
534 /* Draw particle systems (foreground) */
535 for(p = world.particle_systems.begin(); p != world.particle_systems.end(); ++p)
537 (*p)->draw(scroll_x, 0, 1);
544 int x = screen->h / 20;
545 for(int i = 0; i < x; ++i)
547 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);
549 fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
550 text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1);
555 menu_process_current();
556 mouse_cursor->draw();
559 /* (Update it all!) */
573 /* --- MAIN GAME LOOP!!! --- */
577 global_frame_counter = 0;
579 timer_init(&fps_timer,true);
580 timer_init(&frame_timer,true);
581 last_update_time = st_get_ticks();
585 clearscreen(0, 0, 0);
589 play_current_music();
591 while (SDL_PollEvent(&event))
599 /* Calculate the movement-factor */
600 frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
601 if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
602 frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
604 if(!timer_check(&frame_timer))
606 timer_start(&frame_timer,25);
607 ++global_frame_counter;
612 tux.input.old_fire = tux.input.fire;
618 if(current_menu == game_menu)
620 switch (game_menu->check())
623 st_pause_ticks_stop();
626 update_load_save_game_menu(save_game_menu, false);
629 update_load_save_game_menu(load_game_menu, true);
632 st_pause_ticks_stop();
637 else if(current_menu == options_menu)
639 process_options_menu();
641 else if(current_menu == save_game_menu )
643 process_save_game_menu();
645 else if(current_menu == load_game_menu )
647 process_load_game_menu();
652 /* Handle actions: */
654 if(!game_pause && !show_menu)
656 /*float z = frame_ratio;
662 /* == 0: no more lives */
663 /* == -1: continues */
675 if(debug_mode && debug_fps)
678 /*Draw the current scene to the screen */
679 /*If the machine running the game is too slow
680 skip the drawing of the frame (so the calculations are more precise and
681 the FPS aren't affected).*/
682 /*if( ! fps_fps < 50.0 )
685 jump = true;*/ /*FIXME: Implement this tweak right.*/
688 /* Time stops in pause mode */
689 if(game_pause || show_menu )
694 /* Set the time of the last update and the time of the current update */
695 last_update_time = update_time;
696 update_time = st_get_ticks();
698 /* Pause till next frame, if the machine running the game is too fast: */
699 /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
700 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
701 if(last_update_time >= update_time - 12 && !jump) {
703 update_time = st_get_ticks();
705 /*if((update_time - last_update_time) < 10)
706 SDL_Delay((11 - (update_time - last_update_time))/2);*/
712 if (timer_check(&time_left))
714 /* are we low on time ? */
715 if ((timer_get_left(&time_left) < TIME_WARNING)
716 && (get_current_music() != HURRYUP_MUSIC)) /* play the fast music */
718 set_current_music(HURRYUP_MUSIC);
719 play_current_music();
727 /* Calculate frames per second */
731 fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
733 if(!timer_check(&fps_timer))
735 timer_start(&fps_timer,1000);
741 while (!done && !quit);
746 current_level.cleanup();
751 game_started = false;
756 /* Load graphics/sounds shared between all levels: */
762 texture_load(&smalltux_stand_left, datadir + "/images/shared/smalltux-left-6.png", USE_ALPHA);
763 texture_load(&smalltux_stand_right, datadir + "/images/shared/smalltux-right-6.png", USE_ALPHA);
765 texture_load(&smalltux_jump_left, datadir + "/images/shared/smalltux-jump-left.png", USE_ALPHA);
766 texture_load(&smalltux_jump_right, datadir + "/images/shared/smalltux-jump-right.png", USE_ALPHA);
769 texture_load(&tux_right[0], datadir + "/images/shared/smalltux-right-1.png", USE_ALPHA);
770 texture_load(&tux_right[1], datadir + "/images/shared/smalltux-right-2.png", USE_ALPHA);
771 texture_load(&tux_right[2], datadir + "/images/shared/smalltux-right-3.png", USE_ALPHA);
772 texture_load(&tux_right[3], datadir + "/images/shared/smalltux-right-4.png", USE_ALPHA);
773 texture_load(&tux_right[4], datadir + "/images/shared/smalltux-right-5.png", USE_ALPHA);
774 texture_load(&tux_right[5], datadir + "/images/shared/smalltux-right-6.png", USE_ALPHA);
775 texture_load(&tux_right[6], datadir + "/images/shared/smalltux-right-7.png", USE_ALPHA);
776 texture_load(&tux_right[7], datadir + "/images/shared/smalltux-right-8.png", USE_ALPHA);
779 texture_load(&tux_left[0], datadir + "/images/shared/smalltux-left-1.png", USE_ALPHA);
780 texture_load(&tux_left[1], datadir + "/images/shared/smalltux-left-2.png", USE_ALPHA);
781 texture_load(&tux_left[2], datadir + "/images/shared/smalltux-left-3.png", USE_ALPHA);
782 texture_load(&tux_left[3], datadir + "/images/shared/smalltux-left-4.png", USE_ALPHA);
783 texture_load(&tux_left[4], datadir + "/images/shared/smalltux-left-5.png", USE_ALPHA);
784 texture_load(&tux_left[5], datadir + "/images/shared/smalltux-left-6.png", USE_ALPHA);
785 texture_load(&tux_left[6], datadir + "/images/shared/smalltux-left-7.png", USE_ALPHA);
786 texture_load(&tux_left[7], datadir + "/images/shared/smalltux-left-8.png", USE_ALPHA);
788 texture_load(&firetux_right[0], datadir + "/images/shared/firetux-right-0.png", USE_ALPHA);
789 texture_load(&firetux_right[1], datadir + "/images/shared/firetux-right-1.png", USE_ALPHA);
790 texture_load(&firetux_right[2], datadir + "/images/shared/firetux-right-2.png", USE_ALPHA);
792 texture_load(&firetux_left[0], datadir + "/images/shared/firetux-left-0.png", USE_ALPHA);
793 texture_load(&firetux_left[1], datadir + "/images/shared/firetux-left-1.png", USE_ALPHA);
794 texture_load(&firetux_left[2], datadir + "/images/shared/firetux-left-2.png", USE_ALPHA);
797 texture_load(&cape_right[0], datadir + "/images/shared/cape-right-0.png",
800 texture_load(&cape_right[1], datadir + "/images/shared/cape-right-1.png",
803 texture_load(&cape_left[0], datadir + "/images/shared/cape-left-0.png",
806 texture_load(&cape_left[1], datadir + "/images/shared/cape-left-1.png",
809 texture_load(&bigtux_right[0], datadir + "/images/shared/bigtux-right-0.png",
812 texture_load(&bigtux_right[1], datadir + "/images/shared/bigtux-right-1.png",
815 texture_load(&bigtux_right[2], datadir + "/images/shared/bigtux-right-2.png",
818 texture_load(&bigtux_right_jump, datadir + "/images/shared/bigtux-right-jump.png", USE_ALPHA);
820 texture_load(&bigtux_left[0], datadir + "/images/shared/bigtux-left-0.png",
823 texture_load(&bigtux_left[1], datadir + "/images/shared/bigtux-left-1.png",
826 texture_load(&bigtux_left[2], datadir + "/images/shared/bigtux-left-2.png",
829 texture_load(&bigtux_left_jump, datadir + "/images/shared/bigtux-left-jump.png", USE_ALPHA);
831 texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
834 texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
837 texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
840 texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
843 texture_load(&bigfiretux_right[0], datadir + "/images/shared/bigfiretux-right-0.png",
846 texture_load(&bigfiretux_right[1], datadir + "/images/shared/bigfiretux-right-1.png",
849 texture_load(&bigfiretux_right[2], datadir + "/images/shared/bigfiretux-right-2.png",
852 texture_load(&bigfiretux_right_jump, datadir + "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
854 texture_load(&bigfiretux_left[0], datadir + "/images/shared/bigfiretux-left-0.png",
857 texture_load(&bigfiretux_left[1], datadir + "/images/shared/bigfiretux-left-1.png",
860 texture_load(&bigfiretux_left[2], datadir + "/images/shared/bigfiretux-left-2.png",
863 texture_load(&bigfiretux_left_jump, datadir + "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
865 texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
868 texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
871 texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
874 texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
878 texture_load(&ducktux_right, datadir +
879 "/images/shared/ducktux-right.png",
882 texture_load(&ducktux_left, datadir +
883 "/images/shared/ducktux-left.png",
886 texture_load(&skidtux_right, datadir +
887 "/images/shared/skidtux-right.png",
890 texture_load(&skidtux_left, datadir +
891 "/images/shared/skidtux-left.png",
894 texture_load(&duckfiretux_right, datadir +
895 "/images/shared/duckfiretux-right.png",
898 texture_load(&duckfiretux_left, datadir +
899 "/images/shared/duckfiretux-left.png",
902 texture_load(&skidfiretux_right, datadir +
903 "/images/shared/skidfiretux-right.png",
906 texture_load(&skidfiretux_left, datadir +
907 "/images/shared/skidfiretux-left.png",
913 texture_load(&img_box_full, datadir + "/images/shared/box-full.png",
915 texture_load(&img_box_empty, datadir + "/images/shared/box-empty.png",
922 texture_load(&img_water, datadir + "/images/shared/water.png", IGNORE_ALPHA);
924 texture_load(&img_waves[0], datadir + "/images/shared/waves-0.png",
927 texture_load(&img_waves[1], datadir + "/images/shared/waves-1.png",
930 texture_load(&img_waves[2], datadir + "/images/shared/waves-2.png",
936 texture_load(&img_pole, datadir + "/images/shared/pole.png", USE_ALPHA);
937 texture_load(&img_poletop, datadir + "/images/shared/poletop.png",
943 texture_load(&img_flag[0], datadir + "/images/shared/flag-0.png",
945 texture_load(&img_flag[1], datadir + "/images/shared/flag-1.png",
951 texture_load(&img_cloud[0][0], datadir + "/images/shared/cloud-00.png",
954 texture_load(&img_cloud[0][1], datadir + "/images/shared/cloud-01.png",
957 texture_load(&img_cloud[0][2], datadir + "/images/shared/cloud-02.png",
960 texture_load(&img_cloud[0][3], datadir + "/images/shared/cloud-03.png",
964 texture_load(&img_cloud[1][0], datadir + "/images/shared/cloud-10.png",
967 texture_load(&img_cloud[1][1], datadir + "/images/shared/cloud-11.png",
970 texture_load(&img_cloud[1][2], datadir + "/images/shared/cloud-12.png",
973 texture_load(&img_cloud[1][3], datadir + "/images/shared/cloud-13.png",
982 texture_load(&img_mints, datadir + "/images/shared/mints.png", USE_ALPHA);
983 texture_load(&img_coffee, datadir + "/images/shared/coffee.png", USE_ALPHA);
988 texture_load(&img_bullet, datadir + "/images/shared/bullet.png", USE_ALPHA);
990 texture_load(&img_red_glow, datadir + "/images/shared/red-glow.png",
997 texture_load(&img_distro[0], datadir + "/images/shared/distro-0.png",
1000 texture_load(&img_distro[1], datadir + "/images/shared/distro-1.png",
1003 texture_load(&img_distro[2], datadir + "/images/shared/distro-2.png",
1006 texture_load(&img_distro[3], datadir + "/images/shared/distro-3.png",
1012 texture_load(&tux_life, datadir + "/images/shared/tux-life.png",
1017 texture_load(&img_golden_herring, datadir + "/images/shared/golden-herring.png",
1021 /* Super background: */
1023 texture_load(&img_super_bkgd, datadir + "/images/shared/super-bkgd.png",
1027 /* Sound effects: */
1029 /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1030 // initialize sounds[i] with the correct pointer's value:
1031 // NULL or something else. And it will be dangerous to
1032 // play with not-initialized pointers.
1033 // This is also true with if (use_music)
1034 Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1036 for (i = 0; i < NUM_SOUNDS; i++)
1037 sounds[i] = load_sound(datadir + soundfilenames[i]);
1040 herring_song = load_song(datadir + "/music/SALCON.MOD");
1044 /* Free shared data: */
1046 void unloadshared(void)
1050 for (i = 0; i < 3; i++)
1052 texture_free(&tux_right[i]);
1053 texture_free(&tux_left[i]);
1054 texture_free(&bigtux_right[i]);
1055 texture_free(&bigtux_left[i]);
1058 texture_free(&bigtux_right_jump);
1059 texture_free(&bigtux_left_jump);
1061 for (i = 0; i < 2; i++)
1063 texture_free(&cape_right[i]);
1064 texture_free(&cape_left[i]);
1065 texture_free(&bigcape_right[i]);
1066 texture_free(&bigcape_left[i]);
1069 texture_free(&ducktux_left);
1070 texture_free(&ducktux_right);
1072 texture_free(&skidtux_left);
1073 texture_free(&skidtux_right);
1077 texture_free(&img_box_full);
1078 texture_free(&img_box_empty);
1080 texture_free(&img_water);
1081 for (i = 0; i < 3; i++)
1082 texture_free(&img_waves[i]);
1084 texture_free(&img_pole);
1085 texture_free(&img_poletop);
1087 for (i = 0; i < 2; i++)
1088 texture_free(&img_flag[i]);
1090 texture_free(&img_mints);
1091 texture_free(&img_coffee);
1093 for (i = 0; i < 4; i++)
1095 texture_free(&img_distro[i]);
1096 texture_free(&img_cloud[0][i]);
1097 texture_free(&img_cloud[1][i]);
1100 texture_free(&img_golden_herring);
1102 for (i = 0; i < NUM_SOUNDS; i++)
1103 free_chunk(sounds[i]);
1105 /* free the herring song */
1106 free_music( herring_song );
1110 /* Draw a tile on the screen: */
1112 void drawshape(float x, float y, unsigned int c, Uint8 alpha)
1116 Tile* ptile = TileManager::instance()->get(c);
1119 if(ptile->images.size() > 1)
1121 texture_draw(&ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))],x,y, alpha);
1123 else if (ptile->images.size() == 1)
1125 texture_draw(&ptile->images[0],x,y, alpha);
1129 //printf("Tile not dravable %u\n", c);
1135 /* Bounce a brick: */
1136 void bumpbrick(float x, float y)
1138 world.add_bouncy_brick(((int)(x + 1) / 32) * 32,
1139 (int)(y / 32) * 32);
1141 play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1145 void drawstatus(void)
1149 sprintf(str, "%d", score);
1150 text_draw(&white_text, "SCORE", 0, 0, 1);
1151 text_draw(&gold_text, str, 96, 0, 1);
1153 if(st_gl_mode != ST_GL_TEST)
1155 sprintf(str, "%d", hs_score);
1156 text_draw(&white_text, "HIGH", 0, 20, 1);
1157 text_draw(&gold_text, str, 96, 20, 1);
1161 text_draw(&white_text,"Press ESC To Return",0,20,1);
1164 if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
1166 sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1167 text_draw(&white_text, "TIME", 224, 0, 1);
1168 text_draw(&gold_text, str, 304, 0, 1);
1171 sprintf(str, "%d", distros);
1172 text_draw(&white_text, "DISTROS", screen->h, 0, 1);
1173 text_draw(&gold_text, str, 608, 0, 1);
1175 text_draw(&white_text, "LIVES", screen->h, 20, 1);
1179 sprintf(str, "%2.1f", fps_fps);
1180 text_draw(&white_text, "FPS", screen->h, 40, 1);
1181 text_draw(&gold_text, str, screen->h + 60, 40, 1);
1184 for(int i=0; i < tux.lives; ++i)
1186 texture_draw(&tux_life,565+(18*i),20);
1191 void drawendscreen(void)
1195 clearscreen(0, 0, 0);
1197 text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
1199 sprintf(str, "SCORE: %d", score);
1200 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1202 sprintf(str, "DISTROS: %d", distros);
1203 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1208 wait_for_event(event,2000,5000,true);
1211 void drawresultscreen(void)
1215 clearscreen(0, 0, 0);
1217 text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
1219 sprintf(str, "SCORE: %d", score);
1220 text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1222 sprintf(str, "DISTROS: %d", distros);
1223 text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1228 wait_for_event(event,2000,5000,true);
1232 GameSession::savegame(int slot)
1234 char savefile[1024];
1238 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1240 fi = fopen(savefile, "wb");
1244 fprintf(stderr, "Warning: I could not open the slot file ");
1248 fputs(level_subset, fi);
1250 fwrite(&level,sizeof(int),1,fi);
1251 fwrite(&score,sizeof(int),1,fi);
1252 fwrite(&distros,sizeof(int),1,fi);
1253 fwrite(&scroll_x,sizeof(float),1,fi);
1254 fwrite(&tux,sizeof(Player),1,fi);
1255 timer_fwrite(&tux.invincible_timer,fi);
1256 timer_fwrite(&tux.skidding_timer,fi);
1257 timer_fwrite(&tux.safe_timer,fi);
1258 timer_fwrite(&tux.frame_timer,fi);
1259 timer_fwrite(&time_left,fi);
1260 ui = st_get_ticks();
1261 fwrite(&ui,sizeof(int),1,fi);
1268 GameSession::loadgame(int slot)
1270 char savefile[1024];
1275 sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1277 fi = fopen(savefile, "rb");
1281 fprintf(stderr, "Warning: I could not open the slot file ");
1286 fgets(str, 100, fi);
1287 strcpy(level_subset, str);
1288 level_subset[strlen(level_subset)-1] = '\0';
1289 fread(&level,sizeof(int),1,fi);
1292 current_level.cleanup();
1293 if(current_level.load(level_subset,level) != 0)
1295 world.arrays_free();
1296 activate_bad_guys(¤t_level);
1297 activate_particle_systems();
1299 current_level.load_gfx();
1301 current_level.load_song();
1303 update_time = st_get_ticks();
1305 fread(&score, sizeof(int),1,fi);
1306 fread(&distros, sizeof(int),1,fi);
1307 fread(&scroll_x,sizeof(float),1,fi);
1308 fread(&tux, sizeof(Player), 1, fi);
1309 timer_fread(&tux.invincible_timer,fi);
1310 timer_fread(&tux.skidding_timer,fi);
1311 timer_fread(&tux.safe_timer,fi);
1312 timer_fread(&tux.frame_timer,fi);
1313 timer_fread(&time_left,fi);
1314 fread(&ui,sizeof(int),1,fi);
1320 std::string slotinfo(int slot)
1323 char slotfile[1024];
1327 sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1329 fi = fopen(slotfile, "rb");
1331 sprintf(tmp,"Slot %d - ",slot);
1339 fgets(str, 100, fi);
1340 str[strlen(str)-1] = '\0';
1342 strcat(tmp, " / Level:");
1343 fread(&slot_level,sizeof(int),1,fi);
1344 sprintf(str,"%d",slot_level);