1 | // Toad - A jumping toad |
2 | // Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de> |
3 | // |
4 | // This program is free software: you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation, either version 3 of the License, or |
7 | // (at your option) any later version. |
8 | // |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | #include "badguy/toad.hpp" |
18 | |
19 | #include "audio/sound_manager.hpp" |
20 | #include "object/player.hpp" |
21 | #include "sprite/sprite.hpp" |
22 | |
23 | namespace { |
24 | const float VERTICAL_SPEED = -450; /**< y-speed when jumping */ |
25 | const float HORIZONTAL_SPEED = 320; /**< x-speed when jumping */ |
26 | const float TOAD_RECOVER_TIME = 0.5; /**< time to stand still before starting a (new) jump */ |
27 | static const std::string HOP_SOUND = "sounds/hop.ogg" ; |
28 | } |
29 | |
30 | Toad::Toad(const ReaderMapping& reader) : |
31 | BadGuy(reader, "images/creatures/toad/toad.sprite" ), |
32 | recover_timer(), |
33 | state() |
34 | { |
35 | SoundManager::current()->preload(HOP_SOUND); |
36 | } |
37 | |
38 | void |
39 | Toad::initialize() |
40 | { |
41 | // initial state is JUMPING, because we might start airborne |
42 | state = JUMPING; |
43 | m_sprite->set_action(m_dir == Direction::LEFT ? "jumping-left" : "jumping-right" ); |
44 | } |
45 | |
46 | void |
47 | Toad::set_state(ToadState newState) |
48 | { |
49 | if (newState == IDLE) { |
50 | m_physic.set_velocity_x(0); |
51 | m_physic.set_velocity_y(0); |
52 | if (!m_frozen) |
53 | m_sprite->set_action(m_dir == Direction::LEFT ? "idle-left" : "idle-right" ); |
54 | |
55 | recover_timer.start(TOAD_RECOVER_TIME); |
56 | } else |
57 | if (newState == JUMPING) { |
58 | m_sprite->set_action(m_dir == Direction::LEFT ? "jumping-left" : "jumping-right" ); |
59 | m_physic.set_velocity_x(m_dir == Direction::LEFT ? -HORIZONTAL_SPEED : HORIZONTAL_SPEED); |
60 | m_physic.set_velocity_y(VERTICAL_SPEED); |
61 | SoundManager::current()->play( HOP_SOUND, get_pos()); |
62 | } else |
63 | if (newState == FALLING) { |
64 | Player* player = get_nearest_player(); |
65 | // face player |
66 | if (player && (player->get_bbox().get_right() < m_col.m_bbox.get_left()) && (m_dir == Direction::RIGHT)) m_dir = Direction::LEFT; |
67 | if (player && (player->get_bbox().get_left() > m_col.m_bbox.get_right()) && (m_dir == Direction::LEFT)) m_dir = Direction::RIGHT; |
68 | m_sprite->set_action(m_dir == Direction::LEFT ? "idle-left" : "idle-right" ); |
69 | } |
70 | |
71 | state = newState; |
72 | } |
73 | |
74 | bool |
75 | Toad::collision_squished(GameObject& object) |
76 | { |
77 | m_sprite->set_action(m_dir == Direction::LEFT ? "squished-left" : "squished-right" ); |
78 | kill_squished(object); |
79 | return true; |
80 | } |
81 | |
82 | void |
83 | Toad::collision_solid(const CollisionHit& hit) |
84 | { |
85 | // default behavior when frozen |
86 | if (m_frozen || BadGuy::get_state() == STATE_BURNING) |
87 | { |
88 | BadGuy::collision_solid(hit); |
89 | return; |
90 | } |
91 | |
92 | // just default behaviour (i.e. stop at floor/walls) when squished |
93 | if (BadGuy::get_state() == STATE_SQUISHED) { |
94 | BadGuy::collision_solid(hit); |
95 | return; |
96 | } |
97 | |
98 | // ignore collisions while standing still |
99 | if (state == IDLE) { |
100 | return; |
101 | } |
102 | |
103 | // check if we hit left or right while moving in either direction |
104 | if (((m_physic.get_velocity_x() < 0) && hit.left) || ((m_physic.get_velocity_x() > 0) && hit.right)) { |
105 | /* |
106 | dir = dir == LEFT ? RIGHT : LEFT; |
107 | if (state == JUMPING) { |
108 | sprite->set_action(dir == LEFT ? "jumping-left" : "jumping-right"); |
109 | } else { |
110 | sprite->set_action(dir == LEFT ? "idle-left" : "idle-right"); |
111 | } |
112 | */ |
113 | m_physic.set_velocity_x(-0.25f*m_physic.get_velocity_x()); |
114 | } |
115 | |
116 | // check if we hit the floor while falling |
117 | if ((state == FALLING) && hit.bottom) { |
118 | set_state(IDLE); |
119 | return; |
120 | } |
121 | |
122 | // check if we hit the roof while climbing |
123 | if ((state == JUMPING) && hit.top) { |
124 | m_physic.set_velocity_y(0); |
125 | } |
126 | |
127 | } |
128 | |
129 | HitResponse |
130 | Toad::collision_badguy(BadGuy& , const CollisionHit& hit) |
131 | { |
132 | // behaviour for badguy collisions is the same as for collisions with solids |
133 | collision_solid(hit); |
134 | |
135 | return CONTINUE; |
136 | } |
137 | |
138 | void |
139 | Toad::active_update(float dt_sec) |
140 | { |
141 | BadGuy::active_update(dt_sec); |
142 | |
143 | |
144 | // change sprite when we are falling and not frozen |
145 | if ((state == JUMPING) && (m_physic.get_velocity_y() > 0) && !m_frozen) { |
146 | set_state(FALLING); |
147 | return; |
148 | } |
149 | |
150 | // jump when fully recovered and if not frozen |
151 | if ((state == IDLE) && (recover_timer.check() && !m_frozen)) { |
152 | set_state(JUMPING); |
153 | return; |
154 | } |
155 | |
156 | } |
157 | |
158 | void |
159 | Toad::unfreeze() |
160 | { |
161 | BadGuy::unfreeze(); |
162 | initialize(); |
163 | } |
164 | |
165 | bool |
166 | Toad::is_freezable() const |
167 | { |
168 | return true; |
169 | } |
170 | |
171 | /* EOF */ |
172 | |