~ubuntu-branches/ubuntu/precise/pingus/precise

« back to all changes in this revision

Viewing changes to src/worldmap/pingus.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cyril Brulebois
  • Date: 2008-02-28 19:44:25 UTC
  • mfrom: (4.1.4 hardy)
  • Revision ID: james.westby@ubuntu.com-20080228194425-e8ilohlijv02kgcf
Tags: 0.7.2-2
* Fix FTBFS with gcc-4.3 by adding the missing include in
  src/input/evdev_device.cpp (Closes: #462238):
   + debian/patches/20_fix_FTBFS_with_gcc-4.3.
* Rename former patch so that the filename reflects the order in which
  the patches are applied:
   - debian/patches/data_dir.patch
   + debian/patches/10_fix_data_directory.
* Bump Standards-Version from 3.7.2 to 3.7.3, no changes needed.
* Add a dh_desktop call in the arch-dep part of debian/rules.
* Adjust the “missing-dep-for-interpreter guile” override since lintian
  now lists an alternative for that dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  $Id: pingus.cpp 2986 2007-08-17 16:20:09Z grumbel $
 
2
//
 
3
//  Pingus - A free Lemmings clone
 
4
//  Copyright (C) 2000 Ingo Ruhnke <grumbel@gmx.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  02111-1307, USA.
 
19
 
 
20
#include <iostream>
 
21
#include <math.h>
 
22
#include "../math/vector3f.hpp"
 
23
#include "../display/drawing_context.hpp"
 
24
#include "dot.hpp"
 
25
#include "../math.hpp"
 
26
#include "../direction.hpp"
 
27
#include "../resource.hpp"
 
28
#include "pingus.hpp"
 
29
 
 
30
namespace WorldMapNS {
 
31
 
 
32
Pingus::Pingus (PathGraph* arg_path)
 
33
  : Drawable("pingus"),
 
34
    path(arg_path),
 
35
    sprite_standing (Resource::load_sprite("core/worldmap/pingus_standing")),
 
36
    arrow (Resource::load_sprite("core/worldmap/arrow"))
 
37
{
 
38
  sprite.load(Direction::LEFT,  Resource::load_sprite("core/worldmap/pingus/left"));
 
39
  sprite.load(Direction::RIGHT, Resource::load_sprite("core/worldmap/pingus/right"));
 
40
 
 
41
  final_target_node = NoNode;
 
42
  current_node = NoNode;
 
43
}
 
44
 
 
45
Pingus::~Pingus ()
 
46
{
 
47
}
 
48
 
 
49
 
 
50
void
 
51
Pingus::draw (DrawingContext& gc)
 
52
{
 
53
  // Add 10 to z_pos so that the pingu gets drawn above the node it is
 
54
  // standing one
 
55
  if (final_target_node != NoNode && current_node == NoNode)
 
56
    {
 
57
      gc.draw(arrow, path->get_dot(final_target_node)->get_pos() + Vector3f(0, 0, 10));
 
58
    }
 
59
 
 
60
  if (!is_walking())
 
61
    {
 
62
      gc.draw(sprite_standing, pos);
 
63
    }
 
64
  else
 
65
    {
 
66
      // FIXME: Replace the sprite and add up/down here
 
67
      float direction = get_direction();
 
68
      
 
69
      if (direction >= 0 && direction < 180)
 
70
        gc.draw(sprite[Direction::RIGHT], pos + Vector3f(0, 0, 10));
 
71
      else
 
72
        gc.draw(sprite[Direction::LEFT], pos + Vector3f(0, 0, 10));
 
73
    }
 
74
}
 
75
 
 
76
void
 
77
Pingus::update (float delta)
 
78
{
 
79
  float direction = get_direction();
 
80
  if (direction >= 0 && direction < 180)
 
81
    sprite[Direction::RIGHT].update(delta);
 
82
  else
 
83
    sprite[Direction::LEFT].update(delta);
 
84
  
 
85
  if (is_walking())
 
86
    update_walk(delta);
 
87
}
 
88
 
 
89
void
 
90
Pingus::update_walk (float delta)
 
91
{
 
92
  float velocity = 70.0f;
 
93
 
 
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;
 
97
 
 
98
  if (edge_path_position > edge_path.length()) // target reached
 
99
    {
 
100
      if (node_path.empty ()) // final target reached
 
101
        {
 
102
          current_node = target_node;
 
103
          final_target_node = NoNode;
 
104
        }
 
105
      else // edge is traveled, now go to the next node
 
106
        {
 
107
          update_edge_path();
 
108
        }
 
109
    }
 
110
 
 
111
  // Recalc pingu position on the screen
 
112
  last_pos = pos;
 
113
  pos = calc_pos ();
 
114
}
 
115
 
 
116
float
 
117
Pingus::get_direction() const
 
118
{
 
119
  return (atan2(last_pos.x - pos.x,
 
120
                -(last_pos.y - pos.y)) / (float)Math::pi * 180.0f) + 180.0f;
 
121
}
 
122
 
 
123
bool
 
124
Pingus::walk_to_node (NodeId target)
 
125
{
 
126
  final_target_node = target;
 
127
 
 
128
  if (current_node == target)
 
129
    {
 
130
      return true;
 
131
    }
 
132
  else if (current_node != NoNode) // pingu stands still
 
133
    {
 
134
      const PathfinderResult& res = path->get_path (current_node, target);
 
135
 
 
136
      if (res.path.empty())
 
137
        {
 
138
          // No path could be found
 
139
          return false;
 
140
        }
 
141
      else
 
142
        {
 
143
          node_path = res.path;
 
144
 
 
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();
 
148
          update_edge_path();
 
149
 
 
150
          current_node = NoNode;
 
151
          return true;
 
152
        }
 
153
    }
 
154
  else // pingu between two nodes
 
155
    {
 
156
      if (target_node == target)
 
157
        {
 
158
          node_path.clear();
 
159
          return true;
 
160
        }
 
161
      else if (source_node == target)
 
162
        {
 
163
          // Reverse the pingu
 
164
          std::swap(target_node, source_node);
 
165
          edge_path.reverse();
 
166
          edge_path_position = edge_path.length() - edge_path_position;
 
167
          node_path.clear();
 
168
          return true;
 
169
        }
 
170
      else
 
171
        {
 
172
          const PathfinderResult& node_path1 = path->get_path (source_node, target);
 
173
          const PathfinderResult& node_path2 = path->get_path (target_node, target);
 
174
 
 
175
          // Check that a path exist
 
176
          if (node_path1.path.empty())
 
177
            {
 
178
              if (node_path2.path.empty())
 
179
                {
 
180
                  return false;
 
181
                }
 
182
              else
 
183
                {
 
184
                  node_path = node_path2.path;
 
185
                }
 
186
            }
 
187
          else
 
188
            {
 
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;
 
194
 
 
195
                  // Reverse the pingu
 
196
                  std::swap(target_node, source_node);
 
197
                  edge_path.reverse();
 
198
                  edge_path_position = edge_path.length() - edge_path_position;
 
199
                }
 
200
              else
 
201
                { // walk to target_node
 
202
                  node_path = node_path2.path;
 
203
                }
 
204
            }
 
205
 
 
206
          // Pop the first element on the stack, since we are already targeting it
 
207
          node_path.pop_back();
 
208
 
 
209
          return true;
 
210
        }
 
211
    }
 
212
}
 
213
 
 
214
Vector3f
 
215
Pingus::calc_pos ()
 
216
{
 
217
  if (current_node != NoNode) // pingu stands still
 
218
    {
 
219
      return path->graph.resolve_node(current_node).data->get_pos ();
 
220
    }
 
221
  else // between two nodes
 
222
    {
 
223
      return edge_path.at(edge_path_position);
 
224
    }
 
225
}
 
226
 
 
227
void
 
228
Pingus::set_position (NodeId node)
 
229
{
 
230
  pos = path->get_dot(node)->get_pos();
 
231
  current_node = node;
 
232
}
 
233
 
 
234
void
 
235
Pingus::update_edge_path()
 
236
{
 
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
 
241
 
 
242
  edge_path_position = 0.0f;
 
243
  edge_path.clear();
 
244
 
 
245
  Path* partial_path = path->graph.resolve_edge(source_node, target_node).data;
 
246
 
 
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());
 
251
}
 
252
 
 
253
bool
 
254
Pingus::is_walking()
 
255
{
 
256
  return current_node == NoNode;
 
257
}
 
258
 
 
259
} // namespace WorldMapNS
 
260
 
 
261
/* EOF */