Sectors support multiple solid tilemaps, tilemaps can have a name
authorChristoph Sommer <mail@christoph-sommer.de>
Tue, 18 Jul 2006 19:22:42 +0000 (19:22 +0000)
committerChristoph Sommer <mail@christoph-sommer.de>
Tue, 18 Jul 2006 19:22:42 +0000 (19:22 +0000)
SVN-Revision: 4045

12 files changed:
src/badguy/kugelblitz.cpp
src/flip_level_transformer.cpp
src/object/camera.cpp
src/object/electrifier.cpp
src/object/particlesystem_interactive.cpp
src/object/player.cpp
src/object/tilemap.cpp
src/object/tilemap.hpp
src/scripting/functions.cpp
src/sector.cpp
src/sector.hpp
src/title.cpp

index 68fc066..e9fac15 100644 (file)
@@ -137,6 +137,7 @@ Kugelblitz::active_update(float elapsed_time)
         movement_timer.start(MOVETIME);
       }
     }
+    /*
     if (Sector::current()->solids->get_tile_at(get_pos())->getAttributes() == 16) {
       //HIT WATER
       Sector::current()->add_object(new Electrifier(75,1421,1.5));
@@ -147,6 +148,7 @@ Kugelblitz::active_update(float elapsed_time)
       //HIT ELECTRIFIED WATER
       explode();
     }
+    */
   }
   BadGuy::active_update(elapsed_time);  
 }
