b627c4934b2c1c173b06ee604b450816081e1c4e
[supertux.git] / src / badguy / livefire.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/livefire.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 LiveFire::LiveFire(const Reader& reader) :
30   WalkingBadguy(reader, "images/creatures/livefire/livefire.sprite", "left", "right"),
31   lightsprite(sprite_manager->create("images/objects/lightmap_light/lightmap_light-medium.sprite")),
32   state(STATE_WALKING)  
33 {
34   walk_speed = WALKSPEED;
35   max_drop_height = MAXDROPHEIGHT;
36   lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE));
37   lightsprite->set_color(Color(1.0f, 0.9f, 0.8f));
38 }
39
40 void
41 LiveFire::collision_solid(const CollisionHit& hit)
42 {
43   if(state != STATE_WALKING) {
44     BadGuy::collision_solid(hit);
45     return;
46   }
47   WalkingBadguy::collision_solid(hit);
48 }
49
50 HitResponse
51 LiveFire::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
52 {
53   if(state != STATE_WALKING) {
54     return BadGuy::collision_badguy(badguy, hit);
55   }
56   return WalkingBadguy::collision_badguy(badguy, hit);
57 }
58
59 void
60 LiveFire::active_update(float elapsed_time) {
61
62   // Remove when extinguish animation is done
63   if((sprite->get_action() == "extinguish-left" || sprite->get_action() == "extinguish-right" )
64     && sprite->animation_done()) remove_me();
65
66   if(state == STATE_WALKING) {
67     WalkingBadguy::active_update(elapsed_time);
68     return;
69   }
70
71   if(state == STATE_SLEEPING) {
72
73     Player* player = this->get_nearest_player();
74     if (player) {
75       Rectf mb = this->get_bbox();
76       Rectf pb = player->get_bbox();
77
78       bool inReach_left = (pb.p2.x >= mb.p2.x-((dir == LEFT) ? 256 : 0));
79       bool inReach_right = (pb.p1.x <= mb.p1.x+((dir == RIGHT) ? 256 : 0));
80       bool inReach_top = (pb.p2.y >= mb.p1.y);
81       bool inReach_bottom = (pb.p1.y <= mb.p2.y);
82
83       if (inReach_left && inReach_right && inReach_top && inReach_bottom) {
84         // wake up
85         sprite->set_action(dir == LEFT ? "waking-left" : "waking-right", 1);
86         state = STATE_WAKING;
87       }
88     }
89
90     BadGuy::active_update(elapsed_time);
91   }
92
93   if(state == STATE_WAKING) {
94     if(sprite->animation_done()) {
95       // start walking
96       state = STATE_WALKING;
97       WalkingBadguy::initialize();
98     }
99
100     BadGuy::active_update(elapsed_time);
101   }
102 }
103
104 void
105 LiveFire::draw(DrawingContext& context)
106 {
107   //Draw the Sprite.
108   sprite->draw(context, get_pos(), LAYER_OBJECTS);
109   //Draw the light
110   context.push_target();
111   context.set_target(DrawingContext::LIGHTMAP);
112   lightsprite->draw(context, get_bbox().get_middle(), 0);
113   context.pop_target();
114 }
115
116 void
117 LiveFire::freeze()
118 {
119   // attempting to freeze a flame causes it to go out
120   kill_fall();
121 }
122
123 bool
124 LiveFire::is_freezable() const
125 {
126   return true;
127 }
128
129 bool
130 LiveFire::is_flammable() const
131 {
132   return false;
133 }
134
135 void
136 LiveFire::kill_fall()
137 {
138   //TODO: get unique sound for ice-fire encounters
139   sound_manager->play("sounds/fall.wav", get_pos());
140   // throw a puff of smoke
141   Vector ppos = bbox.get_middle();
142   Vector pspeed = Vector(0, -150);
143   Vector paccel = Vector(0,0);
144   Sector::current()->add_object(new SpriteParticle("images/objects/particles/smoke.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_BACKGROUNDTILES+2));
145   // extinguish the flame
146   sprite->set_action(dir == LEFT ? "extinguish-left" : "extinguish-right", 1);
147   physic.set_velocity_y(0);
148   physic.set_acceleration_y(0);
149   physic.enable_gravity(false);
150   lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE));
151   lightsprite->set_color(Color(0.5f, 0.4f, 0.3f));
152   set_group(COLGROUP_DISABLED);
153
154   // start dead-script
155   run_dead_script();
156 }
157
158 /* The following defines a sleeping version */
159
160 LiveFireAsleep::LiveFireAsleep(const Reader& reader) :
161   LiveFire(reader)
162 {
163   state = STATE_SLEEPING;
164 }
165
166 void
167 LiveFireAsleep::initialize()
168 {
169   physic.set_velocity_x(0);
170   sprite->set_action(dir == LEFT ? "sleeping-left" : "sleeping-right");
171 }
172
173 /* The following defines a dormant version that never wakes */
174 LiveFireDormant::LiveFireDormant(const Reader& reader) :
175   LiveFire(reader)
176 {
177   walk_speed = 0;
178   state = STATE_DORMANT;
179 }
180
181 void
182 LiveFireDormant::initialize()
183 {
184   physic.set_velocity_x(0);
185   sprite->set_action(dir == LEFT ? "sleeping-left" : "sleeping-right");
186 }
187
188 /* EOF */