1
// $Id: pingu.cxx,v 1.40 2003/03/21 22:08:06 grumbel Exp $
3
// Pingus - A free Lemmings clone
4
// Copyright (C) 1999 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.
23
#include "globals.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"
31
#include "worldobj.hxx"
34
using namespace Actions;
36
// Init a pingu at the given position while falling
37
Pingu::Pingu (int arg_id, const Vector& arg_pos, int owner)
42
previous_action(Actions::Faller),
49
velocity(new Vector(0, 0, 0))
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);
70
Pingu::change_allowed (ActionName new_action)
73
return action->change_allowed (new_action);
77
Pingu::set_x (float x)
79
//std::cout << "Pingu::set_x (" << x << ")" << std::endl;
84
Pingu::set_y (float y)
86
//std::cout << "Pingu::set_y (" << y << ")" << std::endl;
91
Pingu::set_pos (float x, float y)
98
Pingu::set_pos (const Vector& arg_pos)
105
Pingu::set_velocity (const Vector& velocity_)
107
*velocity = velocity_;
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
115
Pingu::request_set_action (PinguAction* act)
117
bool ret_val = false;
120
if (status == PS_DEAD)
122
pout(PINGUS_DEBUG_ACTIONS) << _("Setting action to a dead pingu") << std::endl;
127
switch (act->get_activation_mode()) {
131
if (act->get_type() == action->get_type())
133
pout(PINGUS_DEBUG_ACTIONS) << "Pingu: Already have action" << std::endl;
136
else if (action->change_allowed(act->get_type()))
138
pout(PINGUS_DEBUG_ACTIONS) << "setting instant action" << std::endl;
144
pout(PINGUS_DEBUG_ACTIONS) << "change from action " << action->get_name () << " not allowed" << std::endl;
151
if (wall_action && wall_action->get_type() == act->get_type())
153
pout(PINGUS_DEBUG_ACTIONS) << "Not using wall action, we have already" << std::endl;
158
pout(PINGUS_DEBUG_ACTIONS) << "Setting wall action" << std::endl;
166
if (fall_action && fall_action->get_type() == act->get_type())
168
pout(PINGUS_DEBUG_ACTIONS) << "Not using fall action, we have already" << std::endl;
173
pout(PINGUS_DEBUG_ACTIONS) << "Setting fall action" << std::endl;
179
case COUNTDOWN_TRIGGERED:
181
if (countdown_action && countdown_action->get_type() == act->get_type())
183
pout(PINGUS_DEBUG_ACTIONS) << "Not using countdown action, we have already" << std::endl;
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;
196
pout(PINGUS_DEBUG_ACTIONS) << "unknown action activation_mode" << std::endl;
203
if (ret_val) // Action successfull applied
205
act->on_successfull_apply();
207
else // Action failed to be set
209
act->on_failed_apply(this);
216
Pingu::request_set_action (ActionName action_name)
218
return request_set_action (PinguActionFactory::instance ()->create (this, action_name));
222
Pingu::set_action (ActionName action_name)
224
set_action(PinguActionFactory::instance()->create(this, action_name));
227
// Sets an action without any checking
229
Pingu::set_action (PinguAction* act)
233
previous_action = action->get_type();
239
Pingu::request_fall_action ()
243
set_action(fall_action);
251
Pingu::request_wall_action ()
255
set_action(wall_action);
263
Pingu::get_status (void) const
269
Pingu::set_status (PinguStatus s)
274
// Returns true if the given koordinates are above the pingu
276
Pingu::is_over (int x, int y)
278
Vector center = get_center_pos ();
280
return (center.x + 16 > x && center.x - 16 < x &&
281
center.y + 16 > y && center.y - 16 < y);
285
Pingu::is_inside (int x1, int y1, int x2, int y2)
290
return (pos_x > x1 && pos_x < x2
292
pos_y > y1 && pos_y < y2);
295
// Returns the distance between the Pingu and a given coordinate
297
Pingu::dist (int x, int y)
299
Vector p = get_center_pos ();
301
return sqrt(((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y)));
304
// Let the pingu do his job (i.e. walk his way)
308
if (status == PS_DEAD)
311
// FIXME: Out of screen check is ugly
312
/** The Pingu has hit the edge of the screen, a good time to let him
314
if (rel_getpixel(0, -1) == Groundtype::GP_OUTOFSCREEN)
316
PingusSound::play_sound("die");
321
// if an countdown action is set, update the countdown time
322
if (action_time > -1)
325
if (action_time == 0 && countdown_action)
327
set_action(countdown_action);
328
// Reset the countdown action handlers
329
countdown_action = 0;
337
// Draws the pingu on the screen with the given offset
339
Pingu::draw (GraphicContext& gc)
345
if (action_time != -1)
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);
352
gc.print_center(Fonts::lcd,
353
static_cast<int>(pos_x), static_cast<int>(pos_y - 45) + 2,
359
Pingu::rel_getpixel (int x, int y)
361
return WorldObj::get_world()->get_colmap()->getpixel(static_cast<int>(pos_x + (x * direction)),
362
static_cast<int>(pos_y - y));
366
Pingu::catch_pingu (Pingu* pingu)
368
action->catch_pingu(pingu);
374
if (status == PS_DEAD || status == PS_EXITED)
377
return action->need_catch();
381
Pingu::set_direction (Direction d)
387
Pingu::is_alive (void)
389
return (status != PS_DEAD && status != PS_EXITED);
395
return action->get_name();
401
return action->get_type();
405
Pingu::apply_force (Vector 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
414
Pingu::get_pos () const
416
return Vector(pos_x, pos_y, 0);
420
Pingu::get_center_pos () const
422
return Vector(pos_x, pos_y) + Vector (0, -16);
434
return action->catchable ();