Skip to content

Commit

Permalink
New BadGuy: GoldBomb - a bomb that throws a bunch of coins when explo…
Browse files Browse the repository at this point in the history
…ding.

Note: these coins are currently counted in level statistics.  Also goldbomb is not allowed to be dispensed at this time.
  • Loading branch information
LMH0013 committed Jul 16, 2013
1 parent b9a95f9 commit 29ec866
Show file tree
Hide file tree
Showing 16 changed files with 386 additions and 8 deletions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 68 additions & 0 deletions data/images/creatures/gold_bomb/gold_bomb.sprite
@@ -0,0 +1,68 @@
(supertux-sprite
(action
(name "left")
(fps 10.0)
(hitbox 5 8 32 32)
(images "left-0.png"
"left-1.png"
"left-2.png"
"left-1.png"))

(action
(name "right")
(fps 10.0)
(hitbox 5 8 32 32)
(mirror-action "left"))

(action
(name "iced-left")
(hitbox 5 8 31.8 31.8)
(images "iced-left.png"))

(action
(name "iced-right")
(hitbox 5 8 31.8 31.8)
(mirror-action "iced-left"))

(action
(name "ticking-left")
(fps 10.0)
(hitbox 5 8 32 32)
(images "exploding-left-0.png"
"exploding-left-1.png"
"exploding-left-2.png"
"exploding-left-3.png"
"exploding-left-4.png"
"exploding-left-3.png"
"exploding-left-2.png"
"exploding-left-1.png"
"exploding-left-0.png"
"exploding-left-1.png"
"exploding-left-2.png"
"exploding-left-3.png"
"exploding-left-4.png"
"exploding-left-3.png"
"exploding-left-2.png"
"exploding-left-1.png"
"exploding-left-0.png"
"exploding-left-2.png"
"exploding-left-4.png"
"exploding-left-2.png"
"exploding-left-0.png"
"exploding-left-2.png"
"exploding-left-4.png"
"exploding-left-2.png"
"exploding-left-0.png"
"exploding-left-4.png"
"exploding-left-0.png"
"exploding-left-4.png"
))


(action
(name "ticking-right")
(fps 10.0)
(hitbox 5 8 32 32)
(mirror-action "ticking-left"))

)
Binary file added data/images/creatures/gold_bomb/iced-left.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/creatures/gold_bomb/left-0.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/creatures/gold_bomb/left-1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added data/images/creatures/gold_bomb/left-2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/badguy/bomb.cpp
Expand Up @@ -123,6 +123,7 @@ Bomb::ungrab(MovingObject& object, Direction dir)
this->dir = dir;
// portable objects are usually pushed away from Tux when dropped, but we
// don't want that, so we set the position
//FIXME: why don't we want that? shouldn't behavior be consistent?
set_pos(object.get_pos() + Vector(dir == LEFT ? -16 : 16, get_bbox().get_height()*0.66666 - 32));
set_colgroup_active(COLGROUP_MOVING);
grabbed = false;
Expand Down
4 changes: 4 additions & 0 deletions src/badguy/dispenser.cpp
Expand Up @@ -199,6 +199,10 @@ Dispenser::launch_badguy()
log_warning << "random is outdated; use a list of badguys to select from." << std::endl;
return;
}
if(badguy == "goldbomb") {
log_warning << "goldbomb is not allowed to be dispensed" << std::endl;
return;
}

