[ Patch #1793 ] Turn physic into POD
[supertux.git] / src / badguy / toad.cpp
1 //  $Id: toad.cpp 4192 2006-08-16 23:25:39Z sommer $
2 //
3 //  Toad - A jumping toad
4 //  Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.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 #include <config.h>
21
22 #include "toad.hpp"
23 #include "random_generator.hpp"
24
25 namespace {
26   const float VERTICAL_SPEED = -450;   /**< y-speed when jumping */
27   const float HORIZONTAL_SPEED = 320; /**< x-speed when jumping */
28   const float RECOVER_TIME = 0.5; /**< time to stand still before starting a (new) jump */
29   static const std::string HOP_SOUND = "sounds/hop.ogg";
30 }
31
32 Toad::Toad(const lisp::Lisp& reader)
33         : BadGuy(reader, "images/creatures/toad/toad.sprite")
34 {
35   sound_manager->preload(HOP_SOUND);
36 }
37
38 Toad::Toad(const Vector& pos, Direction d)
39         : BadGuy(pos, d, "images/creatures/toad/toad.sprite")
40 {
41   sound_manager->preload(HOP_SOUND);
42 }
43
44 void
45 Toad::write(lisp::Writer& writer)
46 {
47   writer.start_list("toad");
48   writer.write_float("x", start_position.x);
49   writer.write_float("y", start_position.y);
50   writer.end_list("toad");
51 }
52
53 void
54 Toad::activate()
55 {
56   // initial state is JUMPING, because we might start airborne
57   state = JUMPING;
58   sprite->set_action(dir == LEFT ? "jumping-left" : "jumping-right");
59 }
60
61 void
62 Toad::set_state(ToadState newState)
63 {
64   if (newState == IDLE) {
65     physic.vx = 0;
66     physic.vy = 0;
67     sprite->set_action(dir == LEFT ? "idle-left" : "idle-right");
68
69     recover_timer.start(RECOVER_TIME);
70   } else
71   if (newState == JUMPING) {
72     sprite->set_action(dir == LEFT ? "jumping-left" : "jumping-right");
73     physic.vx = (dir == LEFT ? -HORIZONTAL_SPEED : HORIZONTAL_SPEED);
74     physic.vy = VERTICAL_SPEED;
75     sound_manager->play( HOP_SOUND, get_pos());
76   } else
77   if (newState == FALLING) {
78     Player* player = get_nearest_player();
79     // face player
80     if (player && (player->get_bbox().p2.x < get_bbox().p1.x) && (dir == RIGHT)) dir = LEFT;
81     if (player && (player->get_bbox().p1.x > get_bbox().p2.x) && (dir == LEFT)) dir = RIGHT;
82     sprite->set_action(dir == LEFT ? "idle-left" : "idle-right");
83   }
84
85   state = newState;
86 }
87
88 bool
89 Toad::collision_squished(GameObject& object)
90 {
91   sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
92   kill_squished(object);
93   return true;
94 }
95
96 void
97 Toad::collision_solid(const CollisionHit& hit)
98 {
99   // just default behaviour (i.e. stop at floor/walls) when squished
100   if (BadGuy::get_state() == STATE_SQUISHED) {
101     BadGuy::collision_solid(hit);
102     return;
103   }
104
105   // ignore collisions while standing still
106   if(state == IDLE) {
107     return;
108   }
109
110   // check if we hit left or right while moving in either direction
111   if(((physic.vx < 0) && hit.left) || ((physic.vx > 0) && hit.right)) {
112     /*
113     dir = dir == LEFT ? RIGHT : LEFT;
114     if (state == JUMPING) {
115       sprite->set_action(dir == LEFT ? "jumping-left" : "jumping-right");
116     } else {
117       sprite->set_action(dir == LEFT ? "idle-left" : "idle-right");
118     }
119     */
120     physic.vx = -0.25*physic.vx;
121   }
122
123   // check if we hit the floor while falling
124   if ((state == FALLING) && hit.bottom) {
125     set_state(IDLE);
126     return;
127   }
128
129   // check if we hit the roof while climbing
130   if ((state == JUMPING) && hit.top) {
131     physic.vy = 0;
132   }
133
134 }
135
136 HitResponse
137 Toad::collision_badguy(BadGuy& , const CollisionHit& hit)
138 {
139   // behaviour for badguy collisions is the same as for collisions with solids
140   collision_solid(hit);
141
142   return CONTINUE;
143 }
144
145 void
146 Toad::active_update(float elapsed_time)
147 {
148   BadGuy::active_update(elapsed_time);
149
150   // change sprite when we are falling
151   if ((state == JUMPING) && (physic.vy > 0)) {
152     set_state(FALLING);
153     return;
154   }
155
156   // jump when fully recovered
157   if ((state == IDLE) && (recover_timer.check())) {
158     set_state(JUMPING);
159     return;
160   }
161
162 }
163
164 IMPLEMENT_FACTORY(Toad, "toad")