X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fsector.cpp;h=fedeee512618286e9dfccfd4640f543306645964;hb=6e843b1780f62f45b7021bd8c38181aa211588ee;hp=37a9e39ecdacc5cf473637079a6999d704cff2c5;hpb=d46c78c842ab4090a3f46e560c891234167f124b;p=supertux.git diff --git a/src/sector.cpp b/src/sector.cpp index 37a9e39ec..fedeee512 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -29,7 +29,6 @@ #include "app/globals.h" #include "sector.h" #include "utils/lispreader.h" -#include "badguy.h" #include "gameobjs.h" #include "camera.h" #include "background.h" @@ -45,8 +44,8 @@ #include "math/aatriangle.h" #include "object/coin.h" #include "object/block.h" +#include "object/invisible_block.h" #include "object/platform.h" -#include "trigger/door.h" #include "object/bullet.h" #include "badguy/jumpy.h" #include "badguy/snowball.h" @@ -54,7 +53,12 @@ #include "badguy/flame.h" #include "badguy/mriceblock.h" #include "badguy/mrbomb.h" +#include "badguy/dispenser.h" +#include "badguy/spike.h" +#include "badguy/nolok_01.h" +#include "trigger/door.h" #include "trigger/sequence_trigger.h" +#include "trigger/secretarea_trigger.h" Sector* Sector::_current = 0; @@ -65,10 +69,13 @@ Sector::Sector() song_title = "Mortimers_chipdisko.mod"; player = new Player(); add_object(player); + + printf("seccreated: %p.\n", this); } Sector::~Sector() { + printf("secdel: %p.\n", this); for(GameObjects::iterator i = gameobjects.begin(); i != gameobjects.end(); ++i) { delete *i; @@ -100,30 +107,17 @@ Sector *Sector::create(const std::string& name, size_t width, size_t height) } GameObject* -Sector::parseObject(const std::string& name, LispReader& reader) +Sector::parse_object(const std::string& name, LispReader& reader) { if(name == "background") { background = new Background(reader); return background; } else if(name == "camera") { - if(camera) { - std::cerr << "Warning: More than 1 camera defined in sector.\n"; - return 0; - } - camera = new Camera(this); - camera->read(reader); + Camera* camera = new Camera(this); + camera->parse(reader); return camera; } else if(name == "tilemap") { - TileMap* tilemap = new TileMap(reader); - - if(tilemap->is_solid()) { - if(solids) { - std::cerr << "Warning multiple solid tilemaps in sector.\n"; - return 0; - } - solids = tilemap; - } - return tilemap; + return new TileMap(reader); } else if(name == "particles-snow") { SnowParticleSystem* partsys = new SnowParticleSystem(); partsys->parse(reader); @@ -134,6 +128,8 @@ Sector::parseObject(const std::string& name, LispReader& reader) return partsys; } else if(name == "door") { return new Door(reader); + } else if(name == "secretarea") { + return new SecretAreaTrigger(reader); } else if(name == "platform") { return new Platform(reader); } else if(name == "jumpy" || name == "money") { @@ -148,6 +144,12 @@ Sector::parseObject(const std::string& name, LispReader& reader) return new MrIceBlock(reader); } else if(name == "mrbomb") { return new MrBomb(reader); + } else if(name == "dispenser") { + return new Dispenser(reader); + } else if(name == "spike") { + return new Spike(reader); + } else if(name == "nolok_01") { + return new Nolok_01(reader); } #if 0 else if(badguykind_from_string(name) != BAD_INVALID) { @@ -158,8 +160,8 @@ Sector::parseObject(const std::string& name, LispReader& reader) return new FlyingPlatform(reader); #endif - std::cerr << "Unknown object type '" << name << "'.\n"; - return 0; + std::cerr << "Unknown object type '" << name << "'.\n"; + return 0; } void @@ -188,7 +190,7 @@ Sector::parse(LispReader& lispreader) reader.read_float("y", sp->pos.y); spawnpoints.push_back(sp); } else { - GameObject* object = parseObject(token, reader); + GameObject* object = parse_object(token, reader); if(object) { add_object(object); } @@ -276,31 +278,7 @@ Sector::parse_old_format(LispReader& reader) solids = tilemap; add_object(tilemap); - // 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); - - if(tile->attributes & Tile::COIN) { - Coin* coin = new Coin(Vector(x*32, y*32)); - add_object(coin); - solids->change(x, y, 0); - } else if(tile->attributes & Tile::FULLBOX) { - BonusBlock* block = new BonusBlock(Vector(x*32, y*32), tile->data); - add_object(block); - solids->change(x, y, 0); - } else if(tile->attributes & Tile::BRICK) { - Brick* brick = new Brick(Vector(x*32, y*32), tile->data); - add_object(brick); - solids->change(x, y, 0); - } else if(tile->attributes & Tile::GOAL) { - SequenceTrigger* trigger = new SequenceTrigger(Vector(x*32, y*32), - "endsequence"); - add_object(trigger); - solids->change(x, y, 0); - } - } - } + fix_old_tiles(); } if(reader.read_int_vector("background-tm", tiles)) { @@ -347,7 +325,7 @@ Sector::parse_old_format(LispReader& reader) LispReader reader(lisp_cdr(data)); - GameObject* object = parseObject(object_type, reader); + GameObject* object = parse_object(object_type, reader); if(object) { add_object(object); } else { @@ -365,6 +343,47 @@ Sector::parse_old_format(LispReader& reader) } 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->id == 112) { + add_object(new InvisibleBlock(pos)); + solids->change(x, y, 0); + } else if(tile->id == 295) { + add_object(new Spike(pos, Spike::NORTH)); + solids->change(x, y, 0); + } else if(tile->id == 296) { + add_object(new Spike(pos, Spike::EAST)); + solids->change(x, y, 0); + } else if(tile->id == 297) { + add_object(new Spike(pos, Spike::SOUTH)); + solids->change(x, y, 0); + } else if(tile->id == 298) { + add_object(new Spike(pos, Spike::WEST)); + solids->change(x, y, 0); + } else if(tile->attributes & Tile::COIN) { + add_object(new Coin(pos)); + solids->change(x, y, 0); + } else if(tile->attributes & Tile::FULLBOX) { + add_object(new BonusBlock(pos, tile->data)); + solids->change(x, y, 0); + } else if(tile->attributes & Tile::BRICK) { + add_object(new Brick(pos, tile->data)); + solids->change(x, y, 0); + } else if(tile->attributes & Tile::GOAL) { + add_object(new SequenceTrigger(pos, "endsequence")); + solids->change(x, y, 0); + } + } + } +} + +void Sector::write(LispWriter& writer) { writer.write_string("name", name); @@ -535,15 +554,6 @@ Sector::update_game_objects() std::remove(bullets.begin(), bullets.end(), bullet), bullets.end()); } -#if 0 - InteractiveObject* interactive_object = - dynamic_cast (*i); - if(interactive_object) { - interactive_objects.erase( - std::remove(interactive_objects.begin(), interactive_objects.end(), - interactive_object), interactive_objects.end()); - } -#endif delete *i; i = gameobjects.erase(i); } else { @@ -555,17 +565,30 @@ Sector::update_game_objects() for(std::vector::iterator i = gameobjects_new.begin(); i != gameobjects_new.end(); ++i) { - Bullet* bullet = dynamic_cast (*i); - if(bullet) - bullets.push_back(bullet); -#if 0 - InteractiveObject* interactive_object - = dynamic_cast (*i); - if(interactive_object) - interactive_objects.push_back(interactive_object); -#endif + Bullet* bullet = dynamic_cast (*i); + if(bullet) + bullets.push_back(bullet); + + TileMap* tilemap = dynamic_cast (*i); + if(tilemap && tilemap->is_solid()) { + if(solids == 0) { + solids = tilemap; + fix_old_tiles(); + } else { + std::cerr << "Another solid tilemaps added. Ignoring."; + } + } + + Camera* camera = dynamic_cast (*i); + if(camera) { + if(this->camera != 0) { + std::cerr << "Warning: Multiple cameras added. Ignoring."; + continue; + } + this->camera = camera; + } - gameobjects.push_back(*i); + gameobjects.push_back(*i); } gameobjects_new.clear(); } @@ -588,6 +611,8 @@ Sector::draw(DrawingContext& context) context.pop_transform(); } +static const float DELTA = .001; + void Sector::collision_tilemap(MovingObject* object, int depth) { @@ -626,7 +651,7 @@ Sector::collision_tilemap(MovingObject* object, int depth) CollisionHit temphit, hit; Rectangle dest = object->get_bbox(); dest.move(object->movement); - hit.depth = -1; + hit.time = -1; // represents an invalid value 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); @@ -641,32 +666,18 @@ Sector::collision_tilemap(MovingObject* object, int depth) AATriangle triangle; Vector p1(x*32, y*32); Vector p2((x+1)*32, (y+1)*32); - switch(tile->data) { - case 0: - triangle = AATriangle(p1, p2, AATriangle::SOUTHWEST); - break; - case 1: - triangle = AATriangle(p1, p2, AATriangle::NORTHEAST); - break; - case 2: - triangle = AATriangle(p1, p2, AATriangle::SOUTHEAST); - break; - case 3: - triangle = AATriangle(p1, p2, AATriangle::NORTHWEST); - break; - default: - printf("Invalid slope angle in tile %d !\n", tile->id); - break; - } + triangle = AATriangle(p1, p2, tile->data); - if(Collision::rectangle_aatriangle(temphit, dest, triangle)) { - if(temphit.depth > hit.depth) + if(Collision::rectangle_aatriangle(temphit, dest, object->movement, + triangle)) { + if(temphit.time > hit.time) hit = temphit; } } else { // normal rectangular tile Rectangle rect(x*32, y*32, (x+1)*32, (y+1)*32); - if(Collision::rectangle_rectangle(temphit, dest, rect)) { - if(temphit.depth > hit.depth) + if(Collision::rectangle_rectangle(temphit, dest, + object->movement, rect)) { + if(temphit.time > hit.time) hit = temphit; } } @@ -674,7 +685,7 @@ Sector::collision_tilemap(MovingObject* object, int depth) } // did we collide at all? - if(hit.depth == -1) + if(hit.time < 0) return; // call collision function @@ -687,7 +698,7 @@ Sector::collision_tilemap(MovingObject* object, int depth) return; } // move out of collision and try again - object->movement += hit.normal * (hit.depth + .001); + object->movement += hit.normal * (hit.depth + DELTA); collision_tilemap(object, depth+1); } @@ -699,19 +710,26 @@ Sector::collision_object(MovingObject* object1, MovingObject* object2) dest1.move(object1->get_movement()); Rectangle dest2 = object2->get_bbox(); dest2.move(object2->get_movement()); - if(Collision::rectangle_rectangle(hit, dest1, dest2)) { - HitResponse response = object1->collision(*object2, hit); - if(response == ABORT_MOVE) { - object1->movement = Vector(0, 0); - } else if(response == CONTINUE) { - object1->movement += hit.normal * (hit.depth/2 + .001); - } + + Vector movement = object1->get_movement() - object2->get_movement(); + if(Collision::rectangle_rectangle(hit, dest1, movement, dest2)) { + HitResponse response1 = object1->collision(*object2, hit); hit.normal *= -1; - response = object2->collision(*object1, hit); - if(response == ABORT_MOVE) { - object2->movement = Vector(0, 0); - } else if(response == CONTINUE) { - object2->movement += hit.normal * (hit.depth/2 + .001); + HitResponse response2 = object2->collision(*object1, hit); + + if(response1 != CONTINUE) { + if(response1 == ABORT_MOVE) + object1->movement = Vector(0, 0); + if(response2 == CONTINUE) + object2->movement += hit.normal * (hit.depth + DELTA); + } else if(response2 != CONTINUE) { + if(response2 == ABORT_MOVE) + object2->movement = Vector(0, 0); + if(response1 == CONTINUE) + object1->movement += -hit.normal * (hit.depth + DELTA); + } else { + object1->movement += -hit.normal * (hit.depth/2 + DELTA); + object2->movement += hit.normal * (hit.depth/2 + DELTA); } } } @@ -722,13 +740,17 @@ Sector::collision_handler() for(std::vector::iterator i = gameobjects.begin(); i != gameobjects.end(); ++i) { GameObject* gameobject = *i; - if(!gameobject->is_valid() - || gameobject->get_flags() & GameObject::FLAG_NO_COLLDET) + if(!gameobject->is_valid()) continue; MovingObject* movingobject = dynamic_cast (gameobject); if(!movingobject) continue; - + if(movingobject->get_flags() & GameObject::FLAG_NO_COLLDET) { + movingobject->bbox.move(movingobject->movement); + movingobject->movement = Vector(0, 0); + continue; + } + // collision with tilemap if(! (movingobject->movement == Vector(0, 0))) collision_tilemap(movingobject, 0); @@ -746,7 +768,7 @@ Sector::collision_handler() collision_object(movingobject, movingobject2); } - + movingobject->bbox.move(movingobject->get_movement()); movingobject->movement = Vector(0, 0); } @@ -792,13 +814,6 @@ Sector::add_smoke_cloud(const Vector& pos) return true; } -bool -Sector::add_particles(const Vector& epicenter, int min_angle, int max_angle, const Vector& initial_velocity, const Vector& acceleration, int number, Color color, int size, int life_time, int drawing_layer) -{ - add_object(new Particles(epicenter, min_angle, max_angle, initial_velocity, acceleration, number, color, size, life_time, drawing_layer)); - return true; -} - void Sector::add_floating_text(const Vector& pos, const std::string& text) {