- new more bulletprof endsequence code patch from MatzeB
authorIngo Ruhnke <grumbel@gmx.de>
Mon, 26 Apr 2004 19:11:54 +0000 (19:11 +0000)
committerIngo Ruhnke <grumbel@gmx.de>
Mon, 26 Apr 2004 19:11:54 +0000 (19:11 +0000)
SVN-Revision: 760

src/collision.cpp
src/collision.h
src/gameloop.cpp
src/gameloop.h
src/level.cpp
src/level.h
src/tile.cpp
src/tile.h
src/timer.cpp
src/timer.h

index 1c96d91..540e406 100644 (file)
@@ -79,6 +79,31 @@ bool collision_object_map(const base_type& pbase)
   return false;
 }
 
+void* collision_func(const base_type& base, tiletestfunction function)
+{
+  for(float x = base.x; x < base.x + base.width; x += 32) {
+    for(float y = base.y; y < base.y + base.height; y += 32) {
+      Tile* tile = gettile(x, y);
+      void* result = function(tile);
+      if(result != 0)
+        return result;
+    }
+  }
+
+  return 0;
+}
+
+static void* test_goal_tile_function(Tile* tile)
+{
+  if(tile->goal)
+    return tile;
+  return 0;
+}
+
+Tile* collision_goal(const base_type& base)
+{
+  return (Tile*) collision_func(base, test_goal_tile_function);
+}
 
 void collision_swept_object_map(base_type* old, base_type* current)
 {
index 4a009e5..f813f2a 100644 (file)
@@ -55,5 +55,14 @@ bool  isbrick(float x, float y);
 bool  isice(float x, float y);
 bool  isfullbox(float x, float y);
 
+typedef void* (*tiletestfunction)(Tile* tile);
+/** invokes the function for each tile the baserectangle collides with. The
+ * function aborts and returns true as soon as the tiletestfunction returns
+ * != 0 then this value is returned. returns 0 if all tests failed.
+ */
+void* collision_func(const base_type& base, tiletestfunction* function);
+
+Tile* collision_goal(const base_type& base);
+
 #endif /*SUPERTUX_COLLISION_H*/
 
index d523bda..efc3c94 100644 (file)
@@ -407,43 +407,47 @@ GameSession::process_events()
     }
 }
 
-
 void
 GameSession::check_end_conditions()
 {
   Player* tux = world->get_tux();
 
   /* End of level? */
-  if (tux->base.x >= World::current()->get_level()->endpos + 32 * (get_level()->use_endsequence ? 22 : 10))
+  int endpos = (World::current()->get_level()->width-10) * 32;
+  Tile* endtile = collision_goal(tux->base);
+  printf("EndTile: %p.\n", endtile);
+  // fallback in case the other endpositions don't trigger
+  if (tux->base.x >= endpos || (endtile && endtile->data >= 1)
+      || (end_sequence && !endsequence_timer.check()))
     {
       exit_status = LEVEL_FINISHED;
+      return;
     }
-  else if (tux->base.x >= World::current()->get_level()->endpos && !end_sequence)
+  else if(!end_sequence && endtile && endtile->data == 0)
     {
       end_sequence = true;
       last_x_pos = -1;
       music_manager->halt_music();
+      endsequence_timer.start(5000); // 5 seconds until we finish the map
     }
-  else
+  else if (!end_sequence && tux->is_dead())
     {
-      // Check End conditions
-      if (tux->is_dead())
-        {
-          player_status.lives -= 1;             
-    
-          if (player_status.lives < 0)
-            { // No more lives!?
-              if(st_gl_mode != ST_GL_TEST)
-                drawendscreen();
-              
-              exit_status = GAME_OVER;
-            }
-          else
-            { // Still has lives, so reset Tux to the levelstart
-              restart_level();
-            }
+      player_status.lives -= 1;             
+
+      if (player_status.lives < 0)
+        { // No more lives!?
+          if(st_gl_mode != ST_GL_TEST)
+            drawendscreen();
+          
+          exit_status = GAME_OVER;
         }
-    } 
+      else
+        { // Still has lives, so reset Tux to the levelstart
+          restart_level();
+        }
+
+      return;
+    }
 }
 
 void
index 7f25998..dda4fbb 100644 (file)
@@ -47,6 +47,7 @@ class GameSession
  private:
   Timer fps_timer;
   Timer frame_timer;
+  Timer endsequence_timer;
   World* world;
   int st_gl_mode;
   int levelnb;
index d8d40e5..8ab4078 100644 (file)
@@ -245,8 +245,6 @@ Level::init_defaults()
   bkgd_bottom.red   = 255;
   bkgd_bottom.green = 255;
   bkgd_bottom.blue  = 255;
-  endpos     = 0;
-  use_endsequence = false;
 
   for(int i = 0; i < 15; ++i)
     {
@@ -312,8 +310,6 @@ Level::load(const std::string& filename)
       LispReader reader(lisp_cdr(root_obj));
       version = 0;
       reader.read_int("version",  &version);
-      use_endsequence = false;
-      reader.read_bool("use-endsequence", &use_endsequence);
       if(!reader.read_int("width",  &width))
         st_abort("No width specified for level.", "");
       if (!reader.read_int("start_pos_x", &start_pos_x)) start_pos_x = 100;
@@ -513,14 +509,6 @@ Level::load(const std::string& filename)
         }
     }
 
-  //  Mark the end position of this level!
-  // FIXME: -10 is a rather random value, we still need some kind of
-  // real levelend gola
-  if (use_endsequence)
-    endpos = 32*(width-30);
-  else
-    endpos = 32*(width-15);
-
   lisp_free(root_obj);
   fclose(fi);
   return 0;
index ac503ed..11d8181 100644 (file)
@@ -87,8 +87,6 @@ class Level
   int width;
   int start_pos_x;
   int start_pos_y;
-  int  endpos;
-  bool use_endsequence;
   float gravity;
 
   std::vector<BadGuyData> badguy_data;
index 7d07e43..0966e08 100644 (file)
@@ -93,6 +93,7 @@ void TileManager::load_tileset(std::string filename)
               tile->water   = false;
               tile->fullbox = false;
               tile->distro  = false;
+              tile->goal    = false;
               tile->data    = 0;
               tile->next_tile  = 0;
               tile->anim_speed = 25;
@@ -105,6 +106,8 @@ void TileManager::load_tileset(std::string filename)
               reader.read_bool("water",     &tile->water);
               reader.read_bool("fullbox",   &tile->fullbox);
               reader.read_bool("distro",    &tile->distro);
+              reader.read_bool("goal",      &tile->goal);
+              if(tile->goal) printf("Goal!.\n");
               reader.read_int("data",       &tile->data);
               reader.read_int("anim-speed", &tile->anim_speed);
               reader.read_int("next-tile",  &tile->next_tile);
index b958422..ee6a0f6 100644 (file)
@@ -62,6 +62,12 @@ public:
   /** Tile is a distro/coin */
   bool distro;
 
+  /** the level should be finished when touching a goaltile.
+   * if data is 0 then the endsequence should be triggered, if data is 1
+   * then we can finish the level instantly.
+   */
+  bool goal;
+
   /** General purpose data attached to a tile (content of a box, type of coin) */
   int data;
 
index a8f2d75..5b22c13 100644 (file)
@@ -53,6 +53,11 @@ return;
   st_pause_count = 0;
 }
 
+Timer::Timer()
+{
+  init(true);
+}
+
 void
 Timer::init(bool st_ticks)
 {
index b12d32e..eb516c0 100644 (file)
@@ -36,6 +36,8 @@ class Timer
   unsigned int (*get_ticks) (void);  
 
  public:
+  Timer();
+  
   void init(bool st_ticks);
   void start(unsigned int period);
   void stop();