try {
GameObject *game_object;
Expand Down
240 changes: 240 additions & 0 deletions src/badguy/goldbomb.cpp
@@ -0,0 +1,240 @@
// SuperTux BadGuy GoldBomb - a bomb that throws up coins when exploding
// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
// Copyright (C) 2013 LMH <lmh.0013@gmail.com>
//
// 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
// 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, see <http://www.gnu.org/licenses/>.

#include "audio/sound_manager.hpp"
#include "badguy/goldbomb.hpp"
#include "object/coin_explode.hpp"
#include "object/explosion.hpp"
#include "object/player.hpp"
#include "object/portable.hpp"
#include "sprite/sprite.hpp"
#include "sprite/sprite_manager.hpp"
#include "supertux/object_factory.hpp"
#include "supertux/sector.hpp"
#include "util/reader.hpp"

GoldBomb::GoldBomb(const Reader& reader) :
WalkingBadguy(reader, "images/creatures/gold_bomb/gold_bomb.sprite", "left", "right"),
tstate(STATE_NORMAL),
grabbed(false),
grabber(NULL)
{
walk_speed = 80;
max_drop_height = 16;

//Prevent stutter when Tux jumps on Gold Bomb
sound_manager->preload("sounds/explosion.wav");

//Check if we need another sprite
if( !reader.get( "sprite", sprite_name ) ){
return;
}
if( sprite_name == "" ){
sprite_name = "images/creatures/gold_bomb/gold_bomb.sprite";
return;
}
//Replace sprite
sprite = sprite_manager->create( sprite_name );
}

void
GoldBomb::collision_solid(const CollisionHit& hit)
{
if(tstate == STATE_TICKING) {
if(hit.bottom) {
physic.set_velocity_y(0);
physic.set_velocity_x(0);
}else if (hit.left || hit.right)
physic.set_velocity_x(-physic.get_velocity_x());
else if (hit.top)
physic.set_velocity_y(0);
return;
}
WalkingBadguy::collision_solid(hit);
}

HitResponse
GoldBomb::collision(GameObject& object, const CollisionHit& hit)
{
if(tstate == STATE_TICKING)
return ABORT_MOVE;
if(grabbed)
return FORCE_MOVE;
return WalkingBadguy::collision(object, hit);
}

HitResponse
GoldBomb::collision_player(Player& player, const CollisionHit& hit)
{
if(tstate == STATE_TICKING)
return ABORT_MOVE;
if(grabbed)
return FORCE_MOVE;
return WalkingBadguy::collision_player(player, hit);
}

HitResponse
GoldBomb::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
{
if(tstate == STATE_TICKING)
return ABORT_MOVE;
return WalkingBadguy::collision_badguy(badguy, hit);
}

bool
GoldBomb::collision_squished(GameObject& object)
{
Player* player = dynamic_cast<Player*>(&object);
if(player && player->is_invincible()) {
player->bounce(*this);
kill_fall();
return true;
}
if(is_valid() && tstate == STATE_NORMAL) {
tstate = STATE_TICKING;
frozen = false;
set_action(dir == LEFT ? "ticking-left" : "ticking-right", 1);
physic.set_velocity_x(0);

if (player)
player->bounce(*this);

ticking.reset(sound_manager->create_sound_source("sounds/fizz.wav"));
ticking->set_position(get_pos());
ticking->set_looping(true);
ticking->set_gain(2.0);
ticking->set_reference_distance(32);
ticking->play();
}
return true;
}

void
GoldBomb::active_update(float elapsed_time)
{
if(tstate == STATE_TICKING) {
ticking->set_position(get_pos());
if(sprite->animation_done()) {
kill_fall();
}
else if (!grabbed) {
movement = physic.get_movement(elapsed_time);
}
return;
}
if(grabbed)
return;
WalkingBadguy::active_update(elapsed_time);
}

void
GoldBomb::kill_fall()
{
if(tstate == STATE_TICKING)
ticking->stop();

// Make the player let go before we explode, otherwise the player is holding
// an invalid object. There's probably a better way to do this than in the
// GoldBomb class.
if (grabber != NULL) {
Player* player = dynamic_cast<Player*>(grabber);

if (player)
player->stop_grabbing();
}

if(is_valid()) {
remove_me();
Sector::current()->add_object(new Explosion(get_bbox().get_middle()));
Sector::current()->add_object(new CoinExplode(get_pos() + Vector (0, -40), 1));
}

run_dead_script();
}

void
GoldBomb::grab(MovingObject& object, const Vector& pos, Direction dir)
{
if(tstate == STATE_TICKING){
movement = pos - get_pos();
this->dir = dir;

// We actually face the opposite direction of Tux here to make the fuse more
// visible instead of hiding it behind Tux
sprite->set_action_continued(dir == LEFT ? "ticking-right" : "ticking-left");
set_colgroup_active(COLGROUP_DISABLED);
grabbed = true;
grabber = &object;
}
else if(frozen){
movement = pos - get_pos();
this->dir = dir;
sprite->set_action(dir == LEFT ? "iced-left" : "iced-right");
set_colgroup_active(COLGROUP_DISABLED);
grabbed = true;
}
}

void
GoldBomb::ungrab(MovingObject& object, Direction dir)
{
int toss_velocity_x = 0;
int toss_velocity_y = 0;
Player* player = dynamic_cast<Player*> (&object);

// toss upwards
if(dir == UP)
toss_velocity_y += -500;

// toss to the side when moving sideways
if(player && player->physic.get_velocity_x()*(dir == LEFT ? -1 : 1) > 1) {
toss_velocity_x += (dir == LEFT) ? -200 : 200;
toss_velocity_y = (toss_velocity_y < -200) ? toss_velocity_y : -200;
// toss farther when running
if(player && player->physic.get_velocity_x()*(dir == LEFT ? -1 : 1) > 200)
toss_velocity_x += player->physic.get_velocity_x()-(190*(dir == LEFT ? -1 : 1));
}
log_warning << toss_velocity_x << toss_velocity_y << std::endl;////

//set_pos(object.get_pos() + Vector((dir == LEFT ? -33 : 33), get_bbox().get_height()*0.66666 - 32));
physic.set_velocity(toss_velocity_x, toss_velocity_y);
set_colgroup_active(COLGROUP_MOVING);
grabbed = false;
}

void
GoldBomb::freeze()
{
if(tstate == STATE_NORMAL){
WalkingBadguy::freeze();
sprite->set_action(dir == LEFT ? "iced-left" : "iced-right");
}
}

bool
GoldBomb::is_freezable() const
{
return true;
}

bool
GoldBomb::is_portable() const
{
return (frozen || (tstate == STATE_TICKING));
}

/* EOF */
67 changes: 67 additions & 0 deletions src/badguy/goldbomb.hpp
@@ -0,0 +1,67 @@
// SuperTux BadGuy GoldBomb - a bomb that throws up coins when exploding
// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
// Copyright (C) 2013 LMH <lmh.0013@gmail.com>
//
// 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
// 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, see <http://www.gnu.org/licenses/>.


#ifndef HEADER_SUPERTUX_BADGUY_GOLDBOMB_HPP
#define HEADER_SUPERTUX_BADGUY_GOLDBOMB_HPP

#include "audio/sound_source.hpp"
#include "badguy/walking_badguy.hpp"
#include "object/portable.hpp"

class GoldBomb : public WalkingBadguy, public Portable
{
public:
GoldBomb(const Reader& reader);

void collision_solid(const CollisionHit& hit);
HitResponse collision(GameObject& object, const CollisionHit& hit);
HitResponse collision_player(Player& player, const CollisionHit& hit);
HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);

void active_update(float elapsed_time);

void grab(MovingObject& object, const Vector& pos, Direction dir);
void ungrab(MovingObject& object, Direction dir);
bool is_portable() const;

void freeze();
bool is_freezable() const;

void kill_fall();

protected:
bool collision_squished(GameObject& object);

private:
GoldBomb(const GoldBomb&);
GoldBomb& operator=(const GoldBomb&);
enum Ticking_State {
STATE_NORMAL,
STATE_TICKING
};

Ticking_State tstate;
bool grabbed;
MovingObject* grabber;

std::auto_ptr<SoundSource> ticking;
};

#endif

/* EOF */

0 comments on commit 29ec866

Please sign in to comment.