1
// $Id: pingus.cpp 2986 2007-08-17 16:20:09Z grumbel $
3
// Pingus - A free Lemmings clone
4
// Copyright (C) 2000 Ingo Ruhnke <grumbel@gmx.de>
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.
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.
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 02111-1307, USA.
22
#include "../math/vector3f.hpp"
23
#include "../display/drawing_context.hpp"
25
#include "../math.hpp"
26
#include "../direction.hpp"
27
#include "../resource.hpp"
30
namespace WorldMapNS {
32
Pingus::Pingus (PathGraph* arg_path)
35
sprite_standing (Resource::load_sprite("core/worldmap/pingus_standing")),
36
arrow (Resource::load_sprite("core/worldmap/arrow"))
38
sprite.load(Direction::LEFT, Resource::load_sprite("core/worldmap/pingus/left"));
39
sprite.load(Direction::RIGHT, Resource::load_sprite("core/worldmap/pingus/right"));
41
final_target_node = NoNode;
42
current_node = NoNode;
51
Pingus::draw (DrawingContext& gc)
53
// Add 10 to z_pos so that the pingu gets drawn above the node it is
55
if (final_target_node != NoNode && current_node == NoNode)
57
gc.draw(arrow, path->get_dot(final_target_node)->get_pos() + Vector3f(0, 0, 10));
62
gc.draw(sprite_standing, pos);
66
// FIXME: Replace the sprite and add up/down here
67
float direction = get_direction();
69
if (direction >= 0 && direction < 180)
70
gc.draw(sprite[Direction::RIGHT], pos + Vector3f(0, 0, 10));
72
gc.draw(sprite[Direction::LEFT], pos + Vector3f(0, 0, 10));
77
Pingus::update (float delta)
79
float direction = get_direction();
80
if (direction >= 0 && direction < 180)
81
sprite[Direction::RIGHT].update(delta);
83
sprite[Direction::LEFT].update(delta);
90
Pingus::update_walk (float delta)
92
float velocity = 70.0f;
94
//std::cout << "Updating Walk: " << edge_path_position << "/" << edge_path_length << std::endl;
95
// Update the edge_path_position
96
edge_path_position += velocity * delta;
98
if (edge_path_position > edge_path.length()) // target reached
100
if (node_path.empty ()) // final target reached
102
current_node = target_node;
103
final_target_node = NoNode;
105
else // edge is traveled, now go to the next node
111
// Recalc pingu position on the screen
117
Pingus::get_direction() const
119
return (atan2(last_pos.x - pos.x,
120
-(last_pos.y - pos.y)) / (float)Math::pi * 180.0f) + 180.0f;
124
Pingus::walk_to_node (NodeId target)
126
final_target_node = target;
128
if (current_node == target)
132
else if (current_node != NoNode) // pingu stands still
134
const PathfinderResult& res = path->get_path (current_node, target);
136
if (res.path.empty())
138
// No path could be found
143
node_path = res.path;
145
// Simulate that we just reached current_node, then update the edge_path
146
target_node = node_path.back(); // equal to current_node;
147
node_path.pop_back();
150
current_node = NoNode;
154
else // pingu between two nodes
156
if (target_node == target)
161
else if (source_node == target)
164
std::swap(target_node, source_node);
166
edge_path_position = edge_path.length() - edge_path_position;
172
const PathfinderResult& node_path1 = path->get_path (source_node, target);
173
const PathfinderResult& node_path2 = path->get_path (target_node, target);
175
// Check that a path exist
176
if (node_path1.path.empty())
178
if (node_path2.path.empty())
184
node_path = node_path2.path;
189
// Select the shorter path
190
if (node_path1.cost + edge_path_position
191
< node_path2.cost + (edge_path.length() - edge_path_position))
192
{ // walk to source node, which means to reverse the pingu
193
node_path = node_path1.path;
196
std::swap(target_node, source_node);
198
edge_path_position = edge_path.length() - edge_path_position;
201
{ // walk to target_node
202
node_path = node_path2.path;
206
// Pop the first element on the stack, since we are already targeting it
207
node_path.pop_back();
217
if (current_node != NoNode) // pingu stands still
219
return path->graph.resolve_node(current_node).data->get_pos ();
221
else // between two nodes
223
return edge_path.at(edge_path_position);
228
Pingus::set_position (NodeId node)
230
pos = path->get_dot(node)->get_pos();
235
Pingus::update_edge_path()
237
// Update source and target nodes
238
source_node = target_node;
239
target_node = node_path.back ();
240
node_path.pop_back (); // remove target node from list of nodes
242
edge_path_position = 0.0f;
245
Path* partial_path = path->graph.resolve_edge(source_node, target_node).data;
247
edge_path.push_back(path->graph.resolve_node(source_node).data->get_pos());
248
// Why do we need to reverse this?!
249
edge_path.reverse_insert(*partial_path);
250
edge_path.push_back(path->graph.resolve_node(target_node).data->get_pos());
256
return current_node == NoNode;
259
} // namespace WorldMapNS