fc3e73c7751c5781bd32f999804ce5471b5a405f
[supertux.git] / src / gameloop.cpp
1 /*
2   gameloop.c
3   
4   Super Tux - Game Loop!
5   
6   by Bill Kendrick & Tobias Glaesser
7   bill@newbreedsoftware.com
8   http://www.newbreedsoftware.com/supertux/
9   
10   April 11, 2000 - March 15, 2004
11 */
12
13 #include <assert.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <math.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <math.h>
21 #include <time.h>
22 #include <SDL.h>
23
24 #ifndef WIN32
25 #include <sys/types.h>
26 #include <ctype.h>
27 #endif
28
29 #include "defines.h"
30 #include "globals.h"
31 #include "gameloop.h"
32 #include "screen.h"
33 #include "setup.h"
34 #include "high_scores.h"
35 #include "menu.h"
36 #include "badguy.h"
37 #include "world.h"
38 #include "special.h"
39 #include "player.h"
40 #include "level.h"
41 #include "scene.h"
42 #include "collision.h"
43 #include "tile.h"
44 #include "particlesystem.h"
45
46 /* extern variables */
47
48 int game_started = false;
49
50 /* Local variables: */
51
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;
55 static SDLKey key;
56 static char level_subset[100];
57 static float fps_fps;
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;
62 static int debug_fps;
63
64 GameSession* GameSession::current_ = 0;
65
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);
73
74 GameSession::GameSession()
75 {
76   current_ = this;
77   assert(0);
78 }
79
80 GameSession::GameSession(const std::string& filename)
81 {
82   current_ = this;
83
84   timer_init(&fps_timer, true);
85   timer_init(&frame_timer, true);
86
87   current_level.load(filename);
88 }
89
90 GameSession::GameSession(const std::string& subset, int levelnb, int mode)
91 {
92   current_ = this;
93
94   timer_init(&fps_timer, true);
95   timer_init(&frame_timer, true);
96
97   game_started = true;
98
99   st_gl_mode = mode;
100   level = levelnb;
101
102   /* Init the game: */
103   arrays_free();
104   set_defaults();
105
106   strcpy(level_subset, subset.c_str());
107
108   if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
109     {
110       if (current_level.load(level_subset))
111         exit(1);
112     }
113   else
114     {
115       if(current_level.load(level_subset, level) != 0)
116         exit(1);
117     }
118
119   current_level.load_gfx();
120   loadshared();
121   activate_bad_guys(&current_level);
122   activate_particle_systems();
123   current_level.load_song();
124
125   tux.init();
126
127   if(st_gl_mode != ST_GL_TEST)
128     load_hs();
129
130   if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
131     levelintro();
132
133   timer_init(&time_left,true);
134   start_timers();
135
136   if(st_gl_mode == ST_GL_LOAD_GAME)
137     loadgame(levelnb);
138 }
139
140 void
141 GameSession::levelintro(void)
142 {
143   char str[60];
144   /* Level Intro: */
145   clearscreen(0, 0, 0);
146
147   sprintf(str, "LEVEL %d", level);
148   text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1);
149
150   sprintf(str, "%s", current_level.name.c_str());
151   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
152
153   sprintf(str, "TUX x %d", tux.lives);
154   text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
155
156   flipscreen();
157
158   SDL_Event event;
159   wait_for_event(event,1000,3000,true);
160 }
161
162 /* Reset Timers */
163 void
164 GameSession::start_timers()
165 {
166   timer_start(&time_left,current_level.time_left*1000);
167   st_pause_ticks_init();
168   update_time = st_get_ticks();
169 }
170
171 void activate_bad_guys(Level* plevel)
172 {
173   for (std::vector<BadGuyData>::iterator i = plevel->badguy_data.begin();
174        i != plevel->badguy_data.end();
175        ++i)
176     {
177       add_bad_guy(i->x, i->y, i->kind);
178     }
179 }
180
181 void
182 GameSession::activate_particle_systems()
183 {
184   if(current_level.particle_system == "clouds")
185     {
186       particle_systems.push_back(new CloudParticleSystem);
187     }
188   else if(current_level.particle_system == "snow")
189     {
190       particle_systems.push_back(new SnowParticleSystem);
191     }
192   else if(current_level.particle_system != "")
193     {
194       st_abort("unknown particle system specified in level", "");
195     }
196 }
197
198 void
199 GameSession::process_events()
200 {
201   while (SDL_PollEvent(&event))
202     {
203           /* Check for menu-events, if the menu is shown */
204           if(show_menu)
205             menu_event(event);
206       switch(event.type)
207         {
208         case SDL_QUIT:        /* Quit event - quit: */
209           quit = 1;
210           break;
211         case SDL_KEYDOWN:     /* A keypress! */
212           key = event.key.keysym.sym;
213
214           if(tux.key_event(key,DOWN))
215             break;
216
217           switch(key)
218             {
219             case SDLK_ESCAPE:    /* Escape: Open/Close the menu: */
220               if(!game_pause)
221                 {
222                   if(st_gl_mode == ST_GL_TEST)
223                     quit = 1;
224                   else if(show_menu)
225                     {
226                       Menu::set_current(game_menu);
227                       show_menu = 0;
228                       st_pause_ticks_stop();
229                     }
230                   else
231                     {
232                       Menu::set_current(game_menu);
233                       show_menu = 1;
234                       st_pause_ticks_start();
235                     }
236                 }
237               break;
238             default:
239               break;
240             }
241           break;
242         case SDL_KEYUP:      /* A keyrelease! */
243           key = event.key.keysym.sym;
244
245           if(tux.key_event(key, UP))
246             break;
247
248           switch(key)
249             {
250             case SDLK_p:
251               if(!show_menu)
252                 {
253                   if(game_pause)
254                     {
255                       game_pause = 0;
256                       st_pause_ticks_stop();
257                     }
258                   else
259                     {
260                       game_pause = 1;
261                       st_pause_ticks_start();
262                     }
263                 }
264               break;
265             case SDLK_TAB:
266               if(debug_mode)
267                 {
268                   tux.size = !tux.size;
269                   if(tux.size == BIG)
270                     {
271                       tux.base.height = 64;
272                     }
273                   else
274                     tux.base.height = 32;
275                 }
276               break;
277             case SDLK_END:
278               if(debug_mode)
279                 distros += 50;
280               break;
281             case SDLK_SPACE:
282               if(debug_mode)
283                 next_level = 1;
284               break;
285             case SDLK_DELETE:
286               if(debug_mode)
287                 tux.got_coffee = 1;
288               break;
289             case SDLK_INSERT:
290               if(debug_mode)
291                 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
292               break;
293             case SDLK_l:
294               if(debug_mode)
295                 --tux.lives;
296               break;
297             case SDLK_s:
298               if(debug_mode)
299                 score += 1000;
300             case SDLK_f:
301               if(debug_fps)
302                 debug_fps = false;
303               else
304                 debug_fps = true;
305               break;
306             default:
307               break;
308             }
309           break;
310
311         case SDL_JOYAXISMOTION:
312           switch(event.jaxis.axis)
313             {
314             case JOY_X:
315               if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
316                 {
317                   tux.input.left  = DOWN;
318                   tux.input.right = UP;
319                 }
320               else if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
321                 {
322                   tux.input.left  = UP;
323                   tux.input.right = DOWN;
324                 }
325               else
326                 {
327                   tux.input.left  = DOWN;
328                   tux.input.right = DOWN;
329                 }
330               break;
331             case JOY_Y:
332               if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
333                 tux.input.down = DOWN;
334               else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
335                 tux.input.down = UP;
336               else
337                 tux.input.down = UP;
338               
339               break;
340             default:
341               break;
342             }
343           break;
344         case SDL_JOYBUTTONDOWN:
345           if (event.jbutton.button == JOY_A)
346             tux.input.up = DOWN;
347           else if (event.jbutton.button == JOY_B)
348             tux.input.fire = DOWN;
349           break;
350         case SDL_JOYBUTTONUP:
351           if (event.jbutton.button == JOY_A)
352             tux.input.up = UP;
353           else if (event.jbutton.button == JOY_B)
354             tux.input.fire = UP;
355             
356           break;
357
358         default:
359           break;
360
361         }  /* switch */
362
363     } /* while */
364 }
365
366 int
367 GameSession::action()
368 {
369   if (tux.is_dead() || next_level)
370     {
371       /* Tux either died, or reached the end of a level! */
372
373       halt_music();
374
375
376       if (next_level)
377         {
378           /* End of a level! */
379           level++;
380           next_level = 0;
381           if(st_gl_mode != ST_GL_TEST)
382             {
383               drawresultscreen();
384             }
385           else
386             {
387               level_free_gfx();
388               current_level.cleanup();
389               level_free_song();
390               unloadshared();
391               arrays_free();
392               return(0);
393             }
394           tux.level_begin();
395         }
396       else
397         {
398           tux.is_dying();
399
400           /* No more lives!? */
401
402           if (tux.lives < 0)
403             {
404               if(st_gl_mode != ST_GL_TEST)
405                 drawendscreen();
406
407               if(st_gl_mode != ST_GL_TEST)
408                 {
409                   if (score > hs_score)
410                     save_hs(score);
411                 }
412               level_free_gfx();
413               current_level.cleanup();
414               level_free_song();
415               unloadshared();
416               arrays_free();
417               return(0);
418             } /* if (lives < 0) */
419         }
420
421       /* Either way, (re-)load the (next) level... */
422
423       tux.level_begin();
424       set_defaults();
425       current_level.cleanup();
426
427       if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
428         {
429           if(current_level.load(level_subset) != 0)
430             return 0;
431         }
432       else
433         {
434           if(current_level.load(level_subset,level) != 0)
435             return 0;
436         }
437
438       arrays_free();
439       activate_bad_guys(&current_level);
440       activate_particle_systems();
441       level_free_gfx();
442       current_level.load_gfx();
443       level_free_song();
444       current_level.load_song();
445       if(st_gl_mode != ST_GL_TEST)
446         levelintro();
447       start_timers();
448       /* Play music: */
449       play_current_music();
450     }
451
452   tux.action();
453
454   /* Handle bouncy distros: */
455   for (unsigned int i = 0; i < bouncy_distros.size(); i++)
456     bouncy_distro_action(&bouncy_distros[i]);
457
458   /* Handle broken bricks: */
459   for (unsigned int i = 0; i < broken_bricks.size(); i++)
460       broken_brick_action(&broken_bricks[i]);
461
462   /* Handle distro counting: */
463   if (counting_distros)
464     {
465       distro_counter--;
466
467       if (distro_counter <= 0)
468         counting_distros = -1;
469     }
470
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]);
474   
475   for (unsigned int i = 0; i < floating_scores.size(); i++)
476     floating_score_action(&floating_scores[i]);
477
478   for (unsigned int i = 0; i < bullets.size(); ++i)
479     bullet_action(&bullets[i]);
480   
481   for (unsigned int i = 0; i < upgrades.size(); i++)
482     upgrade_action(&upgrades[i]);
483
484   for (unsigned int i = 0; i < bad_guys.size(); i++)
485     bad_guys[i].action();
486
487   /* update particle systems */
488   std::vector<ParticleSystem*>::iterator p;
489   for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
490     {
491       (*p)->simulate(frame_ratio);
492     }
493
494   /* Handle all possible collisions. */
495   collision_handler();
496
497   return -1;
498 }
499
500 /* --- GAME DRAW! --- */
501
502 void 
503 GameSession::draw()
504 {
505   int y,x;
506
507   /* Draw screen: */
508   if(timer_check(&super_bkgd_timer))
509     texture_draw(&img_super_bkgd, 0, 0);
510   else
511     {
512       /* Draw the real background */
513       if(current_level.bkgd_image[0] != '\0')
514         {
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);
518         }
519       else
520         {
521           clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
522         }
523     }
524
525   /* Draw particle systems (background) */
526   std::vector<ParticleSystem*>::iterator p;
527   for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
528     {
529       (*p)->draw(scroll_x, 0, 0);
530     }
531
532   /* Draw background: */
533
534   for (y = 0; y < 15; ++y)
535     {
536       for (x = 0; x < 21; ++x)
537         {
538           drawshape(32*x - fmodf(scroll_x, 32), y * 32,
539                     current_level.bg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
540         }
541     }
542
543   /* Draw interactive tiles: */
544   for (y = 0; y < 15; ++y)
545     {
546       for (x = 0; x < 21; ++x)
547         {
548           drawshape(32*x - fmodf(scroll_x, 32), y * 32,
549                     current_level.ia_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
550         }
551     }
552
553   /* (Bouncy bricks): */
554   for (unsigned int i = 0; i < bouncy_bricks.size(); ++i)
555     bouncy_brick_draw(&bouncy_bricks[i]);
556
557   for (unsigned int i = 0; i < bad_guys.size(); ++i)
558     bad_guys[i].draw();
559
560   tux.draw();
561
562   for (unsigned int i = 0; i < bullets.size(); ++i)
563     bullet_draw(&bullets[i]);
564
565   for (unsigned int i = 0; i < floating_scores.size(); ++i)
566     floating_score_draw(&floating_scores[i]);
567
568   for (unsigned int i = 0; i < upgrades.size(); ++i)
569     upgrade_draw(&upgrades[i]);
570
571   for (unsigned int i = 0; i < bouncy_distros.size(); ++i)
572     bouncy_distro_draw(&bouncy_distros[i]);
573
574   for (unsigned int i = 0; i < broken_bricks.size(); ++i)
575     broken_brick_draw(&broken_bricks[i]);
576
577   /* Draw foreground: */
578   for (y = 0; y < 15; ++y)
579     {
580       for (x = 0; x < 21; ++x)
581         {
582           drawshape(32*x - fmodf(scroll_x, 32), y * 32,
583                     current_level.fg_tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
584         }
585     }
586
587   /* Draw particle systems (foreground) */
588   for(p = particle_systems.begin(); p != particle_systems.end(); ++p)
589     {
590       (*p)->draw(scroll_x, 0, 1);
591     }
592
593   drawstatus();
594
595   if(game_pause)
596     {
597       int x = screen->h / 20;
598       for(int i = 0; i < x; ++i)
599         {
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);
601         }
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);
604     }
605
606   if(show_menu)
607   {
608     menu_process_current();
609     mouse_cursor->draw();
610   }
611
612   /* (Update it all!) */
613   updatescreen();
614 }
615
616
617 int
618 GameSession::run()
619 {
620   current_ = this;
621   
622   int  fps_cnt;
623   bool jump;
624   bool done;
625
626   /* --- MAIN GAME LOOP!!! --- */
627   jump = false;
628   done = false;
629   quit = 0;
630   global_frame_counter = 0;
631   game_pause = 0;
632   timer_init(&fps_timer,true);
633   timer_init(&frame_timer,true);
634   last_update_time = st_get_ticks();
635   fps_cnt = 0;
636
637   /* Clear screen: */
638   clearscreen(0, 0, 0);
639   updatescreen();
640
641   /* Play music: */
642   play_current_music();
643
644   while (SDL_PollEvent(&event))
645   {}
646
647   draw();
648   do
649     {
650       jump = false;
651
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;
656
657       if(!timer_check(&frame_timer))
658         {
659           timer_start(&frame_timer,25);
660           ++global_frame_counter;
661         }
662
663       /* Handle events: */
664
665       tux.input.old_fire = tux.input.fire;
666
667       process_events();
668
669       if(show_menu)
670         {
671           if(current_menu == game_menu)
672             {
673               switch (game_menu->check())
674                 {
675                 case 2:
676                   st_pause_ticks_stop();
677                   break;
678                 case 3:
679                   update_load_save_game_menu(save_game_menu, false);
680                   break;
681                 case 4:
682                   update_load_save_game_menu(load_game_menu, true);
683                   break;
684                 case 7:
685                   st_pause_ticks_stop();
686                   done = true;
687                   break;
688                 }
689             }
690           else if(current_menu == options_menu)
691             {
692               process_options_menu();
693             }
694           else if(current_menu == save_game_menu )
695             {
696               process_save_game_menu();
697             }
698           else if(current_menu == load_game_menu )
699             {
700               process_load_game_menu();
701             }
702         }
703
704
705       /* Handle actions: */
706
707       if(!game_pause && !show_menu)
708         {
709           /*float z = frame_ratio;
710             frame_ratio = 1;
711             while(z >= 1)
712             {*/
713           if (action() == 0)
714             {
715               /* == 0: no more lives */
716               /* == -1: continues */
717               return 0;
718             }
719           /*  --z;
720                      }*/
721         }
722       else
723         {
724           ++pause_menu_frame;
725           SDL_Delay(50);
726         }
727
728       if(debug_mode && debug_fps)
729         SDL_Delay(60);
730
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 )
736         game_draw();
737         else
738         jump = true;*/ /*FIXME: Implement this tweak right.*/
739       draw();
740
741       /* Time stops in pause mode */
742       if(game_pause || show_menu )
743         {
744           continue;
745         }
746
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();
750
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) {
755         SDL_Delay(10);
756         update_time = st_get_ticks();
757       }
758       /*if((update_time - last_update_time) < 10)
759         SDL_Delay((11 - (update_time - last_update_time))/2);*/
760
761
762
763       /* Handle time: */
764
765       if (timer_check(&time_left))
766         {
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 */
770             {
771               set_current_music(HURRYUP_MUSIC);
772               play_current_music();
773             }
774
775         }
776       else
777         tux.kill(KILL);
778
779
780       /* Calculate frames per second */
781       if(show_fps)
782         {
783           ++fps_cnt;
784           fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
785
786           if(!timer_check(&fps_timer))
787             {
788               timer_start(&fps_timer,1000);
789               fps_cnt = 0;
790             }
791         }
792
793     }
794   while (!done && !quit);
795
796   halt_music();
797
798   level_free_gfx();
799   current_level.cleanup();
800   level_free_song();
801   unloadshared();
802   arrays_free();
803
804   game_started = false;
805
806   return(quit);
807 }
808
809 /* Load graphics/sounds shared between all levels: */
810 void loadshared()
811 {
812   int i;
813
814   /* Tuxes: */
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);
817
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);
820
821   tux_right.resize(8);
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);
830
831   tux_left.resize(8);
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);
840
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);
844
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);
848
849
850   texture_load(&cape_right[0], datadir + "/images/shared/cape-right-0.png",
851                USE_ALPHA);
852
853   texture_load(&cape_right[1], datadir + "/images/shared/cape-right-1.png",
854                USE_ALPHA);
855
856   texture_load(&cape_left[0], datadir + "/images/shared/cape-left-0.png",
857                USE_ALPHA);
858
859   texture_load(&cape_left[1], datadir + "/images/shared/cape-left-1.png",
860                USE_ALPHA);
861
862   texture_load(&bigtux_right[0], datadir + "/images/shared/bigtux-right-0.png",
863                USE_ALPHA);
864
865   texture_load(&bigtux_right[1], datadir + "/images/shared/bigtux-right-1.png",
866                USE_ALPHA);
867
868   texture_load(&bigtux_right[2], datadir + "/images/shared/bigtux-right-2.png",
869                USE_ALPHA);
870
871   texture_load(&bigtux_right_jump, datadir + "/images/shared/bigtux-right-jump.png", USE_ALPHA);
872
873   texture_load(&bigtux_left[0], datadir + "/images/shared/bigtux-left-0.png",
874                USE_ALPHA);
875
876   texture_load(&bigtux_left[1], datadir + "/images/shared/bigtux-left-1.png",
877                USE_ALPHA);
878
879   texture_load(&bigtux_left[2], datadir + "/images/shared/bigtux-left-2.png",
880                USE_ALPHA);
881
882   texture_load(&bigtux_left_jump, datadir + "/images/shared/bigtux-left-jump.png", USE_ALPHA);
883
884   texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
885                USE_ALPHA);
886
887   texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
888                USE_ALPHA);
889
890   texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
891                USE_ALPHA);
892
893   texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
894                USE_ALPHA);
895
896   texture_load(&bigfiretux_right[0], datadir + "/images/shared/bigfiretux-right-0.png",
897                USE_ALPHA);
898
899   texture_load(&bigfiretux_right[1], datadir + "/images/shared/bigfiretux-right-1.png",
900                USE_ALPHA);
901
902   texture_load(&bigfiretux_right[2], datadir + "/images/shared/bigfiretux-right-2.png",
903                USE_ALPHA);
904
905   texture_load(&bigfiretux_right_jump, datadir + "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
906
907   texture_load(&bigfiretux_left[0], datadir + "/images/shared/bigfiretux-left-0.png",
908                USE_ALPHA);
909
910   texture_load(&bigfiretux_left[1], datadir + "/images/shared/bigfiretux-left-1.png",
911                USE_ALPHA);
912
913   texture_load(&bigfiretux_left[2], datadir + "/images/shared/bigfiretux-left-2.png",
914                USE_ALPHA);
915
916   texture_load(&bigfiretux_left_jump, datadir + "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
917
918   texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
919                USE_ALPHA);
920
921   texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
922                USE_ALPHA);
923
924   texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
925                USE_ALPHA);
926
927   texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
928                USE_ALPHA);
929
930
931   texture_load(&ducktux_right, datadir +
932                "/images/shared/ducktux-right.png",
933                USE_ALPHA);
934
935   texture_load(&ducktux_left, datadir +
936                "/images/shared/ducktux-left.png",
937                USE_ALPHA);
938
939   texture_load(&skidtux_right, datadir +
940                "/images/shared/skidtux-right.png",
941                USE_ALPHA);
942
943   texture_load(&skidtux_left, datadir +
944                "/images/shared/skidtux-left.png",
945                USE_ALPHA);
946
947   texture_load(&duckfiretux_right, datadir +
948                "/images/shared/duckfiretux-right.png",
949                USE_ALPHA);
950
951   texture_load(&duckfiretux_left, datadir +
952                "/images/shared/duckfiretux-left.png",
953                USE_ALPHA);
954
955   texture_load(&skidfiretux_right, datadir +
956                "/images/shared/skidfiretux-right.png",
957                USE_ALPHA);
958
959   texture_load(&skidfiretux_left, datadir +
960                "/images/shared/skidfiretux-left.png",
961                USE_ALPHA);
962
963
964   /* Boxes: */
965
966   texture_load(&img_box_full, datadir + "/images/shared/box-full.png",
967                IGNORE_ALPHA);
968   texture_load(&img_box_empty, datadir + "/images/shared/box-empty.png",
969                IGNORE_ALPHA);
970
971
972   /* Water: */
973
974
975   texture_load(&img_water, datadir + "/images/shared/water.png", IGNORE_ALPHA);
976
977   texture_load(&img_waves[0], datadir + "/images/shared/waves-0.png",
978                USE_ALPHA);
979
980   texture_load(&img_waves[1], datadir + "/images/shared/waves-1.png",
981                USE_ALPHA);
982
983   texture_load(&img_waves[2], datadir + "/images/shared/waves-2.png",
984                USE_ALPHA);
985
986
987   /* Pole: */
988
989   texture_load(&img_pole, datadir + "/images/shared/pole.png", USE_ALPHA);
990   texture_load(&img_poletop, datadir + "/images/shared/poletop.png",
991                USE_ALPHA);
992
993
994   /* Flag: */
995
996   texture_load(&img_flag[0], datadir + "/images/shared/flag-0.png",
997                USE_ALPHA);
998   texture_load(&img_flag[1], datadir + "/images/shared/flag-1.png",
999                USE_ALPHA);
1000
1001
1002   /* Cloud: */
1003
1004   texture_load(&img_cloud[0][0], datadir + "/images/shared/cloud-00.png",
1005                USE_ALPHA);
1006
1007   texture_load(&img_cloud[0][1], datadir + "/images/shared/cloud-01.png",
1008                USE_ALPHA);
1009
1010   texture_load(&img_cloud[0][2], datadir + "/images/shared/cloud-02.png",
1011                USE_ALPHA);
1012
1013   texture_load(&img_cloud[0][3], datadir + "/images/shared/cloud-03.png",
1014                USE_ALPHA);
1015
1016
1017   texture_load(&img_cloud[1][0], datadir + "/images/shared/cloud-10.png",
1018                USE_ALPHA);
1019
1020   texture_load(&img_cloud[1][1], datadir + "/images/shared/cloud-11.png",
1021                USE_ALPHA);
1022
1023   texture_load(&img_cloud[1][2], datadir + "/images/shared/cloud-12.png",
1024                USE_ALPHA);
1025
1026   texture_load(&img_cloud[1][3], datadir + "/images/shared/cloud-13.png",
1027                USE_ALPHA);
1028
1029
1030   /* Bad guys: */
1031   load_badguy_gfx();
1032
1033   /* Upgrades: */
1034
1035   texture_load(&img_mints, datadir + "/images/shared/mints.png", USE_ALPHA);
1036   texture_load(&img_coffee, datadir + "/images/shared/coffee.png", USE_ALPHA);
1037
1038
1039   /* Weapons: */
1040
1041   texture_load(&img_bullet, datadir + "/images/shared/bullet.png", USE_ALPHA);
1042
1043   texture_load(&img_red_glow, datadir + "/images/shared/red-glow.png",
1044                USE_ALPHA);
1045
1046
1047
1048   /* Distros: */
1049
1050   texture_load(&img_distro[0], datadir + "/images/shared/distro-0.png",
1051                USE_ALPHA);
1052
1053   texture_load(&img_distro[1], datadir + "/images/shared/distro-1.png",
1054                USE_ALPHA);
1055
1056   texture_load(&img_distro[2], datadir + "/images/shared/distro-2.png",
1057                USE_ALPHA);
1058
1059   texture_load(&img_distro[3], datadir + "/images/shared/distro-3.png",
1060                USE_ALPHA);
1061
1062
1063   /* Tux life: */
1064
1065   texture_load(&tux_life, datadir + "/images/shared/tux-life.png",
1066                USE_ALPHA);
1067
1068   /* Herring: */
1069
1070   texture_load(&img_golden_herring, datadir + "/images/shared/golden-herring.png",
1071                USE_ALPHA);
1072
1073
1074   /* Super background: */
1075
1076   texture_load(&img_super_bkgd, datadir + "/images/shared/super-bkgd.png",
1077                IGNORE_ALPHA);
1078
1079
1080   /* Sound effects: */
1081
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. :)
1088   */
1089   for (i = 0; i < NUM_SOUNDS; i++)
1090     sounds[i] = load_sound(datadir + soundfilenames[i]);
1091
1092   /* Herring song */
1093   herring_song = load_song(datadir + "/music/SALCON.MOD");
1094 }
1095
1096
1097 /* Free shared data: */
1098
1099 void unloadshared(void)
1100 {
1101   int i;
1102
1103   for (i = 0; i < 3; i++)
1104     {
1105       texture_free(&tux_right[i]);
1106       texture_free(&tux_left[i]);
1107       texture_free(&bigtux_right[i]);
1108       texture_free(&bigtux_left[i]);
1109     }
1110
1111   texture_free(&bigtux_right_jump);
1112   texture_free(&bigtux_left_jump);
1113
1114   for (i = 0; i < 2; i++)
1115     {
1116       texture_free(&cape_right[i]);
1117       texture_free(&cape_left[i]);
1118       texture_free(&bigcape_right[i]);
1119       texture_free(&bigcape_left[i]);
1120     }
1121
1122   texture_free(&ducktux_left);
1123   texture_free(&ducktux_right);
1124
1125   texture_free(&skidtux_left);
1126   texture_free(&skidtux_right);
1127
1128   free_badguy_gfx();
1129
1130   texture_free(&img_box_full);
1131   texture_free(&img_box_empty);
1132
1133   texture_free(&img_water);
1134   for (i = 0; i < 3; i++)
1135     texture_free(&img_waves[i]);
1136
1137   texture_free(&img_pole);
1138   texture_free(&img_poletop);
1139
1140   for (i = 0; i < 2; i++)
1141     texture_free(&img_flag[i]);
1142
1143   texture_free(&img_mints);
1144   texture_free(&img_coffee);
1145
1146   for (i = 0; i < 4; i++)
1147     {
1148       texture_free(&img_distro[i]);
1149       texture_free(&img_cloud[0][i]);
1150       texture_free(&img_cloud[1][i]);
1151     }
1152
1153   texture_free(&img_golden_herring);
1154
1155   for (i = 0; i < NUM_SOUNDS; i++)
1156     free_chunk(sounds[i]);
1157
1158   /* free the herring song */
1159   free_music( herring_song );
1160 }
1161
1162
1163 /* Draw a tile on the screen: */
1164
1165 void drawshape(float x, float y, unsigned int c, Uint8 alpha)
1166 {
1167   if (c != 0)
1168     {
1169       Tile* ptile = TileManager::instance()->get(c);
1170       if(ptile)
1171         {
1172           if(ptile->images.size() > 1)
1173             {
1174               texture_draw(&ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))],x,y, alpha);
1175             }
1176           else if (ptile->images.size() == 1)
1177             {
1178               texture_draw(&ptile->images[0],x,y, alpha);
1179             }
1180           else
1181             {
1182               //printf("Tile not dravable %u\n", c);
1183             }
1184         }
1185     }
1186 }
1187
1188 /* Bounce a brick: */
1189 void bumpbrick(float x, float y)
1190 {
1191   add_bouncy_brick(((int)(x + 1) / 32) * 32,
1192                    (int)(y / 32) * 32);
1193
1194   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1195 }
1196
1197 /* (Status): */
1198 void drawstatus(void)
1199 {
1200   char str[60];
1201
1202   sprintf(str, "%d", score);
1203   text_draw(&white_text, "SCORE", 0, 0, 1);
1204   text_draw(&gold_text, str, 96, 0, 1);
1205
1206   if(st_gl_mode != ST_GL_TEST)
1207     {
1208       sprintf(str, "%d", hs_score);
1209       text_draw(&white_text, "HIGH", 0, 20, 1);
1210       text_draw(&gold_text, str, 96, 20, 1);
1211     }
1212   else
1213     {
1214       text_draw(&white_text,"Press ESC To Return",0,20,1);
1215     }
1216
1217   if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
1218     {
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);
1222     }
1223
1224   sprintf(str, "%d", distros);
1225   text_draw(&white_text, "DISTROS", screen->h, 0, 1);
1226   text_draw(&gold_text, str, 608, 0, 1);
1227
1228   text_draw(&white_text, "LIVES", screen->h, 20, 1);
1229
1230   if(show_fps)
1231     {
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);
1235     }
1236
1237   for(int i=0; i < tux.lives; ++i)
1238     {
1239       texture_draw(&tux_life,565+(18*i),20);
1240     }
1241 }
1242
1243
1244 void drawendscreen(void)
1245 {
1246   char str[80];
1247
1248   clearscreen(0, 0, 0);
1249
1250   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
1251
1252   sprintf(str, "SCORE: %d", score);
1253   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1254
1255   sprintf(str, "DISTROS: %d", distros);
1256   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1257
1258   flipscreen();
1259   
1260   SDL_Event event;
1261   wait_for_event(event,2000,5000,true);
1262 }
1263
1264 void drawresultscreen(void)
1265 {
1266   char str[80];
1267
1268   clearscreen(0, 0, 0);
1269
1270   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
1271
1272   sprintf(str, "SCORE: %d", score);
1273   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1274
1275   sprintf(str, "DISTROS: %d", distros);
1276   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1277
1278   flipscreen();
1279   
1280   SDL_Event event;
1281   wait_for_event(event,2000,5000,true);
1282 }
1283
1284 void
1285 GameSession::savegame(int slot)
1286 {
1287   char savefile[1024];
1288   FILE* fi;
1289   unsigned int ui;
1290
1291   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1292
1293   fi = fopen(savefile, "wb");
1294
1295   if (fi == NULL)
1296     {
1297       fprintf(stderr, "Warning: I could not open the slot file ");
1298     }
1299   else
1300     {
1301       fputs(level_subset, fi);
1302       fputs("\n", 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);
1315     }
1316   fclose(fi);
1317
1318 }
1319
1320 void
1321 GameSession::loadgame(int slot)
1322 {
1323   char savefile[1024];
1324   char str[100];
1325   FILE* fi;
1326   unsigned int ui;
1327
1328   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1329
1330   fi = fopen(savefile, "rb");
1331
1332   if (fi == NULL)
1333     {
1334       fprintf(stderr, "Warning: I could not open the slot file ");
1335
1336     }
1337   else
1338     {
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);
1343
1344       set_defaults();
1345       current_level.cleanup();
1346       if(current_level.load(level_subset,level) != 0)
1347         exit(1);
1348       arrays_free();
1349       activate_bad_guys(&current_level);
1350       activate_particle_systems();
1351       level_free_gfx();
1352       current_level.load_gfx();
1353       level_free_song();
1354       current_level.load_song();
1355       levelintro();
1356       update_time = st_get_ticks();
1357
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);
1368       fclose(fi);
1369     }
1370
1371 }
1372
1373 std::string slotinfo(int slot)
1374 {
1375   FILE* fi;
1376   char slotfile[1024];
1377   char tmp[200];
1378   char str[5];
1379   int slot_level;
1380   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1381
1382   fi = fopen(slotfile, "rb");
1383
1384   sprintf(tmp,"Slot %d - ",slot);
1385
1386   if (fi == NULL)
1387     {
1388       strcat(tmp,"Free");
1389     }
1390   else
1391     {
1392       fgets(str, 100, fi);
1393       str[strlen(str)-1] = '\0';
1394       strcat(tmp, str);
1395       strcat(tmp, " / Level:");
1396       fread(&slot_level,sizeof(int),1,fi);
1397       sprintf(str,"%d",slot_level);
1398       strcat(tmp,str);
1399       fclose(fi);
1400     }
1401
1402   return tmp;
1403 }
1404