X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fobject%2Fplatform.cpp;h=c6a2da656213c2e57abca593fa32ca98f0f256f5;hb=5745d9670262c91e6cd35363fd0d2ec169e7c8a4;hp=b0b2a3b1c1bce0c23d44d778b89598f36cc6388e;hpb=07ddaed2a657e4d2a3d038fed223fc5827159caf;p=supertux.git diff --git a/src/object/platform.cpp b/src/object/platform.cpp index b0b2a3b1c..c6a2da656 100644 --- a/src/object/platform.cpp +++ b/src/object/platform.cpp @@ -28,68 +28,123 @@ #include "player.hpp" #include "path.hpp" #include "path_walker.hpp" -#include "sprite/sprite_manager.hpp" +#include "sprite/sprite.hpp" #include "lisp/lisp.hpp" #include "object_factory.hpp" +#include "scripting/platform.hpp" +#include "scripting/squirrel_util.hpp" +#include "sector.hpp" Platform::Platform(const lisp::Lisp& reader) + : MovingSprite(reader, Vector(0,0), LAYER_OBJECTS, COLGROUP_STATIC), + speed(Vector(0,0)), + automatic(false), player_contact(false), last_player_contact(false) { - std::string sprite_name; - reader.get("sprite", sprite_name); - if(sprite_name == "") - throw std::runtime_error("No sprite specified in platform object"); - sprite.reset(sprite_manager->create(sprite_name)); - + bool running = true; + reader.get("name", name); + reader.get("running", running); + if ((name == "") && (!running)) automatic=true; const lisp::Lisp* pathLisp = reader.get_lisp("path"); if(pathLisp == NULL) throw std::runtime_error("No path specified for platform"); path.reset(new Path()); path->read(*pathLisp); - walker.reset(new PathWalker(path.get())); - - bbox.p1 = path->get_base(); - bbox.set_size(sprite->get_width(), sprite->get_height()); - - set_group(COLGROUP_STATIC); - flags |= FLAG_SOLID; + walker.reset(new PathWalker(path.get(), running)); + bbox.set_pos(path->get_base()); } -Platform::~Platform() +Platform::Platform(const Platform& other) + : MovingSprite(other), ScriptInterface(other), + speed(other.speed), + automatic(other.automatic), player_contact(false), last_player_contact(false) { + name = other.name; + path.reset(new Path(*other.path)); + walker.reset(new PathWalker(*other.walker)); + walker->path = &*path; } -//TODO: Squish Tux when standing between platform and solid tile/object -// Improve collision handling -// Move all MovingObjects lying on the platform instead of only the player HitResponse -Platform::collision(GameObject& other, const CollisionHit& hit) +Platform::collision(GameObject& other, const CollisionHit& ) { - if (typeid(other) == typeid(Player)) { - if (hit.normal.y >= 0.9) { - //Tux is standing on the platform - //Player* player = (Player*) &other; - //player->add_velocity(speed * 1.5); - return PASS_MOVEMENT; - } - } - if(other.get_flags() & FLAG_SOLID) { - //Collision with a solid tile - return ABORT_MOVE; - } + if (dynamic_cast(&other)) player_contact = true; return FORCE_MOVE; } void Platform::update(float elapsed_time) { - movement = walker->advance(elapsed_time); + // check if Platform should automatically pick a destination + if (automatic) { + + if (!player_contact && !walker->is_moving()) { + // Player doesn't touch platform and Platform is not moving + + // Travel to node nearest to nearest player + // FIXME: does not really use nearest player + Player* player = 0; + std::vector players = Sector::current()->get_players(); + for (std::vector::iterator playerIter = players.begin(); playerIter != players.end(); ++playerIter) { + player = *playerIter; + } + if (player) { + int nearest_node_id = path->get_nearest_node_no(player->get_bbox().p2); + if (nearest_node_id != -1) { + goto_node(nearest_node_id); + } + } + } + + if (player_contact && !last_player_contact && !walker->is_moving()) { + // Player touched platform, didn't touch last frame and Platform is not moving + + // Travel to node farthest from current position + int farthest_node_id = path->get_farthest_node_no(get_pos()); + if (farthest_node_id != -1) { + goto_node(farthest_node_id); + } + } + + // Clear player_contact flag set by collision() method + last_player_contact = player_contact; + player_contact = false; + } + + movement = walker->advance(elapsed_time) - get_pos(); speed = movement / elapsed_time; } void -Platform::draw(DrawingContext& context) +Platform::goto_node(int node_no) +{ + walker->goto_node(node_no); +} + +void +Platform::start_moving() +{ + walker->start_moving(); +} + +void +Platform::stop_moving() +{ + walker->stop_moving(); +} + +void +Platform::expose(HSQUIRRELVM vm, SQInteger table_idx) +{ + if (name.empty()) return; + Scripting::Platform* interface = new Scripting::Platform(this); + expose_object(vm, table_idx, interface, name, true); +} + +void +Platform::unexpose(HSQUIRRELVM vm, SQInteger table_idx) { - sprite->draw(context, get_pos(), LAYER_OBJECTS); + if (name.empty()) return; + Scripting::unexpose_object(vm, table_idx, name); } IMPLEMENT_FACTORY(Platform, "platform");