Possible fix for issue 369: Wrong kill animation after being hit by enemy on a sloped...
[supertux.git] / src / object / coin.cpp
index 9977ff8..d3cc163 100644 (file)
 #include "object/coin.hpp"
 
 #include "audio/sound_manager.hpp"
+#include "util/reader.hpp"
 #include "object/bouncy_coin.hpp"
 #include "object/player.hpp"
+#include "object/tilemap.hpp"
 #include "supertux/level.hpp"
 #include "supertux/object_factory.hpp"
 #include "supertux/sector.hpp"
 
 Coin::Coin(const Vector& pos)
-  : MovingSprite(pos, "images/objects/coin/coin.sprite", LAYER_TILES, COLGROUP_TOUCHABLE)
+  : MovingSprite(pos, "images/objects/coin/coin.sprite", LAYER_OBJECTS - 1, COLGROUP_TOUCHABLE),
+    path(),
+    walker(),
+    offset(),
+    from_tilemap(false),
+    physic()
 {
   sound_manager->preload("sounds/coin.wav");
 }
 
+Coin::Coin(const Vector& pos, TileMap* tilemap)
+  : MovingSprite(pos, "images/objects/coin/coin.sprite", LAYER_OBJECTS - 1, COLGROUP_TOUCHABLE),
+    path(boost::shared_ptr<Path>(tilemap->get_path())),
+    walker(boost::shared_ptr<PathWalker>(tilemap->get_walker())),
+    offset(),
+    from_tilemap(true),
+    physic()
+{
+  if(walker.get()) {
+    Vector v = path->get_base();
+    offset = pos - v;
+  }
+
+  sound_manager->preload("sounds/coin.wav");
+}
+
 Coin::Coin(const Reader& reader)
-  : MovingSprite(reader, "images/objects/coin/coin.sprite", LAYER_TILES, COLGROUP_TOUCHABLE)
+  : MovingSprite(reader, "images/objects/coin/coin.sprite", LAYER_OBJECTS - 1, COLGROUP_TOUCHABLE),
+    path(),
+    walker(),
+    offset(),
+    from_tilemap(false),
+    physic()
 {
+  const lisp::Lisp* pathLisp = reader.get_lisp("path");
+  if (pathLisp) {
+    path.reset(new Path());
+    path->read(*pathLisp);
+    walker.reset(new PathWalker(path.get()));
+    Vector v = path->get_base();
+    set_pos(v);
+  }
+
   sound_manager->preload("sounds/coin.wav");
 }
 
 void
+Coin::update(float elapsed_time)
+{
+  // if we have a path to follow, follow it
+  if (walker.get()) {
+    Vector v = from_tilemap ? offset + walker->get_pos() : walker->advance(elapsed_time);
+    movement = v - get_pos();
+  }
+}
+
+void
 Coin::collect()
 {
   // TODO: commented out musical code. Maybe fork this for a special "MusicalCoin" object?
@@ -125,4 +172,59 @@ Coin::collision(GameObject& other, const CollisionHit& )
   return ABORT_MOVE;
 }
 
+/* The following defines a coin subject to gravity */
+HeavyCoin::HeavyCoin(const Vector& pos, const Vector& init_velocity)
+  : Coin(pos),
+  physic()
+{
+  physic.enable_gravity(true);
+  sound_manager->preload("sounds/coin2.ogg");
+  set_group(COLGROUP_MOVING);
+  physic.set_velocity(init_velocity);
+}
+
+HeavyCoin::HeavyCoin(const Reader& reader)
+  : Coin(reader),
+  physic()
+{
+  physic.enable_gravity(true);
+  sound_manager->preload("sounds/coin2.ogg");
+  set_group(COLGROUP_MOVING);
+}
+
+void
+HeavyCoin::update(float elapsed_time)
+{
+  // enable physics
+  movement = physic.get_movement(elapsed_time);
+}
+
+void
+HeavyCoin::collision_solid(const CollisionHit& hit)
+{
+  int clink_threshold = 100; // sets the minimum speed needed to result in collision noise
+  //TODO: colliding HeavyCoins should have their own unique sound
+
+  if(hit.bottom) {
+    if(physic.get_velocity_y() > clink_threshold)
+      sound_manager->play("sounds/coin2.ogg");
+    if(physic.get_velocity_y() > 200) {// lets some coins bounce
+      physic.set_velocity_y(-99);
+    }else{
+      physic.set_velocity_y(0);
+      physic.set_velocity_x(0);
+    }
+  }
+  if(hit.right || hit.left) {
+    if(physic.get_velocity_x() > clink_threshold || physic.get_velocity_x() < clink_threshold)
+      sound_manager->play("sounds/coin2.ogg");
+    physic.set_velocity_x(-physic.get_velocity_x());
+  }
+  if(hit.top) {
+    if(physic.get_velocity_y() < clink_threshold)
+      sound_manager->play("sounds/coin2.ogg");
+    physic.set_velocity_y(-physic.get_velocity_y());
+  }
+}
+
 /* EOF */