X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fobject%2Fblock.cpp;h=1e115d9046781bae2dbc377727038b9ac5d0da41;hb=9eab9403c2b9ff629c07380e8d5f1032d21bd3f7;hp=4cf7920e32e8e8dff03555c2748acff077a162d2;hpb=72325436a6b4c5eef61f4a14ef287a9520717baa;p=supertux.git diff --git a/src/object/block.cpp b/src/object/block.cpp index 4cf7920e3..1e115d904 100644 --- a/src/object/block.cpp +++ b/src/object/block.cpp @@ -1,12 +1,10 @@ -// $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 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 3 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 @@ -14,54 +12,41 @@ // 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.hpp" -#include "log.hpp" +// along with this program. If not, see . -#include +#include "object/block.hpp" -#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 "portable.hpp" -#include "specialriser.hpp" -#include "growup.hpp" -#include "flower.hpp" -#include "oneup.hpp" -#include "star.hpp" -#include "player_status.hpp" +#include "audio/sound_manager.hpp" #include "badguy/badguy.hpp" -#include "coin.hpp" -#include "object_factory.hpp" -#include "lisp/list_iterator.hpp" -#include "object_factory.hpp" -#include "level.hpp" +#include "object/broken_brick.hpp" +#include "object/coin.hpp" +#include "object/flower.hpp" +#include "object/growup.hpp" +#include "object/player.hpp" +#include "object/portable.hpp" +#include "supertux/constants.hpp" +#include "supertux/sector.hpp" static const float BOUNCY_BRICK_MAX_OFFSET = 8; static const float BOUNCY_BRICK_SPEED = 90; -static const float EPSILON = .0001f; +static const float BUMP_ROTATION_ANGLE = 10; -Block::Block(Sprite* newsprite) - : sprite(newsprite), bouncing(false), breaking(false), bounce_dir(0), bounce_offset(0) +Block::Block(SpritePtr newsprite) : + sprite(newsprite), + bouncing(false), + breaking(false), + bounce_dir(0), + bounce_offset(0), + original_y(-1) { bbox.set_size(32, 32.1f); set_group(COLGROUP_STATIC); - sound_manager->preload("sounds/upgrade.wav"); - sound_manager->preload("sounds/brick.wav"); + SoundManager::current()->preload("sounds/upgrade.wav"); + SoundManager::current()->preload("sounds/brick.wav"); } Block::~Block() { - delete sprite; } HitResponse @@ -69,17 +54,20 @@ Block::collision(GameObject& other, const CollisionHit& ) { Player* player = dynamic_cast (&other); if(player) { - if(player->get_bbox().get_top() > get_bbox().get_bottom() - 7.0) { + if(player->get_bbox().get_top() > get_bbox().get_bottom() - SHIFT_DELTA) { hit(*player); } } // only interact with other objects if... // 1) we are bouncing - // and // 2) the object is not portable (either never or not currently) + // 3) the object is being hit from below (baguys don't get killed for activating boxes) Portable* portable = dynamic_cast (&other); - if(bouncing && (portable == 0 || (!portable->is_portable()))) { + MovingObject* moving_object = dynamic_cast (&other); + bool is_portable = ((portable != 0) && portable->is_portable()); + bool hit_mo_from_below = ((moving_object == 0) || (moving_object->get_bbox().get_bottom() < (get_bbox().get_top() + SHIFT_DELTA))); + if(bouncing && !is_portable && hit_mo_from_below) { // Badguys get killed BadGuy* badguy = dynamic_cast (&other); @@ -93,9 +81,15 @@ Block::collision(GameObject& other, const CollisionHit& ) coin->collect(); } + //Eggs get jumped + GrowUp* growup = dynamic_cast (&other); + if(growup) { + growup->do_jump(); + } + } - return SOLID; + return FORCE_MOVE; } void @@ -115,6 +109,7 @@ Block::update(float elapsed_time) movement = Vector(0, offset); bounce_dir = 0; bouncing = false; + sprite->set_angle(0); } else { movement = Vector(0, bounce_dir * elapsed_time); } @@ -127,186 +122,28 @@ Block::draw(DrawingContext& context) } void -Block::start_bounce() +Block::start_bounce(GameObject* hitter) { - original_y = bbox.p1.y; + if(original_y == -1){ + original_y = bbox.p1.y; + } bouncing = true; bounce_dir = -BOUNCY_BRICK_SPEED; bounce_offset = 0; -} - -void -Block::start_break() -{ - start_bounce(); - breaking = true; -} - -//--------------------------------------------------------------------------- - -BonusBlock::BonusBlock(const Vector& pos, int data) - : Block(sprite_manager->create("images/objects/bonus_block/bonusblock.sprite")), object(0) -{ - 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; - } - } + MovingObject* hitter_mo = dynamic_cast(hitter); + if (hitter_mo) { + float center_of_hitter = hitter_mo->get_bbox().get_middle().x; + float offset = (get_bbox().get_middle().x - center_of_hitter)*2 / get_bbox().get_width(); + sprite->set_angle(BUMP_ROTATION_ANGLE*offset); } - - 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(); -} - -HitResponse -BonusBlock::collision(GameObject& other, const CollisionHit& hit){ - BadGuy* badguy = dynamic_cast (&other); - if(badguy) { - // hit contains no information for collisions with blocks. - // Badguy's bottom has to be below the top of the bonusblock - // +7 is required to slide over one tile gaps. - if( badguy->can_break() && ( badguy->get_bbox().get_bottom() > get_bbox().get_top() + 7.0) ){ - try_open(); - } - } - Portable* portable = dynamic_cast (&other); - if(portable) { - MovingObject* moving = dynamic_cast (&other); - if(moving->get_bbox().get_top() > get_bbox().get_bottom() - 7.0) { - try_open(); - } - } - return Block::collision(other, hit); } void -BonusBlock::try_open() +Block::start_break(GameObject* hitter) { - if(sprite->get_action() == "empty") { - sound_manager->play("sounds/brick.wav"); - return; - } - - Sector* sector = Sector::current(); - assert(sector); - assert(sector->player); - Player& player = *(sector->player); - Direction direction = (player.get_bbox().get_middle().x > get_bbox().get_middle().x) ? LEFT : RIGHT; - - switch(contents) { - case CONTENT_COIN: - Sector::current()->add_object(new BouncyCoin(get_pos())); - player.get_status()->add_coins(1); - Sector::current()->get_level()->stats.coins++; - break; - - case CONTENT_FIREGROW: - if(player.get_status()->bonus == NO_BONUS) { - SpecialRiser* riser = new SpecialRiser(get_pos(), new GrowUp(direction)); - sector->add_object(riser); - } else { - SpecialRiser* riser = new SpecialRiser( - get_pos(), new Flower(FIRE_BONUS)); - sector->add_object(riser); - } - sound_manager->play("sounds/upgrade.wav"); - break; - - case CONTENT_ICEGROW: - if(player.get_status()->bonus == NO_BONUS) { - SpecialRiser* riser = new SpecialRiser(get_pos(), new GrowUp(direction)); - sector->add_object(riser); - } else { - SpecialRiser* riser = new SpecialRiser( - get_pos(), new Flower(ICE_BONUS)); - sector->add_object(riser); - } - sound_manager->play("sounds/upgrade.wav"); - break; - - case CONTENT_STAR: - sector->add_object(new Star(get_pos() + Vector(0, -32), direction)); - break; - - case CONTENT_1UP: - sector->add_object(new OneUp(get_pos(), direction)); - break; - - case CONTENT_CUSTOM: - SpecialRiser* riser = new SpecialRiser(get_pos(), object); - object = 0; - sector->add_object(riser); - sound_manager->play("sounds/upgrade.wav"); - break; - } - - start_bounce(); - sprite->set_action("empty"); + start_bounce(hitter); + breaking = true; } void @@ -314,98 +151,17 @@ Block::break_me() { Sector* sector = Sector::current(); sector->add_object( - new BrokenBrick(new Sprite(*sprite), get_pos(), Vector(-100, -400))); + std::make_shared(sprite->clone(), get_pos(), Vector(-100, -400))); sector->add_object( - new BrokenBrick(new Sprite(*sprite), get_pos() + Vector(0, 16), - Vector(-150, -300))); + std::make_shared(sprite->clone(), get_pos() + Vector(0, 16), + Vector(-150, -300))); sector->add_object( - new BrokenBrick(new Sprite(*sprite), get_pos() + Vector(16, 0), - Vector(100, -400))); + std::make_shared(sprite->clone(), get_pos() + Vector(16, 0), + Vector(100, -400))); sector->add_object( - new BrokenBrick(new Sprite(*sprite), get_pos() + Vector(16, 16), - Vector(150, -300))); + std::make_shared(sprite->clone(), get_pos() + Vector(16, 16), + Vector(150, -300))); remove_me(); } -IMPLEMENT_FACTORY(BonusBlock, "bonusblock"); - -//--------------------------------------------------------------------------- - -Brick::Brick(const Vector& pos, int data) - : 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 - breakable = true; -} - -void -Brick::hit(Player& player) -{ - if(sprite->get_action() == "empty") - return; - - try_break(&player); -} - -HitResponse -Brick::collision(GameObject& other, const CollisionHit& hit){ - - Player* player = dynamic_cast (&other); - if (player) { - if (player->butt_jump) try_break(); - } - - BadGuy* badguy = dynamic_cast (&other); - if(badguy) { - // hit contains no information for collisions with blocks. - // Badguy's bottom has to be below the top of the brick - // +7 is required to slide over one tile gaps. - if( badguy->can_break() && ( badguy->get_bbox().get_bottom() > get_bbox().get_top() + 7.0 ) ){ - try_break(); - } - } - Portable* portable = dynamic_cast (&other); - if(portable) { - MovingObject* moving = dynamic_cast (&other); - if(moving->get_bbox().get_top() > get_bbox().get_bottom() - 7.0) { - try_break(); - } - } - return Block::collision(other, hit); -} - -void -Brick::try_break(Player* player) -{ - if(sprite->get_action() == "empty") - return; - - sound_manager->play("sounds/brick.wav"); - Sector* sector = Sector::current(); - Player& player_one = *(sector->player); - if(coin_counter > 0) { - sector->add_object(new BouncyCoin(get_pos())); - coin_counter--; - player_one.get_status()->add_coins(1); - if(coin_counter == 0) - sprite->set_action("empty"); - start_bounce(); - } else if(breakable) { - if(player){ - if(player->is_big()){ - start_break(); - return; - } else { - start_bounce(); - return; - } - } - break_me(); - } -} - -//IMPLEMENT_FACTORY(Brick, "brick"); +/* EOF */