X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fobject%2Fblock.cpp;h=6d0c5f4a650dad77e045289e45f4e11a873ce57f;hb=2bfc38ef3208dee885452cfa59a7c7df671eb24d;hp=0a8b037762bf089243871f590f031da94a04836c;hpb=d46c78c842ab4090a3f46e560c891234167f124b;p=supertux.git diff --git a/src/object/block.cpp b/src/object/block.cpp index 0a8b03776..6d0c5f4a6 100644 --- a/src/object/block.cpp +++ b/src/object/block.cpp @@ -1,30 +1,59 @@ +// $Id$ +// +// SuperTux +// Copyright (C) 2006 Matthias Braun +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + #include -#include "block.h" -#include "resources.h" -#include "player.h" -#include "sector.h" -#include "special/sprite.h" -#include "special/sprite_manager.h" -#include "video/drawing_context.h" -#include "gameobjs.h" -#include "specialriser.h" -#include "growup.h" -#include "flower.h" -#include "oneup.h" -#include "star.h" +#include "block.hpp" +#include "log.hpp" + +#include + +#include "resources.hpp" +#include "player.hpp" +#include "sector.hpp" +#include "sprite/sprite.hpp" +#include "sprite/sprite_manager.hpp" +#include "video/drawing_context.hpp" +#include "lisp/lisp.hpp" +#include "gameobjs.hpp" +#include "specialriser.hpp" +#include "growup.hpp" +#include "flower.hpp" +#include "oneup.hpp" +#include "star.hpp" +#include "player_status.hpp" +#include "badguy/badguy.hpp" +#include "coin.hpp" +#include "object_factory.hpp" +#include "lisp/list_iterator.hpp" +#include "object_factory.hpp" static const float BOUNCY_BRICK_MAX_OFFSET=8; static const float BOUNCY_BRICK_SPEED=90; static const float EPSILON = .0001; -Block::Block(const Vector& pos, Sprite* newsprite) +Block::Block(Sprite* newsprite) : sprite(newsprite), bouncing(false), bounce_dir(0), bounce_offset(0) { - bbox.set_pos(pos); - bbox.set_size(32, 32); + bbox.set_size(32, 32.1); + set_group(COLGROUP_STATIC); flags |= FLAG_SOLID; - original_y = pos.y; } Block::~Block() @@ -35,35 +64,39 @@ Block::~Block() HitResponse Block::collision(GameObject& other, const CollisionHit& hitdata) { - if(bouncing) - return FORCE_MOVE; - - // TODO kill badguys when bumping them... - Player* player = dynamic_cast (&other); - if(!player) - return ABORT_MOVE; + if(player) { + // collided from below? + if(hitdata.normal.x == 0 && hitdata.normal.y < 0) { + hit(*player); + } + } - // collided from below? - if(hitdata.normal.x == 0 && hitdata.normal.y < 0 - && player->get_movement().y < 0) { - hit(player); + if(bouncing) { + BadGuy* badguy = dynamic_cast (&other); + if(badguy) { + badguy->kill_fall(); + } + Coin* coin = dynamic_cast (&other); + if(coin) { + coin->collect(); + } } - return ABORT_MOVE; + return FORCE_MOVE; } void -Block::action(float elapsed_time) +Block::update(float elapsed_time) { if(!bouncing) return; float offset = original_y - get_pos().y; if(offset > BOUNCY_BRICK_MAX_OFFSET) { - bounce_dir *= -1; + bounce_dir = BOUNCY_BRICK_SPEED; movement = Vector(0, bounce_dir * elapsed_time); - } else if(offset < -EPSILON) { + } else if(offset < BOUNCY_BRICK_SPEED * elapsed_time && bounce_dir > 0) { movement = Vector(0, offset); bounce_dir = 0; bouncing = false; @@ -81,6 +114,7 @@ Block::draw(DrawingContext& context) void Block::start_bounce() { + original_y = bbox.p1.y; bouncing = true; bounce_dir = -BOUNCY_BRICK_SPEED; bounce_offset = 0; @@ -88,75 +122,157 @@ Block::start_bounce() //--------------------------------------------------------------------------- -BonusBlock::BonusBlock(const Vector& pos, int newdata) - : Block(pos, sprite_manager->create("bonusblock")), data(newdata) +BonusBlock::BonusBlock(const Vector& pos, int data) + : Block(sprite_manager->create("images/objects/bonus_block/bonusblock.sprite")), object(0) { - sprite->set_action("default"); + bbox.set_pos(pos); + sprite->set_action("normal"); + switch(data) { + case 1: contents = CONTENT_COIN; break; + case 2: contents = CONTENT_FIREGROW; break; + case 3: contents = CONTENT_STAR; break; + case 4: contents = CONTENT_1UP; break; + case 5: contents = CONTENT_ICEGROW; break; + default: + log_warning << "Invalid box contents" << std::endl; + contents = CONTENT_COIN; + break; + } +} + +BonusBlock::BonusBlock(const lisp::Lisp& lisp) + : Block(sprite_manager->create("images/objects/bonus_block/bonusblock.sprite")) +{ + Vector pos; + + contents = CONTENT_COIN; + lisp::ListIterator iter(&lisp); + while(iter.next()) { + const std::string& token = iter.item(); + if(token == "x") { + iter.value()->get(pos.x); + } else if(token == "y") { + iter.value()->get(pos.y); + } else if(token == "contents") { + std::string contentstring; + iter.value()->get(contentstring); + if(contentstring == "coin") { + contents = CONTENT_COIN; + } else if(contentstring == "firegrow") { + contents = CONTENT_FIREGROW; + } else if(contentstring == "icegrow") { + contents = CONTENT_ICEGROW; + } else if(contentstring == "star") { + contents = CONTENT_STAR; + } else if(contentstring == "1up") { + contents = CONTENT_1UP; + } else if(contentstring == "custom") { + contents = CONTENT_CUSTOM; + } else { + log_warning << "Invalid box contents '" << contentstring << "'" << std::endl; + } + } else { + if(contents == CONTENT_CUSTOM) { + GameObject* game_object = create_object(token, *(iter.lisp())); + object = dynamic_cast (game_object); + if(object == 0) + throw std::runtime_error( + "Only MovingObjects are allowed inside BonusBlocks"); + } else { + log_warning << "Invalid element '" << token << "' in bonusblock" << std::endl; + } + } + } + + if(contents == CONTENT_CUSTOM && object == 0) + throw std::runtime_error("Need to specify content object for custom block"); + + bbox.set_pos(pos); +} + +BonusBlock::~BonusBlock() +{ + delete object; +} + +void +BonusBlock::hit(Player& ) +{ + try_open(); } void -BonusBlock::hit(Player* player) +BonusBlock::try_open() { - if(sprite->get_action_name() == "empty") { - SoundManager::get()->play_sound(IDToSound(SND_BRICK)); + if(sprite->get_action() == "empty") { + sound_manager->play("sounds/brick.wav"); return; } Sector* sector = Sector::current(); - switch(data) { - case 1: // coin + Player& player = *(sector->player); + switch(contents) { + case CONTENT_COIN: Sector::current()->add_object(new BouncyCoin(get_pos())); - player->get_status().incCoins(); + player.get_status()->add_coins(1); break; - case 2: // grow/fireflower - if(player->size == SMALL) { - SpecialRiser* riser = new SpecialRiser( - new GrowUp(get_pos() + Vector(0, -32))); + case CONTENT_FIREGROW: + if(player.get_status()->bonus == NO_BONUS) { + SpecialRiser* riser = new SpecialRiser(get_pos(), new GrowUp()); sector->add_object(riser); } else { SpecialRiser* riser = new SpecialRiser( - new Flower(get_pos() + Vector(0, -32), Flower::FIREFLOWER)); + get_pos(), new Flower(Flower::FIREFLOWER)); sector->add_object(riser); } - SoundManager::get()->play_sound(IDToSound(SND_UPGRADE)); + sound_manager->play("sounds/upgrade.wav"); break; - case 5: // grow/iceflower - if(player->size == SMALL) { - SpecialRiser* riser = new SpecialRiser( - new GrowUp(get_pos() + Vector(0, -32))); + case CONTENT_ICEGROW: + if(player.get_status()->bonus == NO_BONUS) { + SpecialRiser* riser = new SpecialRiser(get_pos(), new GrowUp()); sector->add_object(riser); } else { - SpecialRiser* riser = new SpecialRiser( - new Flower(get_pos() + Vector(0, -32), Flower::ICEFLOWER)); + SpecialRiser* riser = new SpecialRiser( + get_pos(), new Flower(Flower::ICEFLOWER)); sector->add_object(riser); } - SoundManager::get()->play_sound(IDToSound(SND_UPGRADE)); + sound_manager->play("sounds/upgrade.wav"); break; - case 3: // star - sector->add_object(new Star(get_pos())); + case CONTENT_STAR: + sector->add_object(new Star(get_pos() + Vector(0, -32))); break; - case 4: // 1up + case CONTENT_1UP: sector->add_object(new OneUp(get_pos())); break; - default: - assert(false); + case CONTENT_CUSTOM: + SpecialRiser* riser = new SpecialRiser(get_pos(), object); + object = 0; + sector->add_object(riser); + sound_manager->play("sounds/upgrade.wav"); + break; + + //default: + //assert(false); } start_bounce(); sprite->set_action("empty"); } +IMPLEMENT_FACTORY(BonusBlock, "bonusblock"); + //--------------------------------------------------------------------------- Brick::Brick(const Vector& pos, int data) - : Block(pos, sprite_manager->create("brick")), - breakable(false), coin_counter(0) + : Block(sprite_manager->create("images/objects/bonus_block/brick.sprite")), breakable(false), + coin_counter(0) { + bbox.set_pos(pos); if(data == 1) coin_counter = 5; else @@ -164,22 +280,32 @@ Brick::Brick(const Vector& pos, int data) } void -Brick::hit(Player* player) +Brick::hit(Player& ) +{ + if(sprite->get_action() == "empty") + return; + + try_break(true); +} + +void +Brick::try_break(bool playerhit) { - if(sprite->get_action_name() == "empty") + if(sprite->get_action() == "empty") return; - SoundManager::get()->play_sound(IDToSound(SND_BRICK)); + sound_manager->play("sounds/brick.wav"); Sector* sector = Sector::current(); + Player& player = *(sector->player); if(coin_counter > 0) { sector->add_object(new BouncyCoin(get_pos())); coin_counter--; - player->get_status().incCoins(); + player.get_status()->add_coins(1); if(coin_counter == 0) sprite->set_action("empty"); start_bounce(); } else if(breakable) { - if(player->size == SMALL) { + if(playerhit && !player.is_big()) { start_bounce(); return; } @@ -199,3 +325,5 @@ Brick::hit(Player* player) } } +//IMPLEMENT_FACTORY(Brick, "brick"); +