X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fobject%2Fpath.cpp;h=5f7cc094767159832ce7c79fea12040a83088dea;hb=113cdbf07f441329690714a53a436503ab1d4b35;hp=ce49d2b44d33bb4ee2f488c4762e803e555d2d91;hpb=ce0795230a1fbf9d4867f966aa6909d19975bfcf;p=supertux.git diff --git a/src/object/path.cpp b/src/object/path.cpp index ce49d2b44..5f7cc0947 100644 --- a/src/object/path.cpp +++ b/src/object/path.cpp @@ -1,7 +1,9 @@ // $Id$ -// -// SuperTux +// +// 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,142 +14,123 @@ // 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/lisp.hpp" #include "lisp/list_iterator.hpp" #include "object_factory.hpp" +#include "log.hpp" #include +#include +#include +#include - -// some constants -#define DEFAULT_PIXELS_PER_SECOND 50 -#define EPSILON 1.5 - -Path::Path(const lisp::Lisp& reader) +Path::Path() { - forward = true; - float x,y; - - lisp::ListIterator iter(&reader); - - assert (iter.next()); - std::string token = iter.item(); - assert(token == "name"); - iter.value()->get(name); - - circular = true; - assert (iter.next()); - token = iter.item(); - if (token == "circular") { - iter.value()->get(circular); - iter.next(); - } - - 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)); - } - } while(iter.next()); - - next_target = points.begin(); - pos = *next_target; - - calc_next_velocity(); - - // register this path for lookup: - registry[name] = this; } Path::~Path() { - registry.erase(name); } void -Path::update(float elapsed_time) +Path::read(const lisp::Lisp& reader) { - last_movement = velocity * elapsed_time; - pos += last_movement; - if ((pos - *next_target).norm() < EPSILON) { - pos = *next_target; - calc_next_velocity(); - } -} + lisp::ListIterator iter(&reader); -void -Path::draw(DrawingContext& ) -{ - // TODO: Add a visible flag, draw the path if true -} + 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; + } + + 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(); -const Vector& -Path::GetPosition() { - return pos; -} + // 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); -const Vector& -Path::GetStart() { - return *(points.begin()); -} + if(node.time <= 0) + throw std::runtime_error("Path node with non-positive time"); + + nodes.push_back(node); + } -const Vector& -Path::GetLastMovement() { - return last_movement; + if (nodes.empty()) + throw std::runtime_error("Path with zero nodes"); } void -Path::calc_next_velocity() +Path::write(lisp::Writer& writer) { - Vector distance; - - if (circular) { - ++next_target; - if (next_target == points.end()) { - next_target = points.begin(); - } - } - else if (forward) { - ++next_target; - if (next_target == points.end()) { - forward = false; - } - } - else { - //FIXME: Implement going backwards on the list - // I have no f***ing idea how this is done in C++ + 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; } - distance = *next_target - pos; - velocity = distance.unit() * pixels_per_second; -} + for (size_t i=0; i < nodes.size(); i++) { + const Node& node = nodes[i]; -////////////////////////////////////////////////////////////////////////////// -// static stuff + writer.start_list("node"); + writer.write_float("x", node.position.x); + writer.write_float("y", node.position.y); + writer.write_float("time", node.time); -PathRegistry Path::registry; + writer.end_list("node"); + } + + writer.end_list("path"); +} -Path* -Path::GetByName(const std::string& name) { - return registry[name]; +Vector +Path::get_base() const +{ + if(nodes.empty()) + return Vector(0, 0); + + return nodes[0].position; } -IMPLEMENT_FACTORY(Path, "path");