4 // Copyright (C) 2005 Philipp <balinor@pnxs.de>
5 // Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 #include "lisp/lisp.hpp"
25 #include "lisp/list_iterator.hpp"
26 #include "object_factory.hpp"
32 // snap to destination if within EPSILON pixels
35 Path::Path(const lisp::Lisp& reader)
40 if (!reader.get("name", name)) throw std::runtime_error("Path without name");
41 reader.get("circular", circular);
42 reader.get("forward", forward);
44 const lisp::Lisp* nodes_lisp = reader.get_lisp("nodes");
45 if(!nodes_lisp) throw std::runtime_error("Path without nodes");
47 lisp::ListIterator iter(nodes_lisp);
53 if(iter.item() != "node") {
54 std::cerr << "Warning: unknown token '" << iter.item() << "' in Path nodes list. Ignored." << std::endl;
57 const lisp::Lisp* node_lisp = iter.lisp();
59 // each new node will inherit all values from the last one
60 node_lisp->get("x", node.position.x);
61 node_lisp->get("y", node.position.y);
62 node_lisp->get("time", node.time);
64 if(node.time <= 0) throw std::runtime_error("Path node with non-positive time");
66 pathNodes.push_back(node);
69 if (pathNodes.size() < 1) throw std::runtime_error("Path with zero nodes");
71 // initial position and velocity will be set with the first update, as timeToGo is initialized to 0.
74 // register this path for lookup:
75 registry[name] = this;
84 Path::update(float elapsed_time)
87 // advance to next node at scheduled time
89 position = pathNodes[destinationNode].position;
91 // set destinationNode to next node
94 if (destinationNode >= (int)pathNodes.size()) {
98 destinationNode = (int)pathNodes.size()-1;
103 if (destinationNode < 0) {
105 destinationNode = (int)pathNodes.size()-1;
112 PathNode dn = pathNodes[destinationNode];
114 velocity = (dn.position - position) / timeToGo;
117 // move according to stored velocity
118 last_movement = velocity * elapsed_time;
119 position += last_movement;
120 timeToGo -= elapsed_time;
122 // stop when we arrive at our destination
123 PathNode dn = pathNodes[destinationNode];
124 if ((position - dn.position).norm() < EPSILON) {
125 velocity = Vector(0,0);
131 Path::draw(DrawingContext& )
133 // TODO: Add a visible flag, draw the path if true
137 Path::GetPosition() {
142 Path::GetLastMovement() {
143 return last_movement;
147 //////////////////////////////////////////////////////////////////////////////
150 std::map<std::string,Path*> Path::registry;
153 Path::GetByName(const std::string& name) {
154 return registry[name];
157 IMPLEMENT_FACTORY(Path, "path");