X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fobject%2Fbonus_block.cpp;h=5f067766d8545da8a205c2f0c051589e044b8c14;hb=d097f456b8ab4f42058545bdd4f8f676d151e974;hp=e11c7ded37b7633ccfdecd6efd674d4f764ffb88;hpb=ee1ac3330b695b5656654f908afe16e5922d911d;p=supertux.git diff --git a/src/object/bonus_block.cpp b/src/object/bonus_block.cpp index e11c7ded3..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,15 +19,18 @@ #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" #include "sprite/sprite_manager.hpp" #include "supertux/constants.hpp" #include "supertux/level.hpp" @@ -37,10 +40,13 @@ #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), - hit_counter(1) + object(), + hit_counter(1), + sprite_name(), + script(), + lightsprite() { bbox.set_pos(pos); sprite->set_action("normal"); @@ -50,6 +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; + SoundManager::current()->preload("sounds/switch.ogg"); + lightsprite=Surface::create("/images/objects/lightmap_light/bonusblock_light.png"); + 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; @@ -58,10 +84,13 @@ 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) + hit_counter(1), + sprite_name(), + script(), + lightsprite() { Vector pos; @@ -75,7 +104,7 @@ 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") { @@ -89,21 +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; + SoundManager::current()->preload("sounds/switch.ogg"); + } else if(contentstring == "trampoline") { + contents = CONTENT_TRAMPOLINE; + } 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"); @@ -115,13 +157,14 @@ BonusBlock::BonusBlock(const Reader& lisp) : if(contents == CONTENT_CUSTOM && object == 0) throw std::runtime_error("Need to specify content object for custom block"); + if(contents == CONTENT_LIGHT) + lightsprite = Surface::create("/images/objects/lightmap_light/bonusblock_light.png"); bbox.set_pos(pos); } BonusBlock::~BonusBlock() { - delete object; } void @@ -131,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); @@ -155,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; } @@ -171,7 +214,7 @@ BonusBlock::try_open(Player *player) if (player == NULL) player = sector->player; - + if (player == NULL) return; @@ -179,60 +222,135 @@ 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); - Sector::current()->get_level()->stats.coins++; + if (hit_counter != 0) + 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)); + 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; + } case CONTENT_SCRIPT: - if(script != "") { - std::istringstream stream(script); - Sector::current()->run_script(stream, "powerup-script"); - } + { break; } // because scripts always run, this prevents default contents from being assumed + + case CONTENT_LIGHT: + { + if(sprite->get_action() == "on") + sprite->set_action("off"); + else + sprite->set_action("on"); + SoundManager::current()->play("sounds/switch.ogg"); + break; + } + case CONTENT_TRAMPOLINE: + { + auto riser = std::make_shared(get_pos(), std::make_shared(get_pos(), false)); + sector->add_object(riser); + SoundManager::current()->play("sounds/upgrade.wav"); + break; + } + case CONTENT_RAIN: + { + 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_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"); + break; + } + } + + if(script != "") { // scripts always run if defined + std::istringstream stream(script); + Sector::current()->run_script(stream, "BonusBlockScript"); } start_bounce(player); - if(hit_counter <= 0){ //use 0 to allow infinite hits + if(hit_counter <= 0 || contents == CONTENT_LIGHT){ //use 0 to allow infinite hits }else if(hit_counter == 1){ sprite->set_action("empty"); }else{ @@ -241,21 +359,156 @@ 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){ + // 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().as_vector() - lightsprite->get_size()) / 2; + context.push_target(); + context.set_target(DrawingContext::LIGHTMAP); + context.draw_surface(lightsprite, pos, 10); + context.pop_target(); + } +} /* EOF */