1// SuperTux badguy - walking flame that glows
2// Copyright (C) 2013 LMH <lmh.0013@gmail.com>
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/livefire.hpp"
18
19#include "audio/sound_manager.hpp"
20#include "editor/editor.hpp"
21#include "object/player.hpp"
22#include "object/sprite_particle.hpp"
23#include "sprite/sprite.hpp"
24#include "supertux/sector.hpp"
25
26LiveFire::LiveFire(const ReaderMapping& reader) :
27 WalkingBadguy(reader, "images/creatures/livefire/livefire.sprite", "left", "right"),
28 death_sound("sounds/fall.wav"),
29 state(STATE_WALKING)
30{
31 walk_speed = 80;
32 max_drop_height = 20;
33 m_lightsprite->set_color(Color(1.0f, 1.0f, 1.0f));
34 m_glowing = true;
35}
36
37void
38LiveFire::collision_solid(const CollisionHit& hit)
39{
40 if (state != STATE_WALKING) {
41 BadGuy::collision_solid(hit);
42 return;
43 }
44 WalkingBadguy::collision_solid(hit);
45}
46
47HitResponse
48LiveFire::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
49{
50 if (state != STATE_WALKING) {
51 return BadGuy::collision_badguy(badguy, hit);
52 }
53 return WalkingBadguy::collision_badguy(badguy, hit);
54}
55
56void
57LiveFire::active_update(float dt_sec) {
58
59 // Remove when extinguish animation is done
60 if ((m_sprite->get_action() == "extinguish-left" || m_sprite->get_action() == "extinguish-right" )
61 && m_sprite->animation_done()) remove_me();
62
63 if (state == STATE_WALKING) {
64 WalkingBadguy::active_update(dt_sec);
65 return;
66 }
67
68 if (state == STATE_SLEEPING && m_col.get_group() == COLGROUP_MOVING) {
69
70 auto player = get_nearest_player();
71 if (player) {
72 Rectf pb = player->get_bbox();
73
74 bool inReach_left = (pb.get_right() >= m_col.m_bbox.get_right()-((m_dir == Direction::LEFT) ? 256 : 0));
75 bool inReach_right = (pb.get_left() <= m_col.m_bbox.get_left()+((m_dir == Direction::RIGHT) ? 256 : 0));
76 bool inReach_top = (pb.get_bottom() >= m_col.m_bbox.get_top());
77 bool inReach_bottom = (pb.get_top() <= m_col.m_bbox.get_bottom());
78
79 if (inReach_left && inReach_right && inReach_top && inReach_bottom) {
80 // wake up
81 m_sprite->set_action(m_dir == Direction::LEFT ? "waking-left" : "waking-right", 1);
82 state = STATE_WAKING;
83 }
84 }
85 }
86 else if (state == STATE_WAKING) {
87 if (m_sprite->animation_done()) {
88 // start walking
89 state = STATE_WALKING;
90 WalkingBadguy::initialize();
91 }
92 }
93
94 BadGuy::active_update(dt_sec);
95}
96
97void
98LiveFire::freeze()
99{
100 // attempting to freeze a flame causes it to go out
101 death_sound = "sounds/sizzle.ogg";
102 kill_fall();
103}
104
105bool
106LiveFire::is_freezable() const
107{
108 return true;
109}
110
111bool
112LiveFire::is_flammable() const
113{
114 return false;
115}
116
117void
118LiveFire::kill_fall()
119{
120 SoundManager::current()->play(death_sound, get_pos());
121 // throw a puff of smoke
122 Vector ppos = m_col.m_bbox.get_middle();
123 Vector pspeed = Vector(0, -150);
124 Vector paccel = Vector(0,0);
125 Sector::get().add<SpriteParticle>("images/objects/particles/smoke.sprite",
126 "default", ppos, ANCHOR_MIDDLE,
127 pspeed, paccel,
128 LAYER_BACKGROUNDTILES+2);
129 // extinguish the flame
130 m_sprite->set_action(m_dir == Direction::LEFT ? "extinguish-left" : "extinguish-right", 1);
131 m_physic.set_velocity_y(0);
132 m_physic.set_acceleration_y(0);
133 m_physic.enable_gravity(false);
134 m_lightsprite->set_blend(Blend::ADD);
135 m_lightsprite->set_color(Color(1.0f, 0.9f, 0.8f));
136 set_group(COLGROUP_DISABLED);
137
138 // start dead-script
139 run_dead_script();
140}
141
142/* The following defines a sleeping version */
143
144LiveFireAsleep::LiveFireAsleep(const ReaderMapping& reader) :
145 LiveFire(reader)
146{
147 state = STATE_SLEEPING;
148}
149
150void
151LiveFireAsleep::draw(DrawingContext& context)
152{
153 if (Editor::is_active()) {
154 m_sprite->set_action(m_dir == Direction::LEFT ? "sleeping-left" : "sleeping-right");
155 BadGuy::draw(context);
156 } else {
157 LiveFire::draw(context);
158 }
159}
160
161void
162LiveFireAsleep::initialize()
163{
164 m_physic.set_velocity_x(0);
165 m_sprite->set_action(m_dir == Direction::LEFT ? "sleeping-left" : "sleeping-right");
166}
167
168/* The following defines a dormant version that never wakes */
169LiveFireDormant::LiveFireDormant(const ReaderMapping& reader) :
170 LiveFire(reader)
171{
172 walk_speed = 0;
173 state = STATE_DORMANT;
174}
175
176void
177LiveFireDormant::draw(DrawingContext& context)
178{
179 if (Editor::is_active()) {
180 m_sprite->set_action(m_dir == Direction::LEFT ? "sleeping-left" : "sleeping-right");
181 BadGuy::draw(context);
182 } else {
183 LiveFire::draw(context);
184 }
185}
186
187void
188LiveFireDormant::initialize()
189{
190 m_physic.set_velocity_x(0);
191 m_sprite->set_action(m_dir == Direction::LEFT ? "sleeping-left" : "sleeping-right");
192}
193
194/* EOF */
195