X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fsector.cpp;h=f9b5ede9c662d17559d040c5e97c3dcfa556b3c9;hb=763454f90866bd4e7db95e5884c48a25d6b9bda1;hp=e4ec1dd795a5615f45a6c9885c12a5404d617dfa;hpb=995d8328815cad1e6572b832832bb61a8aeaeb8e;p=supertux.git diff --git a/src/sector.cpp b/src/sector.cpp index e4ec1dd79..f9b5ede9c 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -29,12 +29,12 @@ #include "app/globals.h" #include "sector.h" #include "utils/lispreader.h" -#include "gameobjs.h" -#include "camera.h" -#include "background.h" -#include "particlesystem.h" +#include "object/gameobjs.h" +#include "object/camera.h" +#include "object/background.h" +#include "object/particlesystem.h" +#include "object/tilemap.h" #include "tile.h" -#include "tilemap.h" #include "audio/sound_manager.h" #include "gameloop.h" #include "resources.h" @@ -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,12 +53,17 @@ #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; Sector::Sector() - : gravity(10), player(0), solids(0), background(0), camera(0), + : gravity(10), player(0), solids(0), camera(0), currentmusic(LEVEL_MUSIC) { song_title = "Mortimers_chipdisko.mod"; @@ -69,6 +73,9 @@ Sector::Sector() Sector::~Sector() { + update_game_objects(); + assert(gameobjects_new.size() == 0); + for(GameObjects::iterator i = gameobjects.begin(); i != gameobjects.end(); ++i) { delete *i; @@ -82,49 +89,17 @@ Sector::~Sector() _current = 0; } -Sector *Sector::create(const std::string& name, size_t width, size_t height) -{ - Sector *sector = new Sector; - sector->name = name; - TileMap *background = new TileMap(LAYER_BACKGROUNDTILES, false, width, height); - TileMap *interactive = new TileMap(LAYER_TILES, true, width, height); - TileMap *foreground = new TileMap(LAYER_FOREGROUNDTILES, false, width, height); - sector->add_object(background); - sector->add_object(interactive); - sector->add_object(foreground); - sector->solids = interactive; - sector->camera = new Camera(sector); - sector->add_object(sector->camera); - sector->update_game_objects(); - return sector; -} - 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; + return new Background(reader); } 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 +110,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,18 +126,16 @@ 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) { - return new BadGuy(badguykind_from_string(name), reader); - } else if(name == "trampoline") { - return new Trampoline(reader); - } else if(name == "flying-platform") { - 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,13 +164,16 @@ 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); } } } + update_game_objects(); + fix_old_tiles(); + update_game_objects(); if(!camera) { std::cerr << "sector '" << name << "' does not contain a camera.\n"; camera = new Camera(this); @@ -236,11 +214,11 @@ Sector::parse_old_format(LispReader& reader) bkgd_bottom.blue = b; if(backgroundimage != "") { - background = new Background; + Background* background = new Background; background->set_image(backgroundimage, bgspeed); add_object(background); } else { - background = new Background; + Background* background = new Background; background->set_gradient(bkgd_top, bkgd_bottom); add_object(background); } @@ -274,10 +252,7 @@ Sector::parse_old_format(LispReader& reader) || reader.read_int_vector("tilemap", tiles)) { TileMap* tilemap = new TileMap(); tilemap->set(width, height, tiles, LAYER_TILES, true); - solids = tilemap; add_object(tilemap); - - fix_old_tiles(); } if(reader.read_int_vector("background-tm", tiles)) { @@ -324,7 +299,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 { @@ -337,8 +312,14 @@ Sector::parse_old_format(LispReader& reader) } // add a camera - camera = new Camera(this); + Camera* camera = new Camera(this); add_object(camera); + + update_game_objects(); + fix_old_tiles(); + update_game_objects(); + if(solids == 0) + throw std::runtime_error("sector does not contain a solid tile layer."); } void @@ -353,6 +334,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); @@ -398,41 +391,6 @@ Sector::write(LispWriter& writer) } void -Sector::do_vertical_flip() -{ - // remove or fix later -#if 0 - for(GameObjects::iterator i = gameobjects_new.begin(); i != gameobjects_new.end(); ++i) - { - TileMap* tilemap = dynamic_cast (*i); - if(tilemap) - { - tilemap->do_vertical_flip(); - } - - BadGuy* badguy = dynamic_cast (*i); - if(badguy) - badguy->start_position.y = solids->get_height()*32 - badguy->start_position.y - 32; - Trampoline* trampoline = dynamic_cast (*i); - if(trampoline) - trampoline->base.y = solids->get_height()*32 - trampoline->base.y - 32; - FlyingPlatform* flying_platform = dynamic_cast (*i); - if(flying_platform) - flying_platform->base.y = solids->get_height()*32 - flying_platform->base.y - 32; - Door* door = dynamic_cast (*i); - if(door) - door->set_area(door->get_area().x, solids->get_height()*32 - door->get_area().y - 32); - } - - for(SpawnPoints::iterator i = spawnpoints.begin(); i != spawnpoints.end(); - ++i) { - SpawnPoint* spawn = *i; - spawn->pos.y = solids->get_height()*32 - spawn->pos.y - 32; - } -#endif -} - -void Sector::add_object(GameObject* object) { // make sure the object isn't already in the list @@ -523,8 +481,7 @@ Sector::action(float elapsed_time) } /* Handle all possible collisions. */ - collision_handler(); - + collision_handler(); update_game_objects(); } @@ -541,15 +498,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 +509,29 @@ 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); - gameobjects.push_back(*i); + TileMap* tilemap = dynamic_cast (*i); + if(tilemap && tilemap->is_solid()) { + if(solids == 0) { + solids = tilemap; + } 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_new.clear(); } @@ -594,6 +554,8 @@ Sector::draw(DrawingContext& context) context.pop_transform(); } +static const float DELTA = .001; + void Sector::collision_tilemap(MovingObject* object, int depth) { @@ -632,7 +594,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 +609,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 +628,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 +641,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 +653,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 +683,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,20 +711,12 @@ Sector::collision_handler() collision_object(movingobject, movingobject2); } - + movingobject->bbox.move(movingobject->get_movement()); movingobject->movement = Vector(0, 0); } } -void -Sector::add_score(const Vector& pos, int s) -{ - global_stats.add_points(SCORE_STAT, s); - - add_object(new FloatingText(pos, s)); -} - bool Sector::add_bullet(const Vector& pos, float xm, Direction dir) {