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

« back to all changes in this revision

Viewing changes to src/pingu.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Raphael Goulais
  • Date: 2004-08-09 10:26:00 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20040809102600-lg2q9lfars0q1p42
Tags: 0.6.0-8
Applied patch from Andreas Jochens (Closes: #263992)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  $Id: pingu.cxx,v 1.40 2003/03/21 22:08:06 grumbel Exp $
 
2
//
 
3
//  Pingus - A free Lemmings clone
 
4
//  Copyright (C) 1999 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 <assert.h>
 
21
#include <math.h>
 
22
#include <stdio.h>
 
23
#include "globals.hxx"
 
24
#include "world.hxx"
 
25
#include "sound/sound.hxx"
 
26
#include "col_map.hxx"
 
27
#include "pingu_action.hxx"
 
28
#include "pingu_action_factory.hxx"
 
29
#include "my_gettext.hxx"
 
30
#include "debug.hxx"
 
31
#include "worldobj.hxx"
 
32
#include "fonts.hxx"
 
33
 
 
34
using namespace Actions;
 
35
 
 
36
// Init a pingu at the given position while falling
 
37
Pingu::Pingu (int arg_id, const Vector& arg_pos, int owner)
 
38
  : action(0),
 
39
    countdown_action (0),
 
40
    wall_action(0),
 
41
    fall_action(0),
 
42
    previous_action(Actions::Faller),
 
43
    id(arg_id),
 
44
    action_time(-1),
 
45
    owner_id(owner),
 
46
    status(PS_ALIVE),
 
47
    pos_x(arg_pos.x),
 
48
    pos_y(arg_pos.y),
 
49
    velocity(new Vector(0, 0, 0))
 
50
{
 
51
  direction.left ();
 
52
 
 
53
  // Initialisize the action, after this step the action ptr will
 
54
  // always be valid in the pingu class
 
55
  action = PinguActionFactory::instance()->create(this, Faller);
 
56
}
 
57
 
 
58
Pingu::~Pingu ()
 
59
{
 
60
  delete velocity;
 
61
}
 
62
 
 
63
unsigned int
 
64
Pingu::get_id ()
 
65
{
 
66
  return id;
 
67
}
 
68
 
 
69
bool
 
70
Pingu::change_allowed (ActionName new_action)
 
71
{
 
72
  assert (action);
 
73
  return action->change_allowed (new_action);
 
74
}
 
75
 
 
76
void
 
77
Pingu::set_x (float x)
 
78
{
 
79
  //std::cout << "Pingu::set_x (" << x << ")" << std::endl;
 
80
  pos_x = x; 
 
81
}
 
82
  
 
83
void
 
84
Pingu::set_y (float y)
 
85
 
86
  //std::cout << "Pingu::set_y (" << y << ")" << std::endl;
 
87
  pos_y = y; 
 
88
}
 
89
 
 
90
void
 
91
Pingu::set_pos (float x, float y)
 
92
{
 
93
  set_x (x);
 
94
  set_y (y);
 
95
}
 
96
 
 
97
void
 
98
Pingu::set_pos (const Vector& arg_pos)
 
99
{
 
100
  set_x (arg_pos.x);
 
101
  set_y (arg_pos.y);
 
102
}
 
103
 
 
104
void
 
105
Pingu::set_velocity (const Vector& velocity_)
 
106
{
 
107
  *velocity = velocity_;
 
108
}
 
109
 
 
110
// Set the action of the pingu (bridger, blocker, bomber, etc.)
 
111
// This function is used by external stuff, like the ButtonPanel, etc
 
112
// When you select a function on the button panel and click on a
 
113
// pingu, this action will be called with the action name
 
114
bool
 
115
Pingu::request_set_action (PinguAction* act)
 
