Removed trailing whitespace from all *.?pp files
[supertux.git] / src / object / weak_block.cpp
1 //  SuperTux - Weak Block
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //  Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
4 //
5 //  This program is free software: you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation, either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 #include "object/weak_block.hpp"
19
20 #include "audio/sound_manager.hpp"
21 #include "math/random_generator.hpp"
22 #include "object/bullet.hpp"
23 #include "object/explosion.hpp"
24 #include "supertux/object_factory.hpp"
25 #include "supertux/sector.hpp"
26 #include "sprite/sprite.hpp"
27 #include "sprite/sprite_manager.hpp"
28 #include "util/reader.hpp"
29
30 #include <math.h>
31
32 WeakBlock::WeakBlock(const Reader& lisp)
33 : MovingSprite(lisp, "images/objects/weak_block/strawbox.sprite", LAYER_TILES, COLGROUP_STATIC), state(STATE_NORMAL),
34   linked(true),
35   light(0.0f,0.0f,0.0f),
36   lightsprite(sprite_manager->create("images/objects/lightmap_light/lightmap_light-small.sprite"))
37 {
38   sprite->set_action("normal");
39   //Check if this weakblock destroys adjacent weakblocks
40   if(lisp.get("linked", linked)){
41     if(! linked){
42       sprite_name = "images/objects/weak_block/meltbox.sprite";
43       sprite = sprite_manager->create(sprite_name);
44       sprite->set_action("normal");
45     }
46   }
47   if(sprite_name == "images/objects/weak_block/strawbox.sprite") {
48     lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE));
49     lightsprite->set_color(Color(0.3f, 0.2f, 0.1f));
50   } else if(sprite_name == "images/objects/weak_block/meltbox.sprite")
51     sound_manager->preload("sounds/sizzle.ogg");
52 }
53
54 HitResponse
55 WeakBlock::collision_bullet(Bullet& bullet, const CollisionHit& hit)
56 {
57   switch (state) {
58                         
59     case STATE_NORMAL:
60       //Ensure only fire destroys weakblock
61       if(bullet.get_type() == FIRE_BONUS) {
62         startBurning();
63         bullet.remove_me();
64       }
65       //Other bullets ricochet
66       else {
67         bullet.ricochet(*this, hit);
68       }
69     break;
70                         
71     case STATE_BURNING:
72     case STATE_DISINTEGRATING:
73       break;
74                         
75     default:
76       log_debug << "unhandled state" << std::endl;
77       break;
78         }
79         
80         return FORCE_MOVE;
81 }
82
83 HitResponse
84 WeakBlock::collision(GameObject& other, const CollisionHit& hit)
85 {
86   switch (state) {
87                                 
88       case STATE_NORMAL:
89         if (Bullet* bullet = dynamic_cast<Bullet*> (&other)) {
90           return collision_bullet(*bullet, hit);
91         }
92         //Explosions destroy weakblocks as well
93         if (dynamic_cast<Explosion*> (&other)) {
94           startBurning();
95         }
96         break;
97                                 
98       case STATE_BURNING:
99       case STATE_DISINTEGRATING:
100         break;
101                                 
102       default:
103         log_debug << "unhandled state" << std::endl;
104         break;
105   }
106         
107   return FORCE_MOVE;
108 }
109
110 void
111 WeakBlock::update(float )
112 {
113   switch (state) {
114                                 
115       case STATE_NORMAL:
116         break;
117                                 
118       case STATE_BURNING:
119         // cause burn light to flicker randomly
120         if (linked) {
121           if(gameRandom.rand(10) >= 7) {
122             lightsprite->set_color(Color(0.2f + gameRandom.rand(20)/100.0f, 0.1f + gameRandom.rand(20)/100.0f, 0.1f));
123           } else
124             lightsprite->set_color(Color(0.3f, 0.2f, 0.1f));
125         }
126
127         if (sprite->animation_done()) {
128           state = STATE_DISINTEGRATING;
129           sprite->set_action("disintegrating", 1);
130           spreadHit();
131           set_group(COLGROUP_DISABLED);
132           lightsprite = sprite_manager->create("images/objects/lightmap_light/lightmap_light-tiny.sprite");
133           lightsprite->set_blend(Blend(GL_SRC_ALPHA, GL_ONE));
134           lightsprite->set_color(Color(0.3f, 0.2f, 0.1f));
135         }
136         break;
137                                 
138       case STATE_DISINTEGRATING:
139         if (sprite->animation_done()) {
140           remove_me();
141           return;
142         }
143         break;
144                                 
145   }
146 }
147
148 void
149 WeakBlock::draw(DrawingContext& context)
150 {
151   //Draw the Sprite just in front of other objects
152   sprite->draw(context, get_pos(), LAYER_OBJECTS + 10);
153   //Draw the light if burning and dark
154   if(linked && (state != STATE_NORMAL)){
155     context.get_light( get_bbox().get_middle(), &light );
156     if (light.red + light.green + light.blue < 3.0){
157       context.push_target();
158       context.set_target(DrawingContext::LIGHTMAP);
159       sprite->draw(context, get_pos(), LAYER_OBJECTS + 10);
160       lightsprite->draw(context, get_bbox().get_middle(), 0);
161       context.pop_target();
162     }
163   }
164 }
165
166 void
167 WeakBlock::startBurning()
168 {
169   if (state != STATE_NORMAL) return;
170   state = STATE_BURNING;
171   sprite->set_action("burning", 1);
172   if(sprite_name == "images/objects/weak_block/meltbox.sprite")
173     sound_manager->play("sounds/sizzle.ogg");
174 }
175
176 void
177 WeakBlock::spreadHit()
178 {
179   //Destroy adjacent weakblocks if applicable
180   if(linked) {
181     Sector* sector = Sector::current();
182     if (!sector) {
183       log_debug << "no current sector" << std::endl;
184       return;
185     }
186     for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); ++i) {
187       WeakBlock* wb = dynamic_cast<WeakBlock*>(*i);
188       if (!wb) continue;
189       if (wb == this) continue;
190       if (wb->state != STATE_NORMAL) continue;
191       float dx = fabsf(wb->get_pos().x - this->get_pos().x);
192       float dy = fabsf(wb->get_pos().y - this->get_pos().y);
193       if ((dx <= 32.5) && (dy <= 32.5)) wb->startBurning();
194     }
195   }
196 }
197
198
199 /* EOF */