X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fsector.cpp;h=fedeee512618286e9dfccfd4640f543306645964;hb=6e843b1780f62f45b7021bd8c38181aa211588ee;hp=e4ec1dd795a5615f45a6c9885c12a5404d617dfa;hpb=995d8328815cad1e6572b832832bb61a8aeaeb8e;p=supertux.git diff --git a/src/sector.cpp b/src/sector.cpp index e4ec1dd79..fedeee512 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -46,7 +46,6 @@ #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,31 +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; - fix_old_tiles(); - } - return tilemap; + return new TileMap(reader); } else if(name == "particles-snow") { SnowParticleSystem* partsys = new SnowParticleSystem(); partsys->parse(reader); @@ -135,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") { @@ -149,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) { @@ -159,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 @@ -189,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); } @@ -324,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 { @@ -353,6 +354,18 @@ Sector::fix_old_tiles() 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); @@ -541,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 { @@ -561,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(); } @@ -594,6 +611,8 @@ Sector::draw(DrawingContext& context) context.pop_transform(); } +static const float DELTA = .001; + void Sector::collision_tilemap(MovingObject* object, int depth) { @@ -632,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); @@ -647,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; } } @@ -680,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 @@ -693,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); } @@ -705,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); } } } @@ -728,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); @@ -752,7 +768,7 @@ Sector::collision_handler() collision_object(movingobject, movingobject2); } - + movingobject->bbox.move(movingobject->get_movement()); movingobject->movement = Vector(0, 0); }