116
{
 
117
  bool ret_val = false;
 
118
  assert(act);
 
119
 
 
120
  if (status == PS_DEAD)
 
121
    {
 
122
      pout(PINGUS_DEBUG_ACTIONS) << _("Setting action to a dead pingu") << std::endl;
 
123
      ret_val =  false;
 
124
    }
 
125
  else
 
126
    {    
 
127
      switch (act->get_activation_mode()) {
 
128
  
 
129
      case INSTANT:
 
130
  
 
131
        if (act->get_type() == action->get_type()) 
 
132
          {
 
133
            pout(PINGUS_DEBUG_ACTIONS) << "Pingu: Already have action" << std::endl;
 
134
            ret_val = false;
 
135
          } 
 
136
        else if (action->change_allowed(act->get_type()))
 
137
          {
 
138
            pout(PINGUS_DEBUG_ACTIONS) << "setting instant action" << std::endl;
 
139
            set_action(act);
 
140
            ret_val = true;
 
141
          }
 
142
        else
 
143
          {
 
144
            pout(PINGUS_DEBUG_ACTIONS) << "change from action " << action->get_name () << " not allowed" << std::endl;
 
145
            ret_val = false;
 
146
          }
 
147
        break;
 
148
                
 
149
      case WALL_TRIGGERED:
 
150
    
 
151
        if (wall_action && wall_action->get_type() == act->get_type())
 
152
          {
 
153
            pout(PINGUS_DEBUG_ACTIONS) << "Not using wall action, we have already" << std::endl;
 
154
            ret_val = false;
 
155
          }
 
156
        else
 
157
          {
 
158
            pout(PINGUS_DEBUG_ACTIONS) << "Setting wall action" << std::endl;
 
159
            wall_action = act;
 
160
            ret_val = true;
 
161
          }
 
162
        break;
 
163
    
 
164
      case FALL_TRIGGERED:
 
165
  
 
166
        if (fall_action && fall_action->get_type() == act->get_type())
 
167
          {
 
168
            pout(PINGUS_DEBUG_ACTIONS) << "Not using fall action, we have already" << std::endl;
 
169
            ret_val = false;
 
170
          }
 
171
        else
 
172
          {
 
173
            pout(PINGUS_DEBUG_ACTIONS) << "Setting fall action" << std::endl;
 
174
            fall_action = act;
 
175
            ret_val = true;
 
176
          }
 
177
        break;
 
178
 
 
179
      case COUNTDOWN_TRIGGERED:
 
180
  
 
181
        if (countdown_action && countdown_action->get_type() == act->get_type())
 
182
          {
 
183
            pout(PINGUS_DEBUG_ACTIONS) << "Not using countdown action, we have already" << std::endl;
 
184
            ret_val = false;
 
185
            break;
 
186
          }
 
187
      
 
188
        pout(PINGUS_DEBUG_ACTIONS) << "Setting countdown action" << std::endl;
 
189
        // We set the action and start the countdown
 
190
        action_time = act->activation_time();
 
191
        countdown_action = act;
 
192
        ret_val = true;
 
193
        break;
 
194
          
 
195
      default:
 
196
        pout(PINGUS_DEBUG_ACTIONS) << "unknown action activation_mode" << std::endl;     
 
197
        ret_val = false;
 
198
        assert(0);
 
199
        break;
 
200
      }
 
201
    }
 
202
 
 
203
  if (ret_val) // Action successfull applied
 
204
    {
 
205
      act->on_successfull_apply();
 
206
    }
 
207
  else // Action failed to be set
 
208
    {
 
209
      act->on_failed_apply(this);
 
210
    }
 
211
    
 
212
  return ret_val;
 
213
}
 
214
 
 
215
bool 
 
216
Pingu::request_set_action (ActionName action_name)
 
217
{
 
218
  return request_set_action (PinguActionFactory::instance ()->create (this, action_name));
 
219
}
 
220
 
 
221
void
 
222
Pingu::set_action (ActionName action_name) 
 
223
{
 
224
  set_action(PinguActionFactory::instance()->create(this, action_name));
 
225
}
 
226
 
 
227
// Sets an action without any checking
 
228
void
 
229
Pingu::set_action (PinguAction* act) 
 
230
{
 
231
  assert(act);
 
232
 
 
233
  previous_action = action->get_type();
 
234
 
 
235
  action = act;
 
236
}
 
237
 
 
238
bool
 
239
Pingu::request_fall_action ()
 
240
{
 
241
  if (fall_action)
 
242
    {
 
243
      set_action(fall_action);
 
244
      return true;
 
245
    }
 
246
    
 
247
  return false;
 
248
}
 
249
 
 
250
bool
 
251
Pingu::request_wall_action ()
 
252
{
 
253
  if (wall_action)
 
254
    {
 
255
      set_action(wall_action);
 
256
      return true;
 
257
    }
 
258
 
 
259
  return false;
 
260
}
 
261
 
 
262
PinguStatus
 
263
Pingu::get_status (void) const
 
264
{
 
265
  return status;
 
266
}
 
267
 
 
268
PinguStatus
 
269
Pingu::set_status (PinguStatus s)
 
270
{
 
271
  return (status = s);
 
272
}
 
273
 
 
274
// Returns true if the given koordinates are above the pingu
 
275
bool
 
276
Pingu::is_over (int x, int y)
 
277
{
 
278
  Vector center = get_center_pos ();
 
279
 
 
280
  return (center.x + 16 > x && center.x - 16 < x &&
 
281
          center.y + 16 > y && center.y - 16 < y);
 
282
}
 
283
 
 
284
bool
 
285
Pingu::is_inside (int x1, int y1, int x2, int y2)
 
