From 011924797f070a383d5010f53cb90b04b4c124a1 Mon Sep 17 00:00:00 2001 From: Christoph Sommer Date: Tue, 18 Jul 2006 19:22:42 +0000 Subject: [PATCH] Sectors support multiple solid tilemaps, tilemaps can have a name SVN-Revision: 4045 --- src/badguy/kugelblitz.cpp | 2 + src/flip_level_transformer.cpp | 3 +- src/object/camera.cpp | 6 +- src/object/electrifier.cpp | 4 +- src/object/particlesystem_interactive.cpp | 66 +++++----- src/object/player.cpp | 2 +- src/object/tilemap.cpp | 5 +- src/object/tilemap.hpp | 4 +- src/scripting/functions.cpp | 2 +- src/sector.cpp | 200 +++++++++++++++++------------- src/sector.hpp | 18 ++- src/title.cpp | 2 +- 12 files changed, 186 insertions(+), 128 deletions(-) diff --git a/src/badguy/kugelblitz.cpp b/src/badguy/kugelblitz.cpp index 68fc066d9..e9fac1519 100644 --- a/src/badguy/kugelblitz.cpp +++ b/src/badguy/kugelblitz.cpp @@ -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); } diff --git a/src/flip_level_transformer.cpp b/src/flip_level_transformer.cpp index e56ac2a5b..12a75639c 100644 --- a/src/flip_level_transformer.cpp +++ b/src/flip_level_transformer.cpp @@ -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) { diff --git a/src/object/camera.cpp b/src/object/camera.cpp index a848d2bf5..023a26281 100644 --- a/src/object/camera.cpp +++ b/src/object/camera.cpp @@ -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) { diff --git a/src/object/electrifier.cpp b/src/object/electrifier.cpp index a0e299232..0a7feca5f 100644 --- a/src/object/electrifier.cpp +++ b/src/object/electrifier.cpp @@ -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(); } } diff --git a/src/object/particlesystem_interactive.cpp b/src/object/particlesystem_interactive.cpp index e253a4362..0a45cb53c 100644 --- a/src/object/particlesystem_interactive.cpp +++ b/src/object/particlesystem_interactive.cpp @@ -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::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; diff --git a/src/object/player.cpp b/src/object/player.cpp index 85dca25ca..bfdd2010d 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -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; } diff --git a/src/object/tilemap.cpp b/src/object/tilemap.cpp index b54c5deed..c574befbb 100644 --- a/src/object/tilemap.cpp +++ b/src/object/tilemap.cpp @@ -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; diff --git a/src/object/tilemap.hpp b/src/object/tilemap.hpp index 172271951..deb1dbb26 100644 --- a/src/object/tilemap.hpp +++ b/src/object/tilemap.hpp @@ -22,6 +22,7 @@ #include #include +#include #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; diff --git a/src/scripting/functions.cpp b/src/scripting/functions.cpp index aa8ace74d..ff0687fe0 100644 --- a/src/scripting/functions.cpp +++ b/src/scripting/functions.cpp @@ -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)); } diff --git a/src/sector.cpp b/src/sector.cpp index 1afc7873b..5432d9813 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -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::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 (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 (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::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::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::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::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::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::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::const_iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) { + TileMap* solids = *i; + solids->change_all(old_tile_id, new_tile_id); + } } diff --git a/src/sector.hpp b/src/sector.hpp index cced76952..b08552dfb 100644 --- a/src/sector.hpp +++ b/src/sector.hpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -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 GameObjects; typedef std::vector MovingObjects; typedef std::vector 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 solid_tilemaps; Camera* camera; }; diff --git a/src/title.cpp b/src/title.cpp index 5b31fe3b1..019837c6e 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -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()); } -- 2.11.0