X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fobject%2Fbonus_block.cpp;h=5f067766d8545da8a205c2f0c051589e044b8c14;hb=8eff855963e2699763d0d653dabc9b709f0d2ab0;hp=6c136c35555d3aee5e439206399da700b17fc67f;hpb=e54fb8e8717ab803f27736bf0c5f8cef20537c6e;p=supertux.git diff --git a/src/object/bonus_block.cpp b/src/object/bonus_block.cpp index 6c136c355..5f067766d 100644 --- a/src/object/bonus_block.cpp +++ b/src/object/bonus_block.cpp @@ -1,5 +1,5 @@ // SuperTux -// Copyright (C) 2009 Ingo Ruhnke +// Copyright (C) 2009 Ingo Ruhnke // // 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 @@ -19,13 +19,15 @@ #include "audio/sound_manager.hpp" #include "badguy/badguy.hpp" #include "lisp/list_iterator.hpp" -#include "object/broken_brick.hpp" #include "object/flower.hpp" #include "object/bouncy_coin.hpp" +#include "object/coin_explode.hpp" +#include "object/coin_rain.hpp" #include "object/growup.hpp" #include "object/oneup.hpp" #include "object/player.hpp" #include "object/portable.hpp" +#include "object/powerup.hpp" #include "object/specialriser.hpp" #include "object/star.hpp" #include "object/trampoline.hpp" @@ -38,10 +40,12 @@ #include BonusBlock::BonusBlock(const Vector& pos, int data) : - Block(sprite_manager->create("images/objects/bonus_block/bonusblock.sprite")), + Block(SpriteManager::current()->create("images/objects/bonus_block/bonusblock.sprite")), contents(), - object(0), + object(), hit_counter(1), + sprite_name(), + script(), lightsprite() { bbox.set_pos(pos); @@ -52,13 +56,26 @@ BonusBlock::BonusBlock(const Vector& pos, int data) : case 3: contents = CONTENT_STAR; break; case 4: contents = CONTENT_1UP; break; case 5: contents = CONTENT_ICEGROW; break; - case 6: contents = CONTENT_LIGHT; - sound_manager->preload("sounds/switch.ogg"); + case 6: contents = CONTENT_LIGHT; + SoundManager::current()->preload("sounds/switch.ogg"); lightsprite=Surface::create("/images/objects/lightmap_light/bonusblock_light.png"); break; - case 7: contents = CONTENT_TRAMPOLINE; break; - case 8: contents = CONTENT_PORTTRAMPOLINE; break; - case 9: contents = CONTENT_ROCK; break; + case 7: contents = CONTENT_TRAMPOLINE; + //object = new Trampoline(get_pos(), false); //needed if this is to be moved to custom + break; + case 8: contents = CONTENT_CUSTOM; + object = std::make_shared(get_pos(), true); + break; + case 9: contents = CONTENT_CUSTOM; + object = std::make_shared(get_pos(), "images/objects/rock/rock.sprite"); + break; + case 10: contents = CONTENT_RAIN; break; + case 11: contents = CONTENT_EXPLODE; break; + case 12: contents = CONTENT_CUSTOM; + object = std::make_shared(get_pos(), "images/powerups/potions/red-potion.sprite"); + break; + case 13: contents = CONTENT_AIRGROW; break; + case 14: contents = CONTENT_EARTHGROW; break; default: log_warning << "Invalid box contents" << std::endl; contents = CONTENT_COIN; @@ -67,10 +84,12 @@ BonusBlock::BonusBlock(const Vector& pos, int data) : } BonusBlock::BonusBlock(const Reader& lisp) : - Block(sprite_manager->create("images/objects/bonus_block/bonusblock.sprite")), + Block(SpriteManager::current()->create("images/objects/bonus_block/bonusblock.sprite")), contents(), object(0), hit_counter(1), + sprite_name(), + script(), lightsprite() { Vector pos; @@ -85,10 +104,10 @@ BonusBlock::BonusBlock(const Reader& lisp) : iter.value()->get(pos.y); } else if(token == "sprite") { iter.value()->get(sprite_name); - sprite = sprite_manager->create(sprite_name); + sprite = SpriteManager::current()->create(sprite_name); } else if(token == "count") { iter.value()->get(hit_counter); - } else if(token == "script") { // use when bonusblock is to contain ONLY a script + } else if(token == "script") { iter.value()->get(script); } else if(token == "contents") { std::string contentstring; @@ -99,30 +118,34 @@ BonusBlock::BonusBlock(const Reader& lisp) : contents = CONTENT_FIREGROW; } else if(contentstring == "icegrow") { contents = CONTENT_ICEGROW; + } else if(contentstring == "airgrow") { + contents = CONTENT_AIRGROW; + } else if(contentstring == "earthgrow") { + contents = CONTENT_EARTHGROW; } else if(contentstring == "star") { contents = CONTENT_STAR; } else if(contentstring == "1up") { contents = CONTENT_1UP; } else if(contentstring == "custom") { contents = CONTENT_CUSTOM; - } else if(contentstring == "script") { + } else if(contentstring == "script") { // use when bonusblock is to contain ONLY a script contents = CONTENT_SCRIPT; } else if(contentstring == "light") { contents = CONTENT_LIGHT; - sound_manager->preload("sounds/switch.ogg"); + SoundManager::current()->preload("sounds/switch.ogg"); } else if(contentstring == "trampoline") { contents = CONTENT_TRAMPOLINE; - } else if(contentstring == "porttrampoline") { - contents = CONTENT_PORTTRAMPOLINE; - } else if(contentstring == "rock") { - contents = CONTENT_ROCK; + } else if(contentstring == "rain") { + contents = CONTENT_RAIN; + } else if(contentstring == "explode") { + contents = CONTENT_EXPLODE; } else { log_warning << "Invalid box contents '" << contentstring << "'" << std::endl; } } else { if(contents == CONTENT_CUSTOM) { - GameObject* game_object = ObjectFactory::instance().create(token, *(iter.lisp())); - object = dynamic_cast (game_object); + GameObjectPtr game_object = ObjectFactory::instance().create(token, *(iter.lisp())); + object = std::dynamic_pointer_cast(game_object); if(object == 0) throw std::runtime_error( "Only MovingObjects are allowed inside BonusBlocks"); @@ -142,7 +165,6 @@ BonusBlock::BonusBlock(const Reader& lisp) : BonusBlock::~BonusBlock() { - delete object; } void @@ -152,12 +174,12 @@ BonusBlock::hit(Player & player) } HitResponse -BonusBlock::collision(GameObject& other, const CollisionHit& hit){ +BonusBlock::collision(GameObject& other, const CollisionHit& hit_){ Player* player = dynamic_cast (&other); if (player) { if (player->does_buttjump) - try_open(player); + try_drop(player); } BadGuy* badguy = dynamic_cast (&other); @@ -176,14 +198,14 @@ BonusBlock::collision(GameObject& other, const CollisionHit& hit){ try_open(player); } } - return Block::collision(other, hit); + return Block::collision(other, hit_); } void BonusBlock::try_open(Player *player) { if(sprite->get_action() == "empty") { - sound_manager->play("sounds/brick.wav"); + SoundManager::current()->play("sounds/brick.wav"); return; } @@ -192,7 +214,7 @@ BonusBlock::try_open(Player *player) if (player == NULL) player = sector->player; - + if (player == NULL) return; @@ -201,7 +223,7 @@ BonusBlock::try_open(Player *player) switch(contents) { case CONTENT_COIN: { - Sector::current()->add_object(new BouncyCoin(get_pos(), true)); + Sector::current()->add_object(std::make_shared(get_pos(), true)); player->get_status()->add_coins(1); if (hit_counter != 0) Sector::current()->get_level()->stats.coins++; @@ -211,49 +233,79 @@ BonusBlock::try_open(Player *player) case CONTENT_FIREGROW: { if(player->get_status()->bonus == NO_BONUS) { - SpecialRiser* riser = new SpecialRiser(get_pos(), new GrowUp(direction)); + auto riser = std::make_shared(get_pos(), std::make_shared(direction)); sector->add_object(riser); } else { - SpecialRiser* riser = new SpecialRiser( - get_pos(), new Flower(FIRE_BONUS)); + auto riser = std::make_shared( + get_pos(), std::make_shared(FIRE_BONUS)); sector->add_object(riser); } - sound_manager->play("sounds/upgrade.wav"); + SoundManager::current()->play("sounds/upgrade.wav"); break; } case CONTENT_ICEGROW: { if(player->get_status()->bonus == NO_BONUS) { - SpecialRiser* riser = new SpecialRiser(get_pos(), new GrowUp(direction)); + auto riser = std::make_shared(get_pos(), std::make_shared(direction)); sector->add_object(riser); } else { - SpecialRiser* riser = new SpecialRiser( - get_pos(), new Flower(ICE_BONUS)); + auto riser = std::make_shared( + get_pos(), std::make_shared(ICE_BONUS)); sector->add_object(riser); } - sound_manager->play("sounds/upgrade.wav"); + SoundManager::current()->play("sounds/upgrade.wav"); + break; + } + + case CONTENT_AIRGROW: + { + if(player->get_status()->bonus == NO_BONUS) { + auto riser = std::make_shared(get_pos(), std::make_shared(direction)); + sector->add_object(riser); + } else { + auto riser = std::make_shared( + get_pos(), std::make_shared(AIR_BONUS)); + sector->add_object(riser); + } + SoundManager::current()->play("sounds/upgrade.wav"); + break; + } + + case CONTENT_EARTHGROW: + { + if(player->get_status()->bonus == NO_BONUS) { + auto riser = std::make_shared(get_pos(), std::make_shared(direction)); + sector->add_object(riser); + } else { + auto riser = std::make_shared( + get_pos(), std::make_shared(EARTH_BONUS)); + sector->add_object(riser); + } + SoundManager::current()->play("sounds/upgrade.wav"); break; } case CONTENT_STAR: { - sector->add_object(new Star(get_pos() + Vector(0, -32), direction)); + sector->add_object(std::make_shared(get_pos() + Vector(0, -32), direction)); + SoundManager::current()->play("sounds/upgrade.wav"); break; } case CONTENT_1UP: { - sector->add_object(new OneUp(get_pos(), direction)); + sector->add_object(std::make_shared(get_pos(), direction)); + SoundManager::current()->play("sounds/upgrade.wav"); break; } case CONTENT_CUSTOM: { - SpecialRiser* riser = new SpecialRiser(get_pos(), object); + auto riser = std::make_shared(get_pos(), object); object = 0; sector->add_object(riser); - sound_manager->play("sounds/upgrade.wav"); + SoundManager::current()->play("sounds/upgrade.wav"); break; } @@ -266,36 +318,35 @@ BonusBlock::try_open(Player *player) sprite->set_action("off"); else sprite->set_action("on"); - sound_manager->play("sounds/switch.ogg"); + SoundManager::current()->play("sounds/switch.ogg"); break; } case CONTENT_TRAMPOLINE: { - SpecialRiser* riser = new SpecialRiser(get_pos(), new Trampoline(get_pos(), false)); + auto riser = std::make_shared(get_pos(), std::make_shared(get_pos(), false)); sector->add_object(riser); - sound_manager->play("sounds/upgrade.wav"); + SoundManager::current()->play("sounds/upgrade.wav"); break; } - case CONTENT_PORTTRAMPOLINE: + case CONTENT_RAIN: { - SpecialRiser* riser = new SpecialRiser(get_pos(), new Trampoline(get_pos(), true)); - sector->add_object(riser); - sound_manager->play("sounds/upgrade.wav"); + hit_counter = 1; // multiple hits of coin rain is not allowed + Sector::current()->add_object(std::make_shared(get_pos(), true)); + SoundManager::current()->play("sounds/upgrade.wav"); break; } - case CONTENT_ROCK: + case CONTENT_EXPLODE: { - SpecialRiser* riser = new SpecialRiser(get_pos(), - new Rock(get_pos(), "images/objects/rock/rock.sprite")); - sector->add_object(riser); - sound_manager->play("sounds/upgrade.wav"); + hit_counter = 1; // multiple hits of coin explode is not allowed + Sector::current()->add_object(std::make_shared(get_pos() + Vector (0, -40))); + SoundManager::current()->play("sounds/upgrade.wav"); break; } } if(script != "") { // scripts always run if defined std::istringstream stream(script); - Sector::current()->run_script(stream, "powerup-script"); + Sector::current()->run_script(stream, "BonusBlockScript"); } start_bounce(player); @@ -308,30 +359,152 @@ BonusBlock::try_open(Player *player) } void -Block::break_me() +BonusBlock::try_drop(Player *player) { + if(sprite->get_action() == "empty") { + SoundManager::current()->play("sounds/brick.wav"); + return; + } + Sector* sector = Sector::current(); - sector->add_object( - new BrokenBrick(sprite->clone(), get_pos(), Vector(-100, -400))); - sector->add_object( - new BrokenBrick(sprite->clone(), get_pos() + Vector(0, 16), - Vector(-150, -300))); - sector->add_object( - new BrokenBrick(sprite->clone(), get_pos() + Vector(16, 0), - Vector(100, -400))); - sector->add_object( - new BrokenBrick(sprite->clone(), get_pos() + Vector(16, 16), - Vector(150, -300))); - remove_me(); + assert(sector); + + // First what's below the bonus block, if solid send it up anyway (excepting doll) + Rectf dest_; + dest_.p1.x = bbox.get_left() + 1; + dest_.p1.y = bbox.get_bottom() + 1; + dest_.p2.x = bbox.get_right() - 1; + dest_.p2.y = dest_.p1.y + 30; + if (!Sector::current()->is_free_of_statics(dest_, this, true) && !(contents == CONTENT_1UP)) { + try_open(player); + return; + } + + if (player == NULL) + player = sector->player; + + if (player == NULL) + return; + + Direction direction = (player->get_bbox().get_middle().x > get_bbox().get_middle().x) ? LEFT : RIGHT; + + bool countdown = false; + + switch(contents) { + case CONTENT_COIN: + { + try_open(player); + break; + } + + case CONTENT_FIREGROW: + { + sector->add_object(std::make_shared(get_pos() + Vector(0, 32), "images/powerups/fireflower/fireflower.sprite")); + SoundManager::current()->play("sounds/upgrade.wav"); + countdown = true; + break; + } + + case CONTENT_ICEGROW: + { + sector->add_object(std::make_shared(get_pos() + Vector(0, 32), "images/powerups/iceflower/iceflower.sprite")); + SoundManager::current()->play("sounds/upgrade.wav"); + countdown = true; + break; + } + + case CONTENT_AIRGROW: + { + sector->add_object(std::make_shared(get_pos() + Vector(0, 32), "images/powerups/airflower/airflower.sprite")); + SoundManager::current()->play("sounds/upgrade.wav"); + countdown = true; + break; + } + + case CONTENT_EARTHGROW: + { + sector->add_object(std::make_shared(get_pos() + Vector(0, 32), "images/powerups/earthflower/earthflower.sprite")); + SoundManager::current()->play("sounds/upgrade.wav"); + countdown = true; + break; + } + + case CONTENT_STAR: + { + sector->add_object(std::make_shared(get_pos() + Vector(0, 32), direction)); + SoundManager::current()->play("sounds/upgrade.wav"); + countdown = true; + break; + } + + case CONTENT_1UP: + { + sector->add_object(std::make_shared(get_pos(), DOWN)); + SoundManager::current()->play("sounds/upgrade.wav"); + countdown = true; + break; + } + + case CONTENT_CUSTOM: + { + //NOTE: non-portable trampolines could be moved to CONTENT_CUSTOM, but they should not drop + object->set_pos(get_pos() + Vector(0, 32)); + sector->add_object(object); + object = 0; + SoundManager::current()->play("sounds/upgrade.wav"); + countdown = true; + break; + } + + case CONTENT_SCRIPT: + { break; } // because scripts always run, this prevents default contents from being assumed + + case CONTENT_LIGHT: + { + try_open(player); + break; + } + case CONTENT_TRAMPOLINE: + { + try_open(player); + break; + } + case CONTENT_RAIN: + { + try_open(player); + break; + } + case CONTENT_EXPLODE: + { + hit_counter = 1; // multiple hits of coin explode is not allowed + Sector::current()->add_object(std::make_shared(get_pos() + Vector (0, 40))); + SoundManager::current()->play("sounds/upgrade.wav"); + countdown = true; + break; + } + } + + if(script != "") { // scripts always run if defined + std::istringstream stream(script); + Sector::current()->run_script(stream, "powerup-script"); + } + + if(countdown){ // only decrease hit counter if try_open was not called + if(hit_counter == 1){ + sprite->set_action("empty"); + }else{ + hit_counter--; + } + } } void BonusBlock::draw(DrawingContext& context){ - // draw regular sprite - sprite->draw(context, get_pos(), 10); - //Draw light if on. + // do the regular drawing first + Block::draw(context); + // then Draw the light if on. if(sprite->get_action() == "on") { - Vector pos = get_pos() + (bbox.get_size() - lightsprite->get_size()) / 2; + Vector pos = get_pos() + (bbox.get_size().as_vector() - lightsprite->get_size()) / 2; context.push_target(); context.set_target(DrawingContext::LIGHTMAP); context.draw_surface(lightsprite, pos, 10);