286
{
 
287
  assert (x1 < x2);
 
288
  assert (y1 < y2);
 
289
 
 
290
  return (pos_x > x1 && pos_x < x2 
 
291
          &&
 
292
          pos_y > y1 && pos_y < y2);
 
293
}
 
294
 
 
295
// Returns the distance between the Pingu and a given coordinate
 
296
double
 
297
Pingu::dist (int x, int y)
 
298
{
 
299
  Vector p = get_center_pos ();
 
300
  
 
301
  return sqrt(((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y)));
 
302
}
 
303
 
 
304
// Let the pingu do his job (i.e. walk his way)
 
305
void
 
306
Pingu::update ()
 
307
{
 
308
  if (status == PS_DEAD)
 
309
    return;
 
310
 
 
311
  // FIXME: Out of screen check is ugly
 
312
  /** The Pingu has hit the edge of the screen, a good time to let him
 
313
      die. */
 
314
  if (rel_getpixel(0, -1) == Groundtype::GP_OUTOFSCREEN) 
 
315
    {
 
316
      PingusSound::play_sound("die");
 
317
      status = PS_DEAD;
 
318
      return;
 
319
    }
 
320
 
 
321
  // if an countdown action is set, update the countdown time
 
322
  if (action_time > -1) 
 
323
    --action_time;
 
324
 
 
325
  if (action_time == 0 && countdown_action) 
 
326
    {
 
327
      set_action(countdown_action);
 
328
      // Reset the countdown action handlers 
 
329
      countdown_action = 0;
 
330
      action_time = -1;
 
331
      return;
 
332
    }
 
333
  
 
334
  action->update();
 
335
}
 
336
 
 
337
// Draws the pingu on the screen with the given offset
 
338
void
 
339
Pingu::draw (GraphicContext& gc)
 
340
{
 
341
  char str[16];
 
342
 
 
343
  action->draw (gc);
 
344
  
 
345
  if (action_time != -1) 
 
346
    {
 
347
      // FIXME: some people preffer a 5-0 or a 9-0 countdown, not sure
 
348
      // FIXME: about that got used to the 50-0 countdown [counting is
 
349
      // FIXME: in ticks, should probally be in seconds]
 
350
      snprintf(str, 16, "%d", action_time/3);
 
351
      
 
352
      gc.print_center(Fonts::lcd, 
 
353
                      static_cast<int>(pos_x), static_cast<int>(pos_y - 45) + 2, 
 
354
                      str);
 
355
    }
 
356
}
 
357
 
 
358
int
 
359
Pingu::rel_getpixel (int x, int y)
 
360
{
 
361
  return WorldObj::get_world()->get_colmap()->getpixel(static_cast<int>(pos_x + (x * direction)), 
 
362
                                                       static_cast<int>(pos_y - y));
 
363
}
 
364
 
 
365
void
 
366
Pingu::catch_pingu (Pingu* pingu)
 
367
{
 
368
  action->catch_pingu(pingu);
 
369
}
 
370
 
 
371
bool
 
372
Pingu::need_catch ()
 
373
{
 
374
  if (status == PS_DEAD || status == PS_EXITED)
 
375
    return false;
 
376
  
 
377
  return action->need_catch();
 
378
}
 
379
 
 
380
void
 
381
Pingu::set_direction (Direction d)
 
382
{
 
383
  direction = d;
 
384
}
 
385
 
 
386
bool
 
387
Pingu::is_alive (void)
 
388
{
 
389
  return (status != PS_DEAD && status != PS_EXITED);
 
390
}
 
391
 
 
392
std::string
 
393
Pingu::get_name()
 
394
{
 
395
  return action->get_name();
 
396
}
 
397
 
 
398
Actions::ActionName
 
399
Pingu::get_action ()
 
400
{
 
401
  return action->get_type();
 
402
}
 
403
 
 
404
void
 
405
Pingu::apply_force (Vector arg_v)
 
406
{
 
407
  *velocity += arg_v;
 
408
  // Moving the pingu on pixel up, so that the force can take effect
 
409
  // FIXME: this should be handled by a state-machine
 
410
  --pos_y; 
 
411
}
 
412
 
 
413
Vector
 
414
Pingu::get_pos () const
 
415
{
 
416
  return Vector(pos_x, pos_y, 0);
 
417
}
 
418
 
 
419
Vector
 
420
Pingu::get_center_pos () const
 
421
{
 
422
  return Vector(pos_x, pos_y) + Vector (0, -16); 
 
423
}
 
424
 
 
425
int 
 
426
Pingu::get_owner ()
 
427
{
 
428
  return owner_id;
 
429
}
 
430
 
 
431
bool 
 
432
Pingu::catchable ()
 
433
{
 
434
  return action->catchable ();
 
435
}
 
436
 
 
437
/* EOF */