Patch by <balinor@pnxs.de>:
[supertux.git] / src / object / path.cpp
1 //  $Id:$
2 // 
3 //  SuperTux
4 //  Copyright (C) 2005 Philipp <balinor@pnxs.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 // 
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 //  02111-1307, USA.
20
21 #include "path.hpp"
22
23 #include "lisp/lisp.hpp"
24 #include "lisp/list_iterator.hpp"
25 #include "object_factory.hpp"
26
27 #include <assert.h>
28
29
30 // some constants
31 #define DEFAULT_PIXELS_PER_SECOND       50
32 #define EPSILON                         1.5
33
34 Path::Path(const lisp::Lisp& reader)
35 {
36   float x,y;
37
38   lisp::ListIterator iter(&reader);
39
40   assert (iter.next());
41   std::string token = iter.item();
42   assert(token == "name");
43   iter.value()->get(name);
44
45   pixels_per_second = DEFAULT_PIXELS_PER_SECOND;
46   assert (iter.next());
47   token = iter.item();
48   if (token == "speed") {
49     iter.value()->get(pixels_per_second);
50     iter.next();
51   }
52   do {
53     token = iter.item();
54     if(token == "x") {
55       iter.value()->get(x);
56     } else if(token == "y") {
57       iter.value()->get(y);
58       points.push_back(Vector(x,y));
59     }
60   } while(iter.next());
61
62   next_target = points.begin();
63   pos = *next_target;
64
65   calc_next_velocity();
66
67   // register this path for lookup:
68   registry[name] = this;
69 }
70
71 Path::~Path()
72 {
73   registry.erase(name);
74 }
75
76 void
77 Path::update(float elapsed_time)
78 {
79   last_movement = velocity * elapsed_time;
80   pos += last_movement;
81   if ((pos - *next_target).norm() < EPSILON) {
82     pos = *next_target;
83     calc_next_velocity();
84   }
85 }
86
87 void
88 Path::draw(DrawingContext& context)
89 {
90   // NOOP ;-)
91 }
92
93 const Vector&
94 Path::GetPosition() {
95   return pos;
96 }
97
98 const Vector&
99 Path::GetStart() {
100   return *(points.begin());
101 }
102
103 const Vector&
104 Path::GetLastMovement() {
105   return last_movement;
106 }
107
108 void
109 Path::calc_next_velocity()
110 {
111   Vector distance;
112
113   ++next_target;
114   if (next_target == points.end()) {
115     next_target = points.begin();
116   }
117
118   distance = *next_target - pos;
119   velocity = distance.unit() * pixels_per_second;
120 }
121
122 //////////////////////////////////////////////////////////////////////////////
123 // static stuff
124
125 PathRegistry Path::registry;
126
127 Path*
128 Path::GetByName(const std::string& name) {
129   return registry[name];
130 }
131
132 IMPLEMENT_FACTORY(Path, "path");