X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fobject%2Fpath.cpp;h=5d7e88a7da8e0cca8a2401e17b3e32cadbc2a711;hb=555d1b7bebb45326d82d934e07463209837309b0;hp=8fa5a16251717576114b723a33e86ebe62332c72;hpb=1bfcf5a82ac306fa5380c4db2be5109b61fac58e;p=supertux.git diff --git a/src/object/path.cpp b/src/object/path.cpp index 8fa5a1625..5d7e88a7d 100644 --- a/src/object/path.cpp +++ b/src/object/path.cpp @@ -1,7 +1,9 @@ -// $Id:$ -// -// SuperTux +// $Id$ +// +// SuperTux Path // Copyright (C) 2005 Philipp +// Copyright (C) 2006 Christoph Sommer +// Copyright (C) 2006 Matthias Braun // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -12,121 +14,156 @@ // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. +#include #include "path.hpp" +#include "lisp/writer.hpp" #include "lisp/lisp.hpp" #include "lisp/list_iterator.hpp" #include "object_factory.hpp" +#include "log.hpp" #include +#include +#include +#include +Path::Path() +{ +} -// some constants -#define DEFAULT_PIXELS_PER_SECOND 50 -#define EPSILON 1.5 - -Path::Path(const lisp::Lisp& reader) +Path::~Path() { - float x,y; +} +void +Path::read(const lisp::Lisp& reader) +{ lisp::ListIterator iter(&reader); - assert (iter.next()); - std::string token = iter.item(); - assert(token == "name"); - iter.value()->get(name); - - pixels_per_second = DEFAULT_PIXELS_PER_SECOND; - assert (iter.next()); - token = iter.item(); - if (token == "speed") { - iter.value()->get(pixels_per_second); - iter.next(); - } - do { - token = iter.item(); - if(token == "x") { - iter.value()->get(x); - } else if(token == "y") { - iter.value()->get(y); - points.push_back(Vector(x,y)); + mode = CIRCULAR; + while(iter.next()) { + if(iter.item() == "mode") { + std::string mode_string; + if(!iter.value()->get(mode_string)) + throw std::runtime_error("Pathmode not a string"); + + if(mode_string == "oneshot") + mode = ONE_SHOT; + else if(mode_string == "pingpong") + mode = PING_PONG; + else if(mode_string == "circular") + mode = CIRCULAR; + else { + std::ostringstream msg; + msg << "Unknown pathmode '" << mode_string << "' found"; + throw std::runtime_error(msg.str()); + } + continue; } - } while(iter.next()); - next_target = points.begin(); - pos = *next_target; + if(iter.item() != "node") { + log_warning << "unknown token '" << iter.item() << "' in Path nodes list. Ignored." << std::endl; + continue; + } + const lisp::Lisp* node_lisp = iter.lisp(); - calc_next_velocity(); + // each new node will inherit all values from the last one + Node node; + node.time = 1; + if( (!node_lisp->get("x", node.position.x) || + !node_lisp->get("y", node.position.y))) + throw std::runtime_error("Path node without x and y coordinate specified"); + node_lisp->get("time", node.time); - // register this path for lookup: - registry[name] = this; -} + if(node.time <= 0) + throw std::runtime_error("Path node with non-positive time"); -Path::~Path() -{ - registry.erase(name); + nodes.push_back(node); + } + + if (nodes.empty()) + throw std::runtime_error("Path with zero nodes"); } void -Path::update(float elapsed_time) +Path::write(lisp::Writer& writer) { - last_movement = velocity * elapsed_time; - pos += last_movement; - if ((pos - *next_target).norm() < EPSILON) { - pos = *next_target; - calc_next_velocity(); + writer.start_list("path"); + + switch(mode) { + case ONE_SHOT: + writer.write_string("mode", "oneshot"); + break; + case PING_PONG: + writer.write_string("mode", "pingpong"); + break; + case CIRCULAR: + writer.write_string("mode", "circular"); + break; + default: + log_warning << "Don't know how to write mode " << (int) mode << " ?!?" << std::endl; + break; } -} -void -Path::draw(DrawingContext& context) -{ - // NOOP ;-) -} + for (size_t i=0; i < nodes.size(); i++) { + const Node& node = nodes[i]; -const Vector& -Path::GetPosition() { - return pos; -} + writer.start_list("node"); + writer.write_float("x", node.position.x); + writer.write_float("y", node.position.y); + writer.write_float("time", node.time); -const Vector& -Path::GetStart() { - return *(points.begin()); -} + writer.end_list("node"); + } -const Vector& -Path::GetLastMovement() { - return last_movement; + writer.end_list("path"); } -void -Path::calc_next_velocity() +Vector +Path::get_base() const { - Vector distance; - - ++next_target; - if (next_target == points.end()) { - next_target = points.begin(); - } + if(nodes.empty()) + return Vector(0, 0); - distance = *next_target - pos; - velocity = distance.unit() * pixels_per_second; + return nodes[0].position; } -////////////////////////////////////////////////////////////////////////////// -// static stuff - -PathRegistry Path::registry; +int +Path::get_nearest_node_no(Vector reference_point) const +{ + int nearest_node_id = -1; + float nearest_node_dist = 0; + int id = 0; + for (std::vector::const_iterator i = nodes.begin(); i != nodes.end(); i++, id++) { + float dist = (i->position - reference_point).norm(); + if ((nearest_node_id == -1) || (dist < nearest_node_dist)) { + nearest_node_id = id; + nearest_node_dist = dist; + } + } + return nearest_node_id; +} -Path* -Path::GetByName(const std::string& name) { - return registry[name]; +int +Path::get_farthest_node_no(Vector reference_point) const +{ + int farthest_node_id = -1; + float farthest_node_dist = 0; + int id = 0; + for (std::vector::const_iterator i = nodes.begin(); i != nodes.end(); i++, id++) { + float dist = (i->position - reference_point).norm(); + if ((farthest_node_id == -1) || (dist > farthest_node_dist)) { + farthest_node_id = id; + farthest_node_dist = dist; + } + } + return farthest_node_id; } -IMPLEMENT_FACTORY(Path, "path");