7652f8ed3eb468f72852e5b8b05aa3fbd22ae434
[supertux.git] / src / badguy / walkingflame.cpp
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/walkingflame.hpp"
18
19 #include "audio/sound_manager.hpp"
20 #include "object/player.hpp"
21 #include "object/sprite_particle.hpp"
22 #include "sprite/sprite.hpp"
23 #include "supertux/object_factory.hpp"
24 #include "supertux/sector.hpp"
25
26 static const float WALKSPEED = 80;
27 static const float MAXDROPHEIGHT = 20;
28
29 WalkingFlame::WalkingFlame(const Reader& reader) :
30   WalkingBadguy(reader, "images/creatures/walkingflame/walkingflame.sprite", "left", "right"),
31   lightsprite(sprite_manager->create("images/objects/lightmap_light/lightmap_light-medium.sprite"))
32 {
33   walk_speed = WALKSPEED;
34   max_drop_height = MAXDROPHEIGHT;
35   lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE));
36   lightsprite->set_color(Color(1.0f, 0.9f, 0.8f));
37 }
38
39 void
40 WalkingFlame::draw(DrawingContext& context)
41 {
42   //Draw the Sprite.
43   sprite->draw(context, get_pos(), LAYER_OBJECTS);
44   //Draw the light
45   context.push_target();
46   context.set_target(DrawingContext::LIGHTMAP);
47   lightsprite->draw(context, get_bbox().get_middle(), 0);
48   context.pop_target();
49 }
50
51 void
52 WalkingFlame::freeze()
53 {
54   // attempting to freeze a flame causes it to go out
55   kill_fall();
56 }
57
58 bool
59 WalkingFlame::is_freezable() const
60 {
61   return true;
62 }
63
64 bool
65 WalkingFlame::is_flammable() const
66 {
67   return false;
68 }
69
70 void
71 WalkingFlame::kill_fall()
72 {
73   //TODO: get unique sound for ice-fire encounters
74   sound_manager->play("sounds/fall.wav", get_pos());
75   // throw a puff of smoke
76   Vector ppos = bbox.get_middle();
77   Vector pspeed = Vector(0, -150);
78   Vector paccel = Vector(0,0);
79   Sector::current()->add_object(new SpriteParticle("images/objects/particles/smoke.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_BACKGROUNDTILES+2));
80   // extinguish the flame
81   sprite->set_action(dir == LEFT ? "extinguish-left" : "extinguish-right");
82   physic.set_velocity_y(0);
83   physic.set_acceleration_y(0);
84   physic.enable_gravity(false);
85   set_state(STATE_SQUISHED); // used to nullify any threat and remove
86
87   // start dead-script
88   run_dead_script();
89 }
90
91 /* The following handles a sleeping version */
92
93 SWalkingFlame::SWalkingFlame(const Reader& reader) :
94   WalkingBadguy(reader, "images/creatures/walkingflame/walkingflame.sprite", "left", "right"), state(STATE_SLEEPING),
95   lightsprite(sprite_manager->create("images/objects/lightmap_light/lightmap_light-medium.sprite"))
96 {
97   walk_speed = WALKSPEED;
98   max_drop_height = MAXDROPHEIGHT;
99   lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE));
100   lightsprite->set_color(Color(1.0f, 0.9f, 0.8f));
101 }
102
103 void
104 SWalkingFlame::initialize()
105 {
106   state = STATE_SLEEPING;
107   physic.set_velocity_x(0);
108   sprite->set_action(dir == LEFT ? "sleeping-left" : "sleeping-right");
109 }
110
111 void
112 SWalkingFlame::collision_solid(const CollisionHit& hit)
113 {
114   if(state != STATE_WALKING) {
115     BadGuy::collision_solid(hit);
116     return;
117   }
118   WalkingBadguy::collision_solid(hit);
119 }
120
121 HitResponse
122 SWalkingFlame::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
123 {
124   if(state != STATE_WALKING) {
125     return BadGuy::collision_badguy(badguy, hit);
126   }
127   return WalkingBadguy::collision_badguy(badguy, hit);
128 }
129
130 void
131 SWalkingFlame::active_update(float elapsed_time) {
132
133   if(state == STATE_WALKING) {
134     WalkingBadguy::active_update(elapsed_time);
135     return;
136   }
137
138   if(state == STATE_SLEEPING) {
139
140     Player* player = this->get_nearest_player();
141     if (player) {
142       Rectf mb = this->get_bbox();
143       Rectf pb = player->get_bbox();
144
145       bool inReach_left = (pb.p2.x >= mb.p2.x-((dir == LEFT) ? 256 : 0));
146       bool inReach_right = (pb.p1.x <= mb.p1.x+((dir == RIGHT) ? 256 : 0));
147       bool inReach_top = (pb.p2.y >= mb.p1.y);
148       bool inReach_bottom = (pb.p1.y <= mb.p2.y);
149
150       if (inReach_left && inReach_right && inReach_top && inReach_bottom) {
151         // wake up
152         sprite->set_action(dir == LEFT ? "waking-left" : "waking-right", 1);
153         state = STATE_WAKING;
154       }
155     }
156
157     BadGuy::active_update(elapsed_time);
158   }
159
160   if(state == STATE_WAKING) {
161     if(sprite->animation_done()) {
162       // start walking
163       state = STATE_WALKING;
164       WalkingBadguy::initialize();
165     }
166
167     BadGuy::active_update(elapsed_time);
168   }
169 }
170
171 void
172 SWalkingFlame::draw(DrawingContext& context)
173 {
174   //Draw the Sprite.
175   sprite->draw(context, get_pos(), LAYER_OBJECTS);
176   //Draw the light
177   context.push_target();
178   context.set_target(DrawingContext::LIGHTMAP);
179   lightsprite->draw(context, get_bbox().get_middle(), 0);
180   context.pop_target();
181 }
182
183 void
184 SWalkingFlame::freeze()
185 {
186   // attempting to freeze a flame causes it to go out
187   kill_fall();
188 }
189
190 bool
191 SWalkingFlame::is_freezable() const
192 {
193   return true;
194 }
195
196 bool
197 SWalkingFlame::is_flammable() const
198 {
199   return false;
200 }
201
202 void
203 SWalkingFlame::kill_fall()
204 {
205   //TODO: get unique sound for ice-fire encounters
206   sound_manager->play("sounds/fall.wav", get_pos());
207   // throw a puff of smoke
208   Vector ppos = bbox.get_middle();
209   Vector pspeed = Vector(0, -150);
210   Vector paccel = Vector(0,0);
211   Sector::current()->add_object(new SpriteParticle("images/objects/particles/smoke.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_BACKGROUNDTILES+2));
212   // extinguish the flame
213   sprite->set_action(dir == LEFT ? "extinguish-left" : "extinguish-right");
214   physic.set_velocity_y(0);
215   physic.set_acceleration_y(0);
216   physic.enable_gravity(false);
217   set_state(STATE_SQUISHED); // used to nullify any threat and remove
218
219   // start dead-script
220   run_dead_script();
221 }
222
223 /* EOF */