New BadGuy: GoldBomb - a bomb that throws a bunch of coins when exploding.
authorLMH <lmh.0013@gmail.com>
Tue, 16 Jul 2013 15:16:05 +0000 (05:16 -1000)
committerLMH <lmh.0013@gmail.com>
Tue, 16 Jul 2013 15:41:36 +0000 (05:41 -1000)
Note: these coins are currently counted in level statistics.  Also goldbomb is not allowed to be dispensed at this time.

16 files changed:
data/images/creatures/gold_bomb/exploding-left-0.png [new file with mode: 0644]
data/images/creatures/gold_bomb/exploding-left-1.png [new file with mode: 0644]
data/images/creatures/gold_bomb/exploding-left-2.png [new file with mode: 0644]
data/images/creatures/gold_bomb/exploding-left-3.png [new file with mode: 0644]
data/images/creatures/gold_bomb/exploding-left-4.png [new file with mode: 0644]
data/images/creatures/gold_bomb/gold_bomb.sprite [new file with mode: 0644]
data/images/creatures/gold_bomb/iced-left.png [new file with mode: 0644]
data/images/creatures/gold_bomb/left-0.png [new file with mode: 0644]
data/images/creatures/gold_bomb/left-1.png [new file with mode: 0644]
data/images/creatures/gold_bomb/left-2.png [new file with mode: 0644]
src/badguy/bomb.cpp
src/badguy/dispenser.cpp
src/badguy/goldbomb.cpp [new file with mode: 0644]
src/badguy/goldbomb.hpp [new file with mode: 0644]
src/supertux/level.cpp
src/supertux/object_factory.cpp

diff --git a/data/images/creatures/gold_bomb/exploding-left-0.png b/data/images/creatures/gold_bomb/exploding-left-0.png
new file mode 100644 (file)
index 0000000..943315f
Binary files /dev/null and b/data/images/creatures/gold_bomb/exploding-left-0.png differ
diff --git a/data/images/creatures/gold_bomb/exploding-left-1.png b/data/images/creatures/gold_bomb/exploding-left-1.png
new file mode 100644 (file)
index 0000000..21d1967
Binary files /dev/null and b/data/images/creatures/gold_bomb/exploding-left-1.png differ
diff --git a/data/images/creatures/gold_bomb/exploding-left-2.png b/data/images/creatures/gold_bomb/exploding-left-2.png
new file mode 100644 (file)
index 0000000..54f9c9f
Binary files /dev/null and b/data/images/creatures/gold_bomb/exploding-left-2.png differ
diff --git a/data/images/creatures/gold_bomb/exploding-left-3.png b/data/images/creatures/gold_bomb/exploding-left-3.png
new file mode 100644 (file)
index 0000000..3c0477b
Binary files /dev/null and b/data/images/creatures/gold_bomb/exploding-left-3.png differ
diff --git a/data/images/creatures/gold_bomb/exploding-left-4.png b/data/images/creatures/gold_bomb/exploding-left-4.png
new file mode 100644 (file)
index 0000000..4e763bb
Binary files /dev/null and b/data/images/creatures/gold_bomb/exploding-left-4.png differ
diff --git a/data/images/creatures/gold_bomb/gold_bomb.sprite b/data/images/creatures/gold_bomb/gold_bomb.sprite
new file mode 100644 (file)
index 0000000..df1ed18
--- /dev/null
@@ -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"))
+)
diff --git a/data/images/creatures/gold_bomb/iced-left.png b/data/images/creatures/gold_bomb/iced-left.png
new file mode 100644 (file)
index 0000000..22f5afa
Binary files /dev/null and b/data/images/creatures/gold_bomb/iced-left.png differ
diff --git a/data/images/creatures/gold_bomb/left-0.png b/data/images/creatures/gold_bomb/left-0.png
new file mode 100644 (file)
index 0000000..3922221
Binary files /dev/null and b/data/images/creatures/gold_bomb/left-0.png differ
diff --git a/data/images/creatures/gold_bomb/left-1.png b/data/images/creatures/gold_bomb/left-1.png
new file mode 100644 (file)
index 0000000..58f39f3
Binary files /dev/null and b/data/images/creatures/gold_bomb/left-1.png differ
diff --git a/data/images/creatures/gold_bomb/left-2.png b/data/images/creatures/gold_bomb/left-2.png
new file mode 100644 (file)
index 0000000..6c2cb05
Binary files /dev/null and b/data/images/creatures/gold_bomb/left-2.png differ
index 75dcf42..0283fb5 100644 (file)
@@ -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;
index da9514b..cb4a923 100644 (file)
@@ -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;
diff --git a/src/badguy/goldbomb.cpp b/src/badguy/goldbomb.cpp
new file mode 100644 (file)
index 0000000..f87f605
--- /dev/null
@@ -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 */
diff --git a/src/badguy/goldbomb.hpp b/src/badguy/goldbomb.hpp
new file mode 100644 (file)
index 0000000..d82d28e
--- /dev/null
@@ -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 */
index fbd16c3..0d78d53 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "supertux/level.hpp"
 
+#include "badguy/goldbomb.hpp"
 #include "lisp/list_iterator.hpp"
 #include "lisp/parser.hpp"
 #include "object/bonus_block.hpp"
@@ -210,15 +211,10 @@ Level::get_total_coins()
           total_coins += 10;
           continue;
         }
-#if 0
-        // FIXME: do we want this? q.v. src/object/oneup.cpp
-        else if (block->contents == BonusBlock::CONTENT_1UP)
-        {
-          total_coins += 100;
-          continue;
-        }
-#endif
       }
+      GoldBomb *goldbomb = dynamic_cast<GoldBomb*> (*o);
+      if(goldbomb)
+        total_coins += 10;
     }
   }
   return total_coins;
index 42fe344..d08e1f7 100644 (file)
@@ -37,6 +37,7 @@
 #include "badguy/flame.hpp"
 #include "badguy/flyingsnowball.hpp"
 #include "badguy/ghosttree.hpp"
+#include "badguy/goldbomb.hpp"
 #include "badguy/haywire.hpp"
 #include "badguy/igel.hpp"
 #include "badguy/jumpy.hpp"
@@ -189,6 +190,7 @@ ObjectFactory::init_factories()
   add_factory<Flame>("flame");
   add_factory<FlyingSnowBall>("flyingsnowball");
   add_factory<GhostTree>("ghosttree");
+  add_factory<GoldBomb>("goldbomb");
   add_factory<Haywire>("haywire");
   add_factory<Igel>("igel");
   add_factory<Jumpy>("jumpy");