index e56ac2a..12a7563 100644 (file)
@@ -30,8 +30,7 @@
 void
 FlipLevelTransformer::transform_sector(Sector* sector)
 {
-  float height = sector->solids->get_height() 
-    * sector->solids->get_tilemanager()->get_default_height();
+  float height = sector->get_height() * 32;
   
   for(Sector::GameObjects::iterator i = sector->gameobjects.begin();
       i != sector->gameobjects.end(); ++i) {
index a848d2b..023a262 100644 (file)
@@ -171,8 +171,8 @@ Camera::update(float elapsed_time)
 void
 Camera::keep_in_bounds(Vector& translation)
 {
-  float width = sector->solids->get_width() * 32;
-  float height = sector->solids->get_height() * 32;
+  float width = sector->get_width() * 32;
+  float height = sector->get_height() * 32;
 
   // don't scroll before the start or after the level's end
   if(translation.y > height - SCREEN_HEIGHT)
@@ -207,7 +207,7 @@ Camera::update_scroll_normal(float elapsed_time)
   /****** Vertical Scrolling part ******/
   bool do_y_scrolling = true;
 
-  if(player->is_dying() || sector->solids->get_height() == 19)
+  if(player->is_dying() || sector->get_height() == 19)
     do_y_scrolling = false;
 
   if(do_y_scrolling) {
index a0e2992..0a7feca 100644 (file)
@@ -29,7 +29,7 @@ Electrifier::Electrifier(uint32_t oldtile, uint32_t newtile, float seconds)
   duration.start(seconds);
   change_from = oldtile;
   change_to = newtile;
-  Sector::current()->solids->change_all(change_from,change_to);
+  Sector::current()->change_solid_tiles(change_from,change_to);
 }
   
 Electrifier::~Electrifier() {
@@ -39,7 +39,7 @@ void
 Electrifier::update(float ) 
 {
   if (duration.check()) {
-    Sector::current()->solids->change_all(change_to,change_from);
+    Sector::current()->change_solid_tiles(change_to,change_from);
     remove_me();
   }
 }
index e253a43..0a45cb5 100644 (file)
@@ -75,8 +75,7 @@ int
 ParticleSystem_Interactive::collision(Particle* object, Vector movement)
 {
   using namespace collision;
-    
-  TileMap* solids = Sector::current()->solids;
+
   // calculate rectangle where the object will move
   float x1, x2;
   float y1, y2;
@@ -85,48 +84,53 @@ ParticleSystem_Interactive::collision(Particle* object, Vector movement)
   y1 = object->pos.y;
   y2 = y1 + 32 + movement.y;
   bool water = false;
-  
+
   // test with all tiles in this rectangle
   int starttilex = int(x1-1) / 32;
   int starttiley = int(y1-1) / 32;
   int max_x = int(x2+1);
   int max_y = int(y2+1);
-  
+
   Rect dest = Rect(x1, y1, x2, y2);
   dest.move(movement);
   Constraints constraints;
-  for(int x = starttilex; x*32 < max_x; ++x) {
-    for(int y = starttiley; y*32 < max_y; ++y) {
-      const Tile* tile = solids->get_tile(x, y);
-      if(!tile)
-        continue;
-      // skip non-solid tiles, except water
-      if(! (tile->getAttributes() & (Tile::WATER | Tile::SOLID)))
-        continue;
-
-      if(tile->getAttributes() & Tile::SLOPE) { // slope tile
-        AATriangle triangle;
-        Vector p1(x*32, y*32);
-        Vector p2((x+1)*32, (y+1)*32);
-        triangle = AATriangle(p1, p2, tile->getData());
-
-        if(rectangle_aatriangle(&constraints, dest, triangle)) {
-          if(tile->getAttributes() & Tile::WATER)
-            water = true;
-        }
-      } else { // normal rectangular tile
-        Rect rect(x*32, y*32, (x+1)*32, (y+1)*32);
-        if(intersects(dest, rect)) {
-          if(tile->getAttributes() & Tile::WATER)
-            water = true;
-          set_rectangle_rectangle_constraints(&constraints, dest, rect); 
-        }
+
+  for(std::list<TileMap*>::const_iterator i = Sector::current()->solid_tilemaps.begin(); i != Sector::current()->solid_tilemaps.end(); i++) {
+    TileMap* solids = *i;
+    for(int x = starttilex; x*32 < max_x; ++x) {
+      for(int y = starttiley; y*32 < max_y; ++y) {
+       const Tile* tile = solids->get_tile(x, y);
+       if(!tile)
+         continue;
+       // skip non-solid tiles, except water
+       if(! (tile->getAttributes() & (Tile::WATER | Tile::SOLID)))
+         continue;
+
+       if(tile->getAttributes() & Tile::SLOPE) { // slope tile
+         AATriangle triangle;
+         Vector p1(x*32, y*32);
+         Vector p2((x+1)*32, (y+1)*32);
+         triangle = AATriangle(p1, p2, tile->getData());
+
+         if(rectangle_aatriangle(&constraints, dest, triangle)) {
+           if(tile->getAttributes() & Tile::WATER)
+             water = true;
+         }
+       } else { // normal rectangular tile
+         Rect rect(x*32, y*32, (x+1)*32, (y+1)*32);
+         if(intersects(dest, rect)) {
+           if(tile->getAttributes() & Tile::WATER)
+             water = true;
+           set_rectangle_rectangle_constraints(&constraints, dest, rect); 
+         }
+       }
       }
     }
   }
 
+
   // TODO don't use magic numbers here...
-  
+
   // did we collide at all?
   if(!constraints.has_constraints())
     return -1;
index 85dca25..bfdd201 100644 (file)
@@ -1061,7 +1061,7 @@ Player::check_bounds(Camera* camera)
   }
 
   /* Keep in-bounds, vertically: */
-  if (get_pos().y > Sector::current()->solids->get_height() * 32) {
+  if (get_pos().y > Sector::current()->get_height() * 32) {
     kill(true);
     return;
   }
index b54c5de..c574bef 100644 (file)
@@ -55,6 +55,7 @@ TileMap::TileMap(const lisp::Lisp& reader, TileManager* new_tile_manager)
   if(tilemanager == 0)
     tilemanager = tile_manager;
 
+  reader.get("name", name);
   reader.get("z-pos", z_pos);
   reader.get("solid", solid);
   reader.get("speed", speed);
@@ -83,8 +84,8 @@ TileMap::TileMap(const lisp::Lisp& reader, TileManager* new_tile_manager)
     tilemanager->get(*i);
 }
 
-TileMap::TileMap(int z_pos, bool solid, size_t width, size_t height)
-  : solid(solid), speed(1), width(0), height(0), z_pos(z_pos),
+TileMap::TileMap(std::string name, int z_pos, bool solid, size_t width, size_t height)
+  : name(name), solid(solid), speed(1), width(0), height(0), z_pos(z_pos),
     drawing_effect(NO_EFFECT)
 {
   tilemanager = tile_manager;
index 1722719..deb1dbb 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <vector>
 #include <stdint.h>
+#include <string>
 
 #include "game_object.hpp"
 #include "serializable.hpp"
@@ -44,7 +45,7 @@ class TileMap : public GameObject, public Serializable
 public:
   TileMap();
   TileMap(const lisp::Lisp& reader, TileManager* tile_manager = 0);
-  TileMap(int z_pos, bool solid_, size_t width_, size_t height_);
+  TileMap(std::string name, int z_pos, bool solid_, size_t width_, size_t height_);
   virtual ~TileMap();
 
   virtual void write(lisp::Writer& writer);
@@ -105,6 +106,7 @@ private:
   
 private:
   TileManager* tilemanager;
+  std::string name;
   bool solid;
   float speed;
   int width, height;
index aa8ace7..ff0687f 100644 (file)
@@ -250,7 +250,7 @@ void gotoend()
   if (!validate_sector_player()) return;
   ::Player* tux = Sector::current()->player;
   tux->move(Vector(
-          (Sector::current()->solids->get_width()*32) - (SCREEN_WIDTH*2), 0));
+          (Sector::current()->get_width()*32) - (SCREEN_WIDTH*2), 0));
   Sector::current()->camera->reset(
         Vector(tux->get_pos().x, tux->get_pos().y));
 }
index 1afc787..5432d98 100644 (file)
@@ -70,7 +70,7 @@ bool Sector::draw_solids_only = false;
 
 Sector::Sector(Level* parent)
   : level(parent), currentmusic(LEVEL_MUSIC), gravity(10),
-    player(0), solids(0), camera(0)
+    player(0), camera(0)
 {
   add_object(new Player(player_status));
   add_object(new DisplayEffect());
@@ -195,8 +195,7 @@ Sector::parse(const lisp::Lisp& sector)
 
   update_game_objects();
 
-  if(!solids)
-    throw std::runtime_error("sector does not contain a solid tile layer.");
+  if(solid_tilemaps.size() < 1) log_warning << "sector '" << name << "' does not contain a solid tile layer." << std::endl;
 
   fix_old_tiles();
   if(!camera) {
@@ -333,8 +332,7 @@ Sector::parse_old_format(const lisp::Lisp& reader)
 
   update_game_objects();
 
-  if(solids == 0)
-    throw std::runtime_error("sector does not contain a solid tile layer.");
+  if(solid_tilemaps.size() < 1) log_warning << "sector '" << name << "' does not contain a solid tile layer." << std::endl;
 
   fix_old_tiles();
   update_game_objects();
@@ -344,27 +342,30 @@ void
 Sector::fix_old_tiles()
 {
   // hack for now...
-  for(size_t x=0; x < solids->get_width(); ++x) {
-    for(size_t y=0; y < solids->get_height(); ++y) {
-      const Tile* tile = solids->get_tile(x, y);
-      Vector pos(x*32, y*32);
-      
-      if(tile->getID() == 112) {
-        add_object(new InvisibleBlock(pos));
-        solids->change(x, y, 0);
-      } else if(tile->getAttributes() & Tile::COIN) {
-        add_object(new Coin(pos));
-        solids->change(x, y, 0);
-      } else if(tile->getAttributes() & Tile::FULLBOX) {
-        add_object(new BonusBlock(pos, tile->getData()));
-        solids->change(x, y, 0);
-      } else if(tile->getAttributes() & Tile::BRICK) {
-        add_object(new Brick(pos, tile->getData()));
-        solids->change(x, y, 0);
-      } else if(tile->getAttributes() & Tile::GOAL) {
-        std::string sequence = tile->getData() == 0 ? "endsequence" : "stoptux";
-        add_object(new SequenceTrigger(pos, sequence));
-        solids->change(x, y, 0);
+  for(std::list<TileMap*>::iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) {
+    TileMap* solids = *i;
+    for(size_t x=0; x < solids->get_width(); ++x) {
+      for(size_t y=0; y < solids->get_height(); ++y) {
+       const Tile* tile = solids->get_tile(x, y);
+       Vector pos(x*32, y*32);
+
+       if(tile->getID() == 112) {
+         add_object(new InvisibleBlock(pos));
+         solids->change(x, y, 0);
+       } else if(tile->getAttributes() & Tile::COIN) {
+         add_object(new Coin(pos));
+         solids->change(x, y, 0);
+       } else if(tile->getAttributes() & Tile::FULLBOX) {
+         add_object(new BonusBlock(pos, tile->getData()));
+         solids->change(x, y, 0);
+       } else if(tile->getAttributes() & Tile::BRICK) {
+         add_object(new Brick(pos, tile->getData()));
+         solids->change(x, y, 0);
+       } else if(tile->getAttributes() & Tile::GOAL) {
+         std::string sequence = tile->getData() == 0 ? "endsequence" : "stoptux";
+         add_object(new SequenceTrigger(pos, sequence));
+         solids->change(x, y, 0);
+       }
       }
     }
   }
@@ -630,13 +631,7 @@ Sector::before_object_add(GameObject* object)
   }
   
   TileMap* tilemap = dynamic_cast<TileMap*> (object);
-  if(tilemap && tilemap->is_solid()) {
-    if(solids == 0) {
-      solids = tilemap;
-    } else {
-      log_warning << "Another solid tilemaps added. Ignoring" << std::endl;
-    }
-  }
+  if(tilemap && tilemap->is_solid()) solid_tilemaps.push_back(tilemap);
 
   Camera* camera = dynamic_cast<Camera*> (object);
   if(camera) {
@@ -824,31 +819,35 @@ Sector::collision_tilemap(collision::Constraints* constraints,
   int max_x = int(x2);
   int max_y = int(y2+1);
 
-  for(int x = starttilex; x*32 < max_x; ++x) {
-    for(int y = starttiley; y*32 < max_y; ++y) {
-      const Tile* tile = solids->get_tile(x, y);
-      if(!tile)
-        continue;
-      // skip non-solid tiles
-      if((tile->getAttributes() & Tile::SOLID) == 0)
-        continue;
-      // only handle unisolid when the player is falling down and when he was
-      // above the tile before
-      if(tile->getAttributes() & Tile::UNISOLID) {
-        if(movement.y <= 0 || dest.get_bottom() - movement.y - SHIFT_DELTA > y*32)
-          continue;
-      }
-
-      if(tile->getAttributes() & Tile::SLOPE) { // slope tile
-        AATriangle triangle;
-        Vector p1(x*32, y*32);
-        Vector p2((x+1)*32, (y+1)*32);
-        triangle = AATriangle(p1, p2, tile->getData());
 
-        collision::rectangle_aatriangle(constraints, dest, triangle);
-      } else { // normal rectangular tile
-        Rect rect(x*32, y*32, (x+1)*32, (y+1)*32);
-        check_collisions(constraints, movement, dest, rect);
+  for(std::list<TileMap*>::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) {
+    TileMap* solids = *i;
+    for(int x = starttilex; x*32 < max_x; ++x) {
+      for(int y = starttiley; y*32 < max_y; ++y) {
+       const Tile* tile = solids->get_tile(x, y);
+       if(!tile)
+         continue;
+       // skip non-solid tiles
+       if((tile->getAttributes() & Tile::SOLID) == 0)
+         continue;
+       // only handle unisolid when the player is falling down and when he was
+       // above the tile before
+       if(tile->getAttributes() & Tile::UNISOLID) {
+         if(movement.y <= 0 || dest.get_bottom() - movement.y - SHIFT_DELTA > y*32)
+           continue;
+       }
+
+       if(tile->getAttributes() & Tile::SLOPE) { // slope tile
+         AATriangle triangle;
+         Vector p1(x*32, y*32);
+         Vector p2((x+1)*32, (y+1)*32);
+         triangle = AATriangle(p1, p2, tile->getData());
+
+         collision::rectangle_aatriangle(constraints, dest, triangle);
+       } else { // normal rectangular tile
+         Rect rect(x*32, y*32, (x+1)*32, (y+1)*32);
+         check_collisions(constraints, movement, dest, rect);
+       }
       }
     }
   }
@@ -869,12 +868,15 @@ Sector::collision_tile_attributes(const Rect& dest) const
   int max_y = int(y2);
 
   uint32_t result = 0;
-  for(int x = starttilex; x*32 < max_x; ++x) {
-    for(int y = starttiley; y*32 < max_y; ++y) {
-      const Tile* tile = solids->get_tile(x, y);
-      if(!tile)
-        continue;
-      result |= tile->getAttributes();
+  for(std::list<TileMap*>::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) {
+    TileMap* solids = *i;
+    for(int x = starttilex; x*32 < max_x; ++x) {
+      for(int y = starttiley; y*32 < max_y; ++y) {
+       const Tile* tile = solids->get_tile(x, y);
+       if(!tile)
+         continue;
+       result |= tile->getAttributes();
+      }
     }
   }
 
@@ -1165,22 +1167,22 @@ Sector::is_free_space(const Rect& rect) const
   int max_x = int(rect.p2.x);
   int max_y = int(rect.p2.y);
 
-  for(int x = starttilex; x*32 <= max_x; ++x) {
-    for(int y = starttiley; y*32 <= max_y; ++y) {
-      const Tile* tile = solids->get_tile(x, y);
-      if(!tile)
-        continue;
-      if(tile->getAttributes() & Tile::SLOPE) {
-       AATriangle triangle;
-       Vector p1(x*32, y*32);
-       Vector p2((x+1)*32, (y+1)*32);
-       triangle = AATriangle(p1, p2, tile->getData());
-       Constraints constraints;
-       return collision::rectangle_aatriangle(&constraints, rect, triangle);
+  for(std::list<TileMap*>::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) {
+    TileMap* solids = *i;
+    for(int x = starttilex; x*32 <= max_x; ++x) {
+      for(int y = starttiley; y*32 <= max_y; ++y) {
+       const Tile* tile = solids->get_tile(x, y);
+       if(!tile) continue;
+       if(tile->getAttributes() & Tile::SLOPE) {
+         AATriangle triangle;
+         Vector p1(x*32, y*32);
+         Vector p2((x+1)*32, (y+1)*32);
+         triangle = AATriangle(p1, p2, tile->getData());
+         Constraints constraints;
+         return collision::rectangle_aatriangle(&constraints, rect, triangle);
+       }
+       if(tile->getAttributes() & Tile::SOLID) return false;
       }
-      // FIXME: also test unisolid tiles
-      if(tile->getAttributes() & Tile::SOLID)
-        return false;
     }
   }
 
@@ -1264,10 +1266,42 @@ Sector::get_total_badguys()
 bool
 Sector::inside(const Rect& rect) const
 {
-  if(rect.p1.x > solids->get_width() * 32 
-      || rect.p1.y > solids->get_height() * 32
-      || rect.p2.x < 0)
-    return false;
+  for(std::list<TileMap*>::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) {
+    TileMap* solids = *i;
+    bool horizontally = ((rect.p2.x >= 0) && (rect.p1.x <= solids->get_width() * 32));
+    bool vertically = (rect.p1.y <= solids->get_height() * 32);
+    if (horizontally && vertically) return true;
+  }
+  return false;
+}
 
-  return true;
+size_t
+Sector::get_width() const
+{
+  size_t width = 0;
+  for(std::list<TileMap*>::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) {
+    TileMap* solids = *i;
+    if (solids->get_width() > width) width = solids->get_width();
+  }
+  return width;
+}
+
+size_t
+Sector::get_height() const
+{
+  size_t height = 0;
+  for(std::list<TileMap*>::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) {
+    TileMap* solids = *i;
+    if (solids->get_height() > height) height = solids->get_height();
+  }
+  return height;
+}
+
+void 
+Sector::change_solid_tiles(uint32_t old_tile_id, uint32_t new_tile_id)
+{
+  for(std::list<TileMap*>::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) {
+    TileMap* solids = *i;
+    solids->change_all(old_tile_id, new_tile_id);
+  }
 }
index cced769..b08552d 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <vector>
+#include <list>
 #include <memory>
 #include <squirrel.h>
 
@@ -145,6 +146,21 @@ public:
 
   Rect get_active_region();
 
+  /**
+   * returns the width (in tiles) of a sector)
+   */
+  size_t get_width() const;
+  
+  /**
+   * returns the height (in tiles) of a sector)
+   */
+  size_t get_height() const;
+
+  /**
+   * globally changes solid tilemaps' tile ids
+   */
+  void change_solid_tiles(uint32_t old_tile_id, uint32_t new_tile_id);
+
   typedef std::vector<GameObject*> GameObjects;
   typedef std::vector<MovingObject*> MovingObjects;
   typedef std::vector<SpawnPoint*> SpawnPoints;
@@ -221,7 +237,7 @@ public: // TODO make this private again
   // some special objects, where we need direct access
   // (try to avoid accessing them directly)
   Player* player;
-  TileMap* solids;
+  std::list<TileMap*> solid_tilemaps;
   Camera* camera;
 };
 
index 5b31fe3..019837c 100644 (file)
@@ -254,7 +254,7 @@ TitleScreen::make_tux_jump()
   last_tux_y_pos = tux->get_pos().y;
 
   // Wrap around at the end of the level back to the beginnig
-  if(sector->solids->get_width() * 32 - 320 < tux->get_pos().x) {
+  if(sector->get_width() * 32 - 320 < tux->get_pos().x) {
     sector->activate("main");
     sector->camera->reset(tux->get_pos());
   }