4 // Copyright (C) 2005 Matthias Braun <matze@braunis.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 #include "resources.h"
27 #include "sprite/sprite.h"
28 #include "sprite/sprite_manager.h"
29 #include "video/drawing_context.h"
30 #include "lisp/lisp.h"
32 #include "specialriser.h"
37 #include "player_status.h"
38 #include "badguy/badguy.h"
40 #include "object_factory.h"
42 static const float BOUNCY_BRICK_MAX_OFFSET=8;
43 static const float BOUNCY_BRICK_SPEED=90;
44 static const float EPSILON = .0001;
46 Block::Block(Sprite* newsprite)
47 : sprite(newsprite), bouncing(false), bounce_dir(0), bounce_offset(0)
49 bbox.set_size(32, 32.1);
59 Block::collision(GameObject& other, const CollisionHit& hitdata)
61 Player* player = dynamic_cast<Player*> (&other);
63 // collided from below?
64 if(hitdata.normal.x == 0 && hitdata.normal.y < 0) {
70 BadGuy* badguy = dynamic_cast<BadGuy*> (&other);
74 Coin* coin = dynamic_cast<Coin*> (&other);
84 Block::update(float elapsed_time)
89 float offset = original_y - get_pos().y;
90 if(offset > BOUNCY_BRICK_MAX_OFFSET) {
91 bounce_dir = BOUNCY_BRICK_SPEED;
92 movement = Vector(0, bounce_dir * elapsed_time);
93 } else if(offset < BOUNCY_BRICK_SPEED * elapsed_time && bounce_dir > 0) {
94 movement = Vector(0, offset);
98 movement = Vector(0, bounce_dir * elapsed_time);
103 Block::draw(DrawingContext& context)
105 sprite->draw(context, get_pos(), LAYER_OBJECTS+1);
109 Block::start_bounce()
111 original_y = bbox.p1.y;
113 bounce_dir = -BOUNCY_BRICK_SPEED;
117 //---------------------------------------------------------------------------
119 BonusBlock::BonusBlock(const Vector& pos, int data)
120 : Block(sprite_manager->create("bonusblock"))
123 sprite->set_action("normal");
125 case 1: contents = CONTENT_COIN; break;
126 case 2: contents = CONTENT_FIREGROW; break;
127 case 3: contents = CONTENT_STAR; break;
128 case 4: contents = CONTENT_1UP; break;
129 case 5: contents = CONTENT_ICEGROW; break;
131 std::cerr << "Invalid box contents!\n";
132 contents = CONTENT_COIN;
137 BonusBlock::BonusBlock(const lisp::Lisp& lisp)
138 : Block(sprite_manager->create("bonusblock"))
141 lisp.get("x", pos.x);
142 lisp.get("y", pos.y);
145 std::string contentstring;
146 contents = CONTENT_COIN;
147 if(lisp.get("contents", contentstring)) {
148 if(contentstring == "coin") {
149 contents = CONTENT_COIN;
150 } else if(contentstring == "firegrow") {
151 contents = CONTENT_FIREGROW;
152 } else if(contentstring == "icegrow") {
153 contents = CONTENT_ICEGROW;
154 } else if(contentstring == "star") {
155 contents = CONTENT_STAR;
156 } else if(contentstring == "1up") {
157 contents = CONTENT_1UP;
159 std::cerr << "Invalid box contents '" << contentstring << "'.\n";
165 BonusBlock::hit(Player& )
171 BonusBlock::try_open()
173 if(sprite->get_action_name() == "empty") {
174 sound_manager->play_sound("brick");
178 Sector* sector = Sector::current();
179 Player& player = *(sector->player);
182 Sector::current()->add_object(new BouncyCoin(get_pos()));
183 player.get_status()->incCoins();
186 case CONTENT_FIREGROW:
187 if(player.get_status()->bonus == NO_BONUS) {
188 SpecialRiser* riser = new SpecialRiser(
189 new GrowUp(get_pos() + Vector(0, -32)));
190 sector->add_object(riser);
192 SpecialRiser* riser = new SpecialRiser(
193 new Flower(get_pos() + Vector(0, -32), Flower::FIREFLOWER));
194 sector->add_object(riser);
196 sound_manager->play_sound("upgrade");
199 case CONTENT_ICEGROW:
200 if(player.get_status()->bonus == NO_BONUS) {
201 SpecialRiser* riser = new SpecialRiser(
202 new GrowUp(get_pos() + Vector(0, -32)));
203 sector->add_object(riser);
205 SpecialRiser* riser = new SpecialRiser(
206 new Flower(get_pos() + Vector(0, -32), Flower::ICEFLOWER));
207 sector->add_object(riser);
209 sound_manager->play_sound("upgrade");
213 sector->add_object(new Star(get_pos() + Vector(0, -32)));
217 sector->add_object(new OneUp(get_pos()));
225 sprite->set_action("empty");
228 IMPLEMENT_FACTORY(BonusBlock, "bonusblock")
230 //---------------------------------------------------------------------------
232 Brick::Brick(const Vector& pos, int data)
233 : Block(sprite_manager->create("brick")), breakable(false),
246 if(sprite->get_action_name() == "empty")
253 Brick::try_break(bool playerhit)
255 if(sprite->get_action_name() == "empty")
258 sound_manager->play_sound("brick");
259 Sector* sector = Sector::current();
260 Player& player = *(sector->player);
261 if(coin_counter > 0) {
262 sector->add_object(new BouncyCoin(get_pos()));
264 player.get_status()->incCoins();
265 if(coin_counter == 0)
266 sprite->set_action("empty");
268 } else if(breakable) {
269 if(playerhit && !player.is_big()) {
275 new BrokenBrick(new Sprite(*sprite), get_pos(), Vector(-100, -400)));
277 new BrokenBrick(new Sprite(*sprite), get_pos() + Vector(0, 16),
278 Vector(-150, -300)));
280 new BrokenBrick(new Sprite(*sprite), get_pos() + Vector(16, 0),
283 new BrokenBrick(new Sprite(*sprite), get_pos() + Vector(16, 16),
289 //IMPLEMENT_FACTORY(Brick, "brick")