merged new collision detection branch back into mainline
authorMatthias Braun <matze@braunis.de>
Sun, 9 Jul 2006 10:32:59 +0000 (10:32 +0000)
committerMatthias Braun <matze@braunis.de>
Sun, 9 Jul 2006 10:32:59 +0000 (10:32 +0000)
SVN-Revision: 3962

101 files changed:
data/images/objects/bullets/firebullet.sprite
data/levels/test/simple.stl
data/levels/test/slopes.stl
src/badguy/angrystone.cpp
src/badguy/angrystone.hpp
src/badguy/badguy.cpp
src/badguy/badguy.hpp
src/badguy/bomb.cpp
src/badguy/bomb.hpp
src/badguy/bouncing_snowball.cpp
src/badguy/bouncing_snowball.hpp
src/badguy/dart.cpp
src/badguy/dart.hpp
src/badguy/fish.cpp
src/badguy/fish.hpp
src/badguy/flyingsnowball.cpp
src/badguy/flyingsnowball.hpp
src/badguy/igel.cpp
src/badguy/igel.hpp
src/badguy/jumpy.cpp
src/badguy/jumpy.hpp
src/badguy/kugelblitz.cpp
src/badguy/kugelblitz.hpp
src/badguy/mrbomb.cpp
src/badguy/mrbomb.hpp
src/badguy/mriceblock.cpp
src/badguy/mriceblock.hpp
src/badguy/mrrocket.cpp
src/badguy/mrrocket.hpp
src/badguy/mrtree.cpp
src/badguy/mrtree.hpp
src/badguy/nolok_01.cpp [deleted file]
src/badguy/nolok_01.hpp [deleted file]
src/badguy/plant.cpp
src/badguy/plant.hpp
src/badguy/poisonivy.cpp
src/badguy/poisonivy.hpp
src/badguy/rocketexplosion.cpp
src/badguy/rocketexplosion.hpp
src/badguy/skullyhop.cpp
src/badguy/skullyhop.hpp
src/badguy/snail.cpp
src/badguy/snail.hpp
src/badguy/snowball.cpp
src/badguy/snowball.hpp
src/badguy/spidermite.cpp
src/badguy/spidermite.hpp
src/badguy/spiky.cpp
src/badguy/spiky.hpp
src/badguy/sspiky.cpp
src/badguy/sspiky.hpp
src/badguy/stalactite.cpp
src/badguy/stalactite.hpp
src/badguy/totem.cpp
src/badguy/totem.hpp
src/badguy/yeti.cpp
src/badguy/yeti.hpp
src/badguy/zeekling.cpp
src/badguy/zeekling.hpp
src/collision.cpp
src/collision.hpp
src/collision_grid.cpp [deleted file]
src/collision_grid.hpp [deleted file]
src/collision_grid_iterator.hpp [deleted file]
src/collision_hit.hpp
src/log.cpp
src/log.hpp
src/math/rect.hpp
src/moving_object.hpp
src/object/block.cpp
src/object/bullet.cpp
src/object/bullet.hpp
src/object/candle.cpp
src/object/coin.cpp
src/object/coin.hpp
src/object/flower.cpp
src/object/flower.hpp
src/object/growup.cpp
src/object/growup.hpp
src/object/hurting_platform.cpp
src/object/invisible_block.cpp
src/object/invisible_block.hpp
src/object/particlesystem_interactive.cpp
src/object/platform.cpp
src/object/player.cpp
src/object/player.hpp
src/object/powerup.cpp
src/object/powerup.hpp
src/object/rock.cpp
src/object/rock.hpp
src/object/scripted_object.cpp
src/object/scripted_object.hpp
src/object/skull_tile.cpp
src/object/star.cpp
src/object/star.hpp
src/object/unstable_tile.cpp
src/object/weak_block.hpp
src/scripting/player.hpp
src/scripting/wrapper.cpp
src/sector.cpp
src/sector.hpp

index c4381ec..dafa1f7 100644 (file)
@@ -1,6 +1,6 @@
 (supertux-sprite
  (action
-  (hitbox 12 12 0 0)
+  (hitbox 2 2 12 12)
   (fps 20)
   (images "fire_bullet-0.png"
    "fire_bullet-1.png"
index c7f720d..29d20c2 100644 (file)
@@ -30,7 +30,7 @@
       (speed 1)
       (width 100)
       (height 35)
-      (tiles 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 0 28 0 28 0 28 0 28 0 28 0 0 28 0 28 0 28 28 28 28 28 28 28 28 28 28 28 28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
+      (tiles 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 0 28 0 28 0 28 0 28 0 28 0 0 28 0 28 0 28 28 28 28 28 28 28 28 28 28 28 28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 48 48 48 48 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 48 0 0 0 0 0 0 0 0 0 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 102 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 48 48 48 48 48 48 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 48 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 48 48 48 48 48 48 48 48 48 48 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
     )
     (tilemap
       (z-pos 100)
index c7789c2..fb17164 100644 (file)
@@ -30,7 +30,7 @@
       (speed 1)
       (width 150)
       (height 35)
-      (tiles 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1001 1002 1001 1002 1001 1002 1052 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1053 1005 1006 1005 1006 1005 1006 1054 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1055 1009 1009 1009 1009 1009 1009 1056 1052 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1053 1057 1009 1009 1009 1009 1009 1009 1058 1054 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1055 1009 1009 1009 1009 1009 1009 1009 1009 1056 1052 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1053 1057 1009 1009 1009 1009 1009 1009 1009 1009 1058 1054 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1001 1002 1001 1003 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1045 1055 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1056 1046 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1053 1005 1006 1005 1007 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1045 1047 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1058 1048 1046 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1055 1013 1013 1013 1011 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1045 1047 1049 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1050 1048 1046 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1001 1002 1001 1003 0 0 0 0 0 0 0 0 0 0 0 0 1001 1002 1001 1003 0 0 0 0 0 0 0 0 0 0 0 0 1053 1057 1013 1013 1013 1011 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1045 1047 1049 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1050 1048 1061 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1005 1006 1005 1007 0 0 0 0 0 0 0 0 0 0 1045 1047 1005 1006 1005 1007 0 0 0 0 0 1051 1052 0 0 0 0 1051 1055 1013 1013 1013 1013 1011 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1047 1049 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1050 1065 1066 1061 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1061 0 0 0 0 1060 1063 1064 1013 1013 1013 1013 1013 1011 0 0 0 0 0 1045 1046 0 0 1045 1047 1049 1013 1013 1013 1011 0 0 0 0 0 1053 1054 0 0 0 0 1053 1057 1013 1013 1013 1013 1011 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1049 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1069 1070 1065 1066 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1001 1002 1001 1002 1001 1002 1001 1063 1064 1065 1066 1002 1001 1063 1064 1067 1013 1013 1013 1013 1013 1013 1035 1001 1002 1001 1002 1001 1047 1048 1001 1002 1047 1049 1013 1013 1013 1013 1035 1001 1002 1001 1002 1001 1055 1056 1002 1001 1002 1001 1055 1013 1013 1013 1013 1013 1035 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1063 1064 1067 1068 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1070 1065 1066 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1005 1006 1005 1006 1005 1006 1005 1067 1068 1069 1070 1006 1005 1067 1068 1069 1013 1013 1013 1013 1013 1013 1043 1005 1006 1005 1006 1005 1049 1050 1005 1006 1049 1013 1013 1013 1013 1013 1043 1005 1006 1005 1006 1005 1057 1058 1006 1005 1006 1005 1057 1013 1013 1013 1013 1013 1043 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1067 1068 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1069 1070 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1061 0 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1035 1061 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1065 1066 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1043 1065 1066 1061 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1013 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 1069 1070 1065 1066 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1001 1002 1001 1002 1001 1001 1002 1001 1002 1001 1063 1064 1013 1013 1013 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 1009 1009 1009 1070 1065 1066 1002 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1005 1006 1005 1006 1005 1005 1006 1005 1006 1005 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 1009 1009 1009 1009 1069 1070 1006 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
+      (tiles 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1001 1002 1001 1002 1001 1002 1052 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1053 1005 1006 1005 1006 1005 1006 1054 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1055 1009 1009 1009 1009 1009 1009 1056 1052 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1053 1057 1009 1009 1009 1009 1009 1009 1058 1054 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1055 1009 1009 1009 1009 1009 1009 1009 1009 1056 1052 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1053 1057 1009 1009 1009 1009 1009 1009 1009 1009 1058 1054 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1001 1002 1001 1003 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1045 1055 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1056 1046 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1053 1005 1006 1005 1007 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1045 1047 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1058 1048 1046 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1051 1055 1013 1013 1013 1011 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1045 1047 1049 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1050 1048 1046 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1001 1002 1001 1003 0 0 0 0 0 0 0 0 0 0 0 0 1001 1002 1001 1003 0 0 0 0 0 0 0 0 0 0 0 0 1053 1057 1013 1013 1013 1011 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1045 1047 1049 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1050 1048 1061 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1005 1006 1005 1007 0 0 0 0 0 0 0 0 0 0 1045 1047 1005 1006 1005 1007 0 0 0 0 0 1051 1052 0 0 0 0 1051 1055 1013 1013 1013 1013 1011 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1047 1049 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1050 1065 1066 1061 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1061 0 0 0 0 1060 1063 1064 1013 1013 1013 1013 1013 1011 0 0 0 0 0 1045 1046 0 0 1045 1047 1049 1013 1013 1013 1011 0 0 0 0 0 1053 1054 0 0 0 0 1053 1057 1013 1013 1013 1013 1011 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1049 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1069 1070 1065 1066 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1001 1002 1001 1002 1001 1002 1001 1063 1064 1065 1066 1002 1001 1063 1064 1067 1013 1013 1013 1013 1013 1013 1035 1001 1002 1001 1002 1001 1047 1048 1001 1002 1047 1049 1013 1013 1013 1013 1035 1001 1002 1001 1002 1001 1055 1056 1002 1001 1002 1001 1055 1013 1013 1013 1013 1013 1035 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1063 1064 1067 1068 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1070 1065 1066 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1005 1006 1005 1006 1005 1006 1005 1067 1068 1069 1070 1006 1005 1067 1068 1069 1013 1013 1013 1013 1013 1013 1043 1005 1006 1005 1006 1005 1049 1050 1005 1006 1049 1013 1013 1013 1013 1013 1043 1006 1006 1005 1006 1005 1057 1058 1006 1005 1006 1005 1057 1013 1013 1013 1013 1013 1043 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1067 1068 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1009 1069 1070 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1013 1013 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1061 0 1013 1013 0 0 0 0 0 1060 1061 0 0 0 0 0 0 1060 1063 1064 1013 1013 1013 1013 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1035 1061 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1065 1066 1013 1013 0 0 0 1060 1063 1064 1065 1066 1061 0 0 1060 1063 1064 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1043 1065 1066 1061 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1060 1063 1064 1013 1013 1013 1013 1013 1013 0 1060 1063 1064 1013 1013 1013 1013 1065 1066 1063 1064 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 1069 1070 1065 1066 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1001 1002 1001 1002 1001 1001 1002 1001 1002 1001 1063 1064 1013 1013 1013 1013 1013 1013 1013 1013 1063 1064 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 1009 1009 1009 1070 1065 1066 1002 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 1002 1001 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1005 1006 1005 1006 1005 1005 1006 1005 1006 1005 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 1013 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1009 1009 1009 1009 1009 1009 1009 1009 1009 1069 1070 1006 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 1006 1005 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
     )
     (tilemap
       (z-pos 100)
index 010230c..bcf6d90 100644 (file)
@@ -53,10 +53,14 @@ AngryStone::activate()
   sprite->set_action("idle");
 }
 
-HitResponse
-AngryStone::collision_solid(GameObject& , const CollisionHit& hit)
+void
+AngryStone::collision_solid(const CollisionHit& hit)
 {
-  if ((state == ATTACKING) && (hit.normal.x == -attackDirection.x) && (hit.normal.y == attackDirection.y)) {
+  // TODO
+  (void) hit;
+#if 0
+  if ((state == ATTACKING) && 
+      (hit.normal.x == -attackDirection.x) && (hit.normal.y == attackDirection.y)) {
     state = IDLE;
     sprite->set_action("idle");
     physic.set_velocity_x(0);
@@ -65,8 +69,7 @@ AngryStone::collision_solid(GameObject& , const CollisionHit& hit)
     oldWallDirection.x = attackDirection.x;
     oldWallDirection.y = attackDirection.y;
   }
-
-  return CONTINUE;
+#endif
 }
 
 void
index 0b7dbf7..3b1c974 100644 (file)
@@ -30,7 +30,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
   void active_update(float elapsed_time);
   void kill_fall();
index 3c1595f..26db65d 100644 (file)
@@ -144,7 +144,7 @@ BadGuy::deactivate()
 void
 BadGuy::save(lisp::Writer& )
 {
-       log_warning << "tried to write out a generic badguy" << std::endl;
+  log_warning << "tried to write out a generic badguy" << std::endl;
 }
 
 void
@@ -173,9 +173,6 @@ BadGuy::collision(GameObject& other, const CollisionHit& hit)
     case STATE_INACTIVE:
       return ABORT_MOVE;
     case STATE_ACTIVE: {
-      if(other.get_flags() & FLAG_SOLID)
-        return collision_solid(other, hit);
-
       BadGuy* badguy = dynamic_cast<BadGuy*> (&other);
       if(badguy && badguy->state == STATE_ACTIVE && badguy->get_group() == COLGROUP_MOVING)
         return collision_badguy(*badguy, hit);
@@ -191,8 +188,6 @@ BadGuy::collision(GameObject& other, const CollisionHit& hit)
       return FORCE_MOVE;
     }
     case STATE_SQUISHED:
-      if(other.get_flags() & FLAG_SOLID)
-        return CONTINUE;
       return FORCE_MOVE;
     case STATE_FALLING:
       return FORCE_MOVE;
@@ -201,28 +196,20 @@ BadGuy::collision(GameObject& other, const CollisionHit& hit)
   return ABORT_MOVE;
 }
 
-HitResponse
-BadGuy::collision_solid(GameObject& , const CollisionHit& )
+void
+BadGuy::collision_solid(const CollisionHit& )
 {
-  return FORCE_MOVE;
 }
 
 HitResponse
 BadGuy::collision_player(Player& player, const CollisionHit& )
 {
-  /*
-  printf("PlayerHit: GT %3.1f PM: %3.1f %3.1f BM: %3.1f %3.1f Hit: %3.1f %3.1f\n",
-          game_time,
-          player.get_movement().x, player.get_movement().y,
-          get_movement().x, get_movement().y,
-          hit.normal.x, hit.normal.y);
-  */
-
   // hit from above?
   if(player.get_bbox().p2.y < (bbox.p1.y + 16)) {
     // if it's not possible to squish us, then this will hurt
-    if(collision_squished(player))
+    if(collision_squished(player)) {
       return ABORT_MOVE;
+    }
   }
 
   if(player.is_invincible()) {
index 0b8d8de..797cd44 100644 (file)
@@ -57,8 +57,7 @@ public:
    * implemetnation calls collision_player, collision_solid, collision_badguy
    * and collision_squished
    */
-  virtual HitResponse collision(GameObject& other,
-      const CollisionHit& hit);
+  virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
 
   /** Called when a collision with tile with special attributes occured */
   virtual void collision_tile(uint32_t tile_attributes);
@@ -96,14 +95,11 @@ protected:
   };
  
   /** Called when the badguy collided with a player */
-  virtual HitResponse collision_player(Player& player,
-      const CollisionHit& hit);
+  virtual HitResponse collision_player(Player& player, const CollisionHit& hit);
   /** Called when the badguy collided with solid ground */
-  virtual HitResponse collision_solid(GameObject& other,
-      const CollisionHit& hit);
+  virtual void collision_solid(const CollisionHit& hit);
   /** Called when the badguy collided with another badguy */
-  virtual HitResponse collision_badguy(BadGuy& other,
-      const CollisionHit& hit);
+  virtual HitResponse collision_badguy(BadGuy& other, const CollisionHit& hit);
  
   /** Called when the player hit the badguy from above. You should return true
    * if the badguy was squished, false if squishing wasn't possible
@@ -111,8 +107,7 @@ protected:
   virtual bool collision_squished(Player& player);
 
   /** Called when the badguy collided with a bullet */
-  virtual HitResponse collision_bullet(Bullet& bullet, 
-      const CollisionHit& hit);
+  virtual HitResponse collision_bullet(Bullet& bullet, const CollisionHit& hit);
 
   /** called each frame when the badguy is activated. */
   virtual void active_update(float elapsed_time);
index 0459531..c9e2c8a 100644 (file)
@@ -57,13 +57,11 @@ Bomb::write(lisp::Writer& )
   // bombs are only temporarily so don't write them out...
 }
 
-HitResponse
-Bomb::collision_solid(GameObject& , const CollisionHit& hit)
+void
+Bomb::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5)
+  if(hit.bottom)
     physic.set_velocity_y(0);
-
-  return CONTINUE;
 }
 
 HitResponse
index 94d7159..40b29d0 100644 (file)
@@ -29,15 +29,13 @@ public:
   Bomb(const Bomb& bomb);
 
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(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 kill_fall();
   void explode();
 
-  virtual Bomb* clone() const { return new Bomb(*this); }
-
 private:
   enum State {
     STATE_TICKING,
@@ -47,7 +45,6 @@ private:
   State state;
 
   std::auto_ptr<SoundSource> ticking;
-
 };
 
 #endif
index c0af31d..9e73ee3 100644 (file)
@@ -60,33 +60,30 @@ BouncingSnowball::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-BouncingSnowball::collision_solid(GameObject& , const CollisionHit& hit)
+void
+BouncingSnowball::collision_solid(const CollisionHit& hit)
 {
-  if(hit.normal.y < -.5) { // hit floor
-    physic.set_velocity_y(JUMPSPEED);
-  } else if(hit.normal.y > .5) { // bumped on roof
+  if(hit.bottom) {
+    if(get_state() == STATE_ACTIVE) {
+      physic.set_velocity_y(JUMPSPEED);
+    } else {
+      physic.set_velocity_y(0);
+    }
+  } else if(hit.top) {
     physic.set_velocity_y(0);
-  } else { // left or right collision
+  }
+  
+  if(hit.left || hit.right) { // left or right collision
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
   }
-
-  return CONTINUE;
 }
 
 HitResponse
 BouncingSnowball::collision_badguy(BadGuy& , const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.x) > .8) { // left/right?
-    dir = dir == LEFT ? RIGHT : LEFT;
-    sprite->set_action(dir == LEFT ? "left" : "right");    
-    physic.set_velocity_x(-physic.get_velocity_x());
-  } else if(hit.normal.y < -.8) { // grounf
-    physic.set_velocity_y(JUMPSPEED);
-  }
-
+  collision_solid(hit);
   return CONTINUE;
 }
 
index 1bcb8ab..b226590 100644 (file)
@@ -30,7 +30,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
 
   virtual BouncingSnowball* clone() const { return new BouncingSnowball(*this); }
index cd251c8..992d774 100644 (file)
@@ -105,13 +105,11 @@ Dart::active_update(float elapsed_time)
   sound_source->set_position(get_pos());
 }
 
-
-HitResponse 
-Dart::collision_solid(GameObject& , const CollisionHit& )
+void
+Dart::collision_solid(const CollisionHit& )
 {
   sound_manager->play("sounds/darthit.wav", get_pos());
   remove_me();
-  return ABORT_MOVE;
 }
 
 HitResponse 
index 670a0d6..bfed41f 100644 (file)
@@ -40,7 +40,7 @@ public:
 
   void active_update(float elapsed_time);
 
-  HitResponse collision_solid(GameObject& object, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
   HitResponse collision_player(Player& player, const CollisionHit& hit);
 
index 4c6817a..4f23778 100644 (file)
@@ -50,10 +50,10 @@ Fish::write(lisp::Writer& writer)
   writer.end_list("fish");
 }
 
-HitResponse
-Fish::collision_solid(GameObject& , const CollisionHit& chit)
+void
+Fish::collision_solid(const CollisionHit& chit)
 {
-  return hit(chit);
+  hit(chit);
 }
 
 HitResponse
@@ -72,9 +72,9 @@ Fish::draw(DrawingContext& context)
 }
 
 HitResponse
-Fish::hit(const CollisionHit& chit)
+Fish::hit(const CollisionHit& hit)
 {
-  if(chit.normal.y < .5) { // hit ceiling
+  if(hit.top) {
     physic.set_velocity_y(0);
   }
 
index e1e9920..117d1d5 100644 (file)
@@ -30,7 +30,7 @@ public:
 
   void draw(DrawingContext& context);
 
-  HitResponse collision_solid(GameObject& , const CollisionHit& );
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& , const CollisionHit& );
   void collision_tile(uint32_t tile_attributes);
 
index 12dfefc..66a2db5 100644 (file)
@@ -75,14 +75,12 @@ FlyingSnowBall::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-FlyingSnowBall::collision_solid(GameObject& , const CollisionHit& hit)
+void
+FlyingSnowBall::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // hit floor or roof?
+  if(hit.top || hit.bottom) {
     physic.set_velocity_y(0);
   }
-
-  return CONTINUE;
 }
 
 void
index d9f8e91..7e78c52 100644 (file)
@@ -31,7 +31,7 @@ public:
   void activate();
   void write(lisp::Writer& writer);
   void active_update(float elapsed_time);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
 
   virtual FlyingSnowBall* clone() const { return new FlyingSnowBall(*this); }
 
index f7d5e1d..02b7163 100644 (file)
@@ -115,30 +115,26 @@ Igel::active_update(float elapsed_time)
   BadGuy::active_update(elapsed_time);
 }
 
-HitResponse
-Igel::collision_solid(GameObject& , const CollisionHit& hit)
+void
+Igel::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // floor or roof
+  if(hit.top || hit.bottom) { // floor or roof
     physic.set_velocity_y(0);
-    return CONTINUE;
+    return;
   }
 
   // hit left or right
   switch(state) {
-
     case STATE_NORMAL:
       turn_around();
       break;
-
   }
-
-  return CONTINUE;
 }
 
 HitResponse
 Igel::collision_badguy(BadGuy& , const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // floor or roof
+  if(hit.top || hit.bottom) { // floor or roof
     physic.set_velocity_y(0);
     return CONTINUE;
   }
@@ -159,7 +155,7 @@ HitResponse
 Igel::collision_bullet(Bullet& , const CollisionHit& hit)
 {
   // die if hit on front side
-  if (((dir == LEFT) && (hit.normal.x > 0)) || ((dir == RIGHT) && (hit.normal.x < 0))) {
+  if (((dir == LEFT) && hit.left) || ((dir == RIGHT) && hit.right)) {
     kill_fall();
     return ABORT_MOVE;
   }
index a824620..e368f1f 100644 (file)
@@ -34,7 +34,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& object, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
   HitResponse collision_bullet(Bullet& bullet, const CollisionHit& hit);
 
index 02ceeb1..233a672 100644 (file)
@@ -41,10 +41,10 @@ Jumpy::write(lisp::Writer& writer)
   writer.end_list("jumpy");
 }
 
-HitResponse
-Jumpy::collision_solid(GameObject& , const CollisionHit& chit)
+void
+Jumpy::collision_solid(const CollisionHit& chit)
 {
-  return hit(chit);
+  hit(chit);
 }
 
 HitResponse
@@ -56,8 +56,7 @@ Jumpy::collision_badguy(BadGuy& , const CollisionHit& chit)
 HitResponse
 Jumpy::hit(const CollisionHit& chit)
 {
-  // hit floor?
-  if(chit.normal.y < -.5) {
+  if(chit.bottom) {
     if (!groundhit_pos_set)
     {
       pos_groundhit = get_pos();
@@ -67,7 +66,7 @@ Jumpy::hit(const CollisionHit& chit)
     physic.set_velocity_y(JUMPSPEED);
     // TODO create a nice sound for this...
     //sound_manager->play("sounds/skid.wav");
-  } else if(chit.normal.y < .5) { // bumped on roof
+  } else if(chit.top) {
     physic.set_velocity_y(0);
   }
 
index 9304a42..494559b 100644 (file)
@@ -27,7 +27,7 @@ class Jumpy : public BadGuy
 public:
   Jumpy(const lisp::Lisp& reader);
 
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& other, const CollisionHit& hit);
 
   void write(lisp::Writer& writer);
index f8ecf17..68fc066 100644 (file)
@@ -60,10 +60,10 @@ Kugelblitz::activate()
   dying = false;
 }
 
-HitResponse
-Kugelblitz::collision_solid(GameObject& , const CollisionHit& chit)
+void
+Kugelblitz::collision_solid(const CollisionHit& chit)
 {
-  return hit(chit);
+  hit(chit);
 }
 
 HitResponse
@@ -97,10 +97,10 @@ Kugelblitz::collision_badguy(BadGuy& other , const CollisionHit& chit)
 }
 
 HitResponse
-Kugelblitz::hit(const CollisionHit& chit)
+Kugelblitz::hit(const CollisionHit& hit)
 {
   // hit floor?
-  if(chit.normal.y < -.5) {
+  if(hit.bottom) {
     if (!groundhit_pos_set)
     {
       pos_groundhit = get_pos();
@@ -115,7 +115,7 @@ Kugelblitz::hit(const CollisionHit& chit)
     movement_timer.start(MOVETIME);
     lifetime.start(LIFETIME);
 
-  } else if(chit.normal.y < .5) { // bumped on roof
+  } else if(hit.top) { // bumped on roof
     physic.set_velocity_y(0);
   }
 
index a9c64ba..2e7b3ee 100644 (file)
@@ -31,7 +31,7 @@ public:
 
   void activate();
   HitResponse collision_badguy(BadGuy& other, const CollisionHit& hit);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_player(Player& player, const CollisionHit& hit);
 
   void write(lisp::Writer& writer);
index 9cb02f5..15ab8f5 100644 (file)
@@ -87,28 +87,29 @@ MrBomb::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-MrBomb::collision_solid(GameObject& , const CollisionHit& hit)
+void
+MrBomb::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // hit floor or roof?
+  if(hit.bottom || hit.top) {
     physic.set_velocity_y(0);
-  } else { // hit right or left
+  }
+  if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
   }
-
-  return CONTINUE;
 }
 
 HitResponse
-MrBomb::collision_badguy(BadGuy& , const CollisionHit& hit)
+MrBomb::collision_badguy(BadGuy& )
 {
+#if 0
   if(fabsf(hit.normal.x) > .8) { // left or right
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");    
     physic.set_velocity_x(-physic.get_velocity_x());
   }
+#endif
 
   return CONTINUE;
 }
index 6e49d0b..5aa053a 100644 (file)
@@ -31,8 +31,8 @@ public:
   void activate();
   void active_update(float elapsed_time);
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
-  HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
+  HitResponse collision_badguy(BadGuy& badguy);
   void kill_fall();
 
   virtual MrBomb* clone() const { return new MrBomb(*this); }
index 95fd17f..85f3f94 100644 (file)
@@ -83,13 +83,14 @@ MrIceBlock::active_update(float elapsed_time)
   BadGuy::active_update(elapsed_time);
 }
 
-HitResponse
-MrIceBlock::collision_solid(GameObject& object, const CollisionHit& hit)
+void
+MrIceBlock::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // floor or roof
+  if(hit.top || hit.bottom) { // floor or roof
     physic.set_velocity_y(0);
-    return CONTINUE;
+    return;
   }
+
   // hit left or right
   switch(ice_state) {
     case ICESTATE_NORMAL:
@@ -98,6 +99,8 @@ MrIceBlock::collision_solid(GameObject& object, const CollisionHit& hit)
       physic.set_velocity_x(-physic.get_velocity_x());       
       break;
     case ICESTATE_KICKED: {
+#if 0
+      // TODO move these into bonusblock class
       BonusBlock* bonusblock = dynamic_cast<BonusBlock*> (&object);
       if(bonusblock) {
         bonusblock->try_open();
@@ -106,6 +109,7 @@ MrIceBlock::collision_solid(GameObject& object, const CollisionHit& hit)
       if(brick) {
         brick->try_break();
       }
+#endif
       
       dir = dir == LEFT ? RIGHT : LEFT;
       sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
@@ -117,10 +121,8 @@ MrIceBlock::collision_solid(GameObject& object, const CollisionHit& hit)
       physic.set_velocity_x(0);
       break;
     case ICESTATE_GRABBED:
-      return FORCE_MOVE;
+      break;
   }
-
-  return CONTINUE;
 }
 
 HitResponse
@@ -140,13 +142,12 @@ MrIceBlock::collision_player(Player& player, const CollisionHit& hit)
 
   // handle kicks from left or right side
   if(ice_state == ICESTATE_FLAT && get_state() == STATE_ACTIVE) {
-    // hit from left side
-    if(hit.normal.x > 0.7) {
+    if(hit.left) {
       dir = RIGHT;
       player.kick();
       set_state(ICESTATE_KICKED);
       return FORCE_MOVE;
-    } else if(hit.normal.x < -0.7) {
+    } else if(hit.right) {
       dir = LEFT;
       player.kick();
       set_state(ICESTATE_KICKED);
@@ -162,7 +163,7 @@ MrIceBlock::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
 {
   switch(ice_state) {
     case ICESTATE_NORMAL:
-      if(fabsf(hit.normal.x) > .8) {
+      if(hit.left || hit.right) {
         dir = dir == LEFT ? RIGHT : LEFT;
         sprite->set_action(dir == LEFT ? "left" : "right");
         physic.set_velocity_x(-physic.get_velocity_x());               
index ea55065..01e693a 100644 (file)
@@ -32,7 +32,7 @@ public:
   void activate();
   void write(lisp::Writer& writer);
   HitResponse collision(GameObject& object, const CollisionHit& hit);
-  HitResponse collision_solid(GameObject& object, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
   HitResponse collision_player(Player& player, const CollisionHit& hit);
 
index cfa4faf..cbf5d31 100644 (file)
@@ -74,18 +74,16 @@ MrRocket::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-MrRocket::collision_solid(GameObject& , const CollisionHit& hit)
+void
+MrRocket::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // hit floor or roof?
+  if(hit.top || hit.bottom) {
     physic.set_velocity_y(0);
-  } else { // hit right or left
+  } else if(hit.left || hit.right) {
     sprite->set_action(dir == LEFT ? "collision-left" : "collision-right");
     physic.set_velocity_x(0);
     collision_timer.start(0.2, true);
   }
-
-  return CONTINUE;
 }
 
 IMPLEMENT_FACTORY(MrRocket, "mrrocket")
index f756d02..77a7634 100644 (file)
@@ -33,7 +33,7 @@ public:
   void activate();
   void active_update(float elapsed_time);
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
 
   virtual MrRocket* clone() const { return new MrRocket(*this); }
 
index 14062c2..9c4a0fa 100644 (file)
@@ -171,27 +171,24 @@ MrTree::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-MrTree::collision_solid(GameObject& , const CollisionHit& hit)
+void
+MrTree::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) {
+  if(hit.top || hit.bottom) {
     physic.set_velocity_y(0);
   } else {
     dir = dir == LEFT ? RIGHT : LEFT;
     activate();
   }
-
-  return CONTINUE;
 }
 
 HitResponse
 MrTree::collision_badguy(BadGuy& , const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.x) > .8) { // left or right hit
+  if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     activate();
   }
-
   return CONTINUE;
 }
 
index 652a00e..02a433d 100644 (file)
@@ -30,7 +30,7 @@ public:
   void activate();
   void active_update(float elapsed_time);
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
 
   virtual MrTree* clone() const { return new MrTree(*this); }
diff --git a/src/badguy/nolok_01.cpp b/src/badguy/nolok_01.cpp
deleted file mode 100644 (file)
index b1e7c77..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-//  $Id$
-//
-//  SuperTux
-//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
-//
-//  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 2
-//  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, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-#include <config.h>
-
-#include "nolok_01.hpp"
-#include "badguy/snail.hpp"
-#include "trigger/door.hpp"
-
-#define WALK_TIME 2.5
-#define SHOOT_TIME 0.4
-#define JUMP_TIME 0.5
-#define INITIAL_HITPOINTS 3
-#define INITIAL_BULLET_HP 10
-
-static const float WALKSPEED = 90;
-
-//TODO: Create sprite, limit max number of snowballs
-Nolok_01::Nolok_01(const lisp::Lisp& reader)
-       : BadGuy(reader, "images/creatures/nolok/nolok.sprite")
-{
-  countMe = false;
-}
-
-Nolok_01::Nolok_01(const Vector& pos)
-       : BadGuy(pos, "images/creatures/nolok/nolok.sprite")
-{
-  countMe = false;
-}
-
-void
-Nolok_01::write(lisp::Writer& writer)
-{
-  writer.start_list("nolok_01");
-
-  writer.write_float("x", start_position.x);
-  writer.write_float("y", start_position.y);
-
-  writer.end_list("nolok_01");
-}
-
-void
-Nolok_01::activate()
-{
-  //hitpoints = INITIAL_HITPOINTS;
-  //bullet_hitpoints = INITIAL_BULLET_HP;
-  physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
-  sprite->set_action(dir == LEFT ? "left" : "right");
-  action = WALKING;
-  action_timer.start(WALK_TIME);
-}
-
-void
-Nolok_01::active_update(float elapsed_time)
-{
-   if (action_timer.check()) {
-     switch (action) {       
-       case WALKING:
-        {
-         sprite->set_action("jump");
-         physic.set_velocity_y(-700);
-         action = JUMPING;
-         action_timer.start(JUMP_TIME);
-         break;
-        }
-       case JUMPING:
-       {
-        sprite->set_action("throw");
-        action = SHOOTING;
-        action_timer.start(SHOOT_TIME);
-        break;
-       }
-       case SHOOTING:
-       {
-        Sector::current()->add_object(new Snail(Vector(get_pos().x - 64, get_pos().y), LEFT));
-        Sector::current()->add_object(new Snail(Vector(get_pos().x + 64, get_pos().y), RIGHT));
-        physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
-        sprite->set_action(dir == LEFT ? "left" : "right");
-        action = WALKING;
-        action_timer.start(WALK_TIME);
-        break;
-       }
-     }
-   }
-   movement = physic.get_movement(elapsed_time);
-}
-
-bool
-Nolok_01::collision_squished(Player& player)
-{
-  bool result = false;
-  player.bounce(*this);
-#if 0
-  if (hitpoints <= 0) {
-    bullet_hitpoints = 0;
-    sprite->set_action("dead"); 
-    kill_squished(player);
-    Sector::current()->add_object(new Door((int)get_pos().x+32, 512, "sector1", "main2"));
-    result = true;
-  }
-#endif
-  return result;
-}
-
-HitResponse
-Nolok_01::collision_solid(GameObject& , const CollisionHit& hit)
-{
-  if(fabsf(hit.normal.y) > .5){ // hit floor or roof?
-    if (action != JUMPING) physic.set_velocity_y(0);
-  } else { // hit right or left
-    dir = dir == LEFT ? RIGHT : LEFT;
-    sprite->set_action(dir == LEFT ? "left" : "right");
-    physic.set_velocity_x(-physic.get_velocity_x());
-  }
-
-  return CONTINUE;
-}
-
-//TODO: Hitpoint count incorrect when combining squishing and shooting
-void
-Nolok_01::kill_fall()
-{
-#if 0
-  bullet_hitpoints--;
-  if (bullet_hitpoints <= 0) {
-   hitpoints = 0;
-   sound_manager->play("sounds/fall.wav", this,
-                             this->get_pos());
-   physic.set_velocity_y(0);
-   physic.enable_gravity(true);
-   set_state(STATE_FALLING);
-   Sector::current()->add_object(new Door((int)get_pos().x+32, 512, "sector1", "main2"));
-  }
-#endif
-}
-
-IMPLEMENT_FACTORY(Nolok_01, "nolok_01")
diff --git a/src/badguy/nolok_01.hpp b/src/badguy/nolok_01.hpp
deleted file mode 100644 (file)
index 460d05e..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-//  $Id$
-//
-//  SuperTux
-//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
-//
-//  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 2
-//  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, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-#ifndef __NOLOK01_H__
-#define __NOLOK01_H__
-
-#include "badguy.hpp"
-#include "timer.hpp"
-
-class Nolok_01 : public BadGuy
-{
-public:
-  Nolok_01(const lisp::Lisp& reader);
-  Nolok_01(const Vector& pos);
-
-  void activate();
-  void write(lisp::Writer& writer);
-  void active_update(float elapsed_time);
-  void kill_fall();
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
-  virtual Nolok_01* clone() const { return new Nolok_01(*this); }
-
-protected:
-  bool collision_squished(Player& player);
-  Timer action_timer;
-  enum Actions { WALKING, JUMPING, SHOOTING };
-  Actions action;
-};
-
-#endif
-
index d452008..91cb1c9 100644 (file)
@@ -52,18 +52,16 @@ Plant::activate()
   sprite->set_action(dir == LEFT ? "sleeping-left" : "sleeping-right");
 }
 
-HitResponse
-Plant::collision_solid(GameObject& , const CollisionHit& hit)
+void
+Plant::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // hit floor or roof?
+  if(hit.top || hit.bottom) {
     physic.set_velocity_y(0);
-  } else { // hit right or left
+  } else if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
   }
-
-  return CONTINUE;
 }
 
 HitResponse
@@ -71,7 +69,7 @@ Plant::collision_badguy(BadGuy& , const CollisionHit& hit)
 {
   if(state != PLANT_WALKING) return CONTINUE;
 
-  if(fabsf(hit.normal.x) > .8) { // left or right
+  if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
index ab0dfd5..75d77e3 100644 (file)
@@ -29,7 +29,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
   void active_update(float elapsed_time);
 
index ae11827..34d4ed8 100644 (file)
@@ -73,24 +73,22 @@ PoisonIvy::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-PoisonIvy::collision_solid(GameObject& , const CollisionHit& hit)
+void
+PoisonIvy::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // hit floor or roof?
+  if(hit.top || hit.bottom) {
     physic.set_velocity_y(0);
-  } else { // hit right or left
+  } else if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
   }
-
-  return CONTINUE;
 }
 
 HitResponse
 PoisonIvy::collision_badguy(BadGuy& , const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.x) > .8) { // left or right hit
+  if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());       
index 09b6af6..fd77d05 100644 (file)
@@ -30,7 +30,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& other, const CollisionHit& hit);
  
   virtual PoisonIvy* clone() const { return new PoisonIvy(*this); }
index a1497ee..4e0520c 100644 (file)
@@ -37,15 +37,6 @@ RocketExplosion::write(lisp::Writer& )
 }
 
 HitResponse
-RocketExplosion::collision_solid(GameObject& , const CollisionHit& hit)
-{
-  if(fabsf(hit.normal.y) > .5)
-    physic.set_velocity_y(0);
-
-  return CONTINUE;
-}
-
-HitResponse
 RocketExplosion::collision_player(Player& player, const CollisionHit& )
 {
   player.kill(false);
index c76a6b8..ef09d17 100644 (file)
@@ -28,7 +28,6 @@ public:
   RocketExplosion(const Vector& pos, Direction dir);
 
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, 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);
index a5ba2ca..d9b954e 100644 (file)
@@ -87,37 +87,37 @@ SkullyHop::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-SkullyHop::collision_solid(GameObject& , const CollisionHit& hit)
+void
+SkullyHop::collision_solid(const CollisionHit& hit)
 {
   // ignore collisions while standing still
-  if(state != JUMPING) return CONTINUE;
+  if(state != JUMPING)
+    return;
 
   // check if we hit the floor while falling
-  if ((hit.normal.y < 0) && (physic.get_velocity_y() > 0)) {
+  if(hit.bottom) {
     set_state(STANDING);
   }
-
   // check if we hit the roof while climbing
-  if ((hit.normal.y > 0) && (physic.get_velocity_y() < 0)) { 
+  if(hit.top) { 
     physic.set_velocity_y(0);
   }
 
   // check if we hit left or right while moving in either direction
-  if ((hit.normal.x != 0) && (physic.get_velocity_x() != 0)) {
+  if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "jumping-left" : "jumping-right");
     physic.set_velocity_x(-0.25*physic.get_velocity_x());
   }
-
-  return CONTINUE;
 }
 
 HitResponse
-SkullyHop::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
+SkullyHop::collision_badguy(BadGuy& , const CollisionHit& hit)
 {
   // behaviour for badguy collisions is the same as for collisions with solids
-  return collision_solid(badguy, hit);
+  collision_solid(hit);
+
+  return CONTINUE;
 }
 
 void
index c12962c..805cf35 100644 (file)
@@ -34,7 +34,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
   bool collision_squished(Player& player);
   void active_update(float elapsed_time);
index 6f1e1e9..5df4e0e 100644 (file)
@@ -138,10 +138,10 @@ Snail::active_update(float elapsed_time)
   BadGuy::active_update(elapsed_time);
 }
 
-HitResponse
-Snail::collision_solid(GameObject& object, const CollisionHit& hit)
+void
+Snail::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // floor or roof
+  if(hit.top || hit.bottom) { // floor or roof
     physic.set_velocity_y(0);
 
     switch (state) {
@@ -153,7 +153,7 @@ Snail::collision_solid(GameObject& object, const CollisionHit& hit)
        break;
     }
 
-    return CONTINUE;
+    return;
   }
   // hit left or right
   switch(state) {
@@ -171,7 +171,9 @@ Snail::collision_solid(GameObject& object, const CollisionHit& hit)
 
     case STATE_KICKED: {
       sound_manager->play("sounds/iceblock_bump.wav", get_pos());
-     
+    
+#if 0
+      // TODO move this into BonusBlock code
       // open bonusblocks, crash bricks
       BonusBlock* bonusblock = dynamic_cast<BonusBlock*> (&object);
       if(bonusblock) {
@@ -181,6 +183,7 @@ Snail::collision_solid(GameObject& object, const CollisionHit& hit)
       if(brick) {
         brick->try_break();
       }
+#endif
       
       dir = (dir == LEFT) ? RIGHT : LEFT;
       sprite->set_action(dir == LEFT ? "flat-left" : "flat-right");
@@ -191,8 +194,6 @@ Snail::collision_solid(GameObject& object, const CollisionHit& hit)
 
     }
   }
-
-  return CONTINUE;
 }
 
 HitResponse
@@ -200,7 +201,7 @@ Snail::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
 {
   switch(state) {
     case STATE_NORMAL:
-      if(fabsf(hit.normal.x) > .5) {
+      if(hit.left || hit.right) {
         dir = (dir == LEFT) ? RIGHT : LEFT;
         sprite->set_action(dir == LEFT ? "left" : "right");
         physic.set_velocity_x(-physic.get_velocity_x());               
index 5d259f0..35802b0 100644 (file)
@@ -33,7 +33,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& object, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
 
   void active_update(float elapsed_time);
index 889578e..57db13a 100644 (file)
 static const float WALKSPEED = 80;
 
 SnowBall::SnowBall(const lisp::Lisp& reader)
-       : BadGuy(reader, "images/creatures/snowball/snowball.sprite")
+    : BadGuy(reader, "images/creatures/snowball/snowball.sprite")
 {
 }
 
 SnowBall::SnowBall(const Vector& pos, Direction d)
-       : BadGuy(pos, d, "images/creatures/snowball/snowball.sprite")
+    : BadGuy(pos, d, "images/creatures/snowball/snowball.sprite")
 {
 }
 
@@ -37,14 +37,8 @@ void
 SnowBall::write(lisp::Writer& writer)
 {
   writer.start_list("snowball");
-
   writer.write_float("x", start_position.x);
   writer.write_float("y", start_position.y);
-  /*
-  if (fluffy) {  // don't give us away at every snowball
-    writer.write_bool("fluffy", true);
-  }
-  */
   writer.end_list("snowball");
 }
 
@@ -63,24 +57,26 @@ SnowBall::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-SnowBall::collision_solid(GameObject& , const CollisionHit& hit)
+void
+SnowBall::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // hit floor or roof?
+  if(hit.top || hit.bottom) {
     physic.set_velocity_y(0);
-  } else { // hit right or left
+  }
+  if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
   }
-
-  return CONTINUE;
 }
 
 HitResponse
 SnowBall::collision_badguy(BadGuy& , const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.x) > .8) { // left or right hit
+  if(hit.top || hit.bottom) {
+    physic.set_velocity_y(0);
+  }
+  if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());       
index 49bfa9f..e7387ef 100644 (file)
@@ -30,7 +30,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& other, const CollisionHit& hit);
  
   virtual SnowBall* clone() const { return new SnowBall(*this); }
index 41ccb2e..70feda7 100644 (file)
@@ -65,14 +65,12 @@ SpiderMite::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-SpiderMite::collision_solid(GameObject& , const CollisionHit& hit)
+void
+SpiderMite::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > 1.5) { // hit floor or roof?
+  if(hit.top || hit.bottom) { // hit floor or roof?
     physic.set_velocity_y(0);
   }
-
-  return CONTINUE;
 }
 
 void
index 5c1bd5e..84f313d 100644 (file)
@@ -31,7 +31,7 @@ public:
   void activate();
   void write(lisp::Writer& writer);
   void active_update(float elapsed_time);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
 
   virtual SpiderMite* clone() const { return new SpiderMite(*this); }
 
index fbe27ee..befbd05 100644 (file)
@@ -59,24 +59,22 @@ Spiky::active_update(float elapsed_time)
   }
 }
 
-HitResponse
-Spiky::collision_solid(GameObject& , const CollisionHit& hit)
+void
+Spiky::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // hit floor or roof?
+  if(hit.top || hit.bottom) { // hit floor or roof?
     physic.set_velocity_y(0);
   } else { // hit right or left
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
   }
-
-  return CONTINUE;
 }
 
 HitResponse
 Spiky::collision_badguy(BadGuy& , const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.x) > .8) { // left or right
+  if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
index fd86096..c0e448e 100644 (file)
@@ -30,7 +30,7 @@ public:
   void activate();
   void write(lisp::Writer& writer);
   void active_update(float elapsed_time);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
 
   virtual Spiky* clone() const { return new Spiky(*this); }
index 3827ae2..2999535 100644 (file)
@@ -48,28 +48,25 @@ SSpiky::activate()
   sprite->set_action(dir == LEFT ? "sleeping-left" : "sleeping-right");
 }
 
-
-
-HitResponse
-SSpiky::collision_solid(GameObject& , const CollisionHit& hit)
+void
+SSpiky::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { // hit floor or roof?
+  if(hit.top || hit.bottom) { // hit floor or roof?
     physic.set_velocity_y(0);
   } else { // hit right or left
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
   }
-
-  return CONTINUE;
 }
 
 HitResponse
 SSpiky::collision_badguy(BadGuy& , const CollisionHit& hit)
 {
-  if(state != SSPIKY_WALKING) return CONTINUE;
+  if(state != SSPIKY_WALKING)
+    return CONTINUE;
 
-  if(fabsf(hit.normal.x) > .8) { // left or right
+  if(hit.left || hit.right) {
     dir = dir == LEFT ? RIGHT : LEFT;
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(-physic.get_velocity_x());
index bb77419..81322f7 100644 (file)
@@ -29,7 +29,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
   void active_update(float elapsed_time);
 
index f53a944..289135b 100644 (file)
@@ -68,13 +68,13 @@ Stalactite::active_update(float elapsed_time)
   }
 }
 
-HitResponse
-Stalactite::collision_solid(GameObject& , const CollisionHit& hit)
+void
+Stalactite::collision_solid(const CollisionHit& hit)
 {
   if(state != STALACTITE_FALLING && state != STALACTITE_SQUISHED)
-    return FORCE_MOVE;
+    return;
   
-  if(hit.normal.y < .9) { // hit floor?
+  if(hit.bottom) { // hit floor?
     state = STALACTITE_SQUISHED;
     set_group(COLGROUP_MOVING_ONLY_STATIC);
     physic.set_velocity_y(0);
@@ -82,12 +82,10 @@ Stalactite::collision_solid(GameObject& , const CollisionHit& hit)
     if(!timer.started())
       timer.start(SQUISH_TIME);
   }
-
-  return CONTINUE;
 }
 
 HitResponse
-Stalactite::collision_player(Player& player, const CollisionHit& )
+Stalactite::collision_player(Player& player)
 {
   if(state != STALACTITE_SQUISHED) {
     player.kill(false);
index 9619f61..74803c2 100644 (file)
@@ -29,8 +29,8 @@ public:
  
   void active_update(float elapsed_time);
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
-  HitResponse collision_player(Player& player, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
+  HitResponse collision_player(Player& player);
 
   void kill_fall();
   void draw(DrawingContext& context);
index 825ed81..2ee60f1 100644 (file)
@@ -151,31 +151,29 @@ Totem::collision_squished(Player& player)
   return true;
 }
 
-HitResponse
-Totem::collision_solid(GameObject& object, const CollisionHit& hit)
+void
+Totem::collision_solid(const CollisionHit& hit)
 {
   // if we are being carried around, pass event to bottom of stack and ignore it
   if (carried_by) {
-    carried_by->collision_solid(object, hit);
-    return CONTINUE;
+    carried_by->collision_solid(hit);
+    return;
   }
 
   // If we hit something from above or below: stop moving in this direction 
-  if (hit.normal.y != 0) {
+  if (hit.top || hit.bottom) {
     physic.set_velocity_y(0);
   }
 
   // If we are hit from the direction we are facing: turn around
-  if ((hit.normal.x > .8) && (dir == LEFT)) {
+  if (hit.left && (dir == LEFT)) {
     dir = RIGHT;
     activate();
   }
-  if ((hit.normal.x < -.8) && (dir == RIGHT)) {
+  if (hit.right && (dir == RIGHT)) {
     dir = LEFT;
     activate();
   }
-
-  return CONTINUE;
 }
 
 HitResponse
@@ -199,11 +197,11 @@ Totem::collision_badguy(BadGuy& badguy, const CollisionHit& hit)
   }
 
   // If we are hit from the direction we are facing: turn around
-  if ((hit.normal.x > .8) && (dir == LEFT)) {
+  if(hit.left && (dir == LEFT)) {
     dir = RIGHT;
     activate();
   }
-  if ((hit.normal.x < -.8) && (dir == RIGHT)) {
+  if(hit.right && (dir == RIGHT)) {
     dir = LEFT;
     activate();
   }
index 8742025..044c000 100644 (file)
@@ -36,7 +36,7 @@ public:
   void activate();
   void active_update(float elapsed_time);
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
 
   virtual Totem* clone() const { return new Totem(*this); }
index 8528e82..909fbe2 100644 (file)
@@ -262,10 +262,10 @@ Yeti::drop_stalactite()
     nearest->start_shaking();
 }
 
-HitResponse
-Yeti::collision_solid(GameObject& , const CollisionHit& hit)
+void
+Yeti::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) { 
+  if(hit.top || hit.bottom) { 
     // hit floor or roof
     physic.set_velocity_y(0);
     switch (state) {
@@ -295,13 +295,10 @@ Yeti::collision_solid(GameObject& , const CollisionHit& hit)
       case SQUISHED:
         break;
     }
-  } else 
-  if(fabsf(hit.normal.x) > .5) {
+  } else if(hit.left || hit.right) {
     // hit wall
     jump_up();
   }
-
-  return CONTINUE;
 }
 
 IMPLEMENT_FACTORY(Yeti, "yeti")
index 30a6744..74d8b19 100644 (file)
@@ -33,7 +33,7 @@ public:
   void write(lisp::Writer& writer);
   void activate();
   void active_update(float elapsed_time);
-  HitResponse collision_solid(GameObject& object, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   bool collision_squished(Player& player);
   void kill_squished(Player& player);
   void kill_fall();
index 3d3a539..4d78943 100644 (file)
@@ -84,6 +84,8 @@ Zeekling::onBumpHorizontal() {
     dir = (dir == LEFT ? RIGHT : LEFT);
     sprite->set_action(dir == LEFT ? "left" : "right");
     physic.set_velocity_x(dir == LEFT ? -speed : speed);
+  } else {
+    assert(false);
   }
 }
 
@@ -103,16 +105,14 @@ Zeekling::onBumpVertical() {
   }
 }
 
-HitResponse
-Zeekling::collision_solid(GameObject& , const CollisionHit& hit)
+void
+Zeekling::collision_solid(const CollisionHit& hit)
 {
-  if(fabsf(hit.normal.y) > .5) {
+  if(hit.top || hit.bottom) {
     onBumpVertical(); 
-  } else {
+  } else if(hit.left || hit.right) {
     onBumpHorizontal();
   }
-
-  return CONTINUE;
 }
 
 /**
@@ -159,30 +159,28 @@ Zeekling::should_we_dive() {
 
 void 
 Zeekling::active_update(float elapsed_time) {
-  BadGuy::active_update(elapsed_time);
-
   if (state == FLYING) {
     if (should_we_dive()) {
       state = DIVING;
       physic.set_velocity_y(2*fabsf(physic.get_velocity_x()));
       sprite->set_action(dir == LEFT ? "diving-left" : "diving-right");
     }
+    BadGuy::active_update(elapsed_time);
     return;
-  }
-
-  if (state == DIVING) {
+  } else if (state == DIVING) {
+    BadGuy::active_update(elapsed_time);
     return;
-  }
-
-  if (state == CLIMBING) {
+  } else if (state == CLIMBING) {
     // stop climbing when we're back at initial height
     if (get_pos().y <= start_position.y) {
       state = FLYING;
       physic.set_velocity_y(0);
     }
+    BadGuy::active_update(elapsed_time);
     return;
+  } else {
+    assert(false);
   }
-
 }
 
 IMPLEMENT_FACTORY(Zeekling, "zeekling")
index fd6b519..1784237 100644 (file)
@@ -32,7 +32,7 @@ public:
 
   void activate();
   void write(lisp::Writer& writer);
-  HitResponse collision_solid(GameObject& other, const CollisionHit& hit);
+  void collision_solid(const CollisionHit& hit);
   void active_update(float elapsed_time);
 
   virtual Zeekling* clone() const { return new Zeekling(*this); }
index bc38f83..8ae5e91 100644 (file)
 #include "math/aatriangle.hpp"
 #include "math/rect.hpp"
 #include "collision_hit.hpp"
+#include "log.hpp"
 
-static const float DELTA = .0001;
-
-bool
-Collision::intersects(const Rect& r1, const Rect& r2)
+namespace collision
 {
-  if(r1.p2.x < r2.p1.x || r1.p1.x > r2.p2.x)
-    return false;
-  if(r1.p2.y < r2.p1.y || r1.p1.y > r2.p2.y)
-    return false;
 
-  return true;
-}
-
-bool
-Collision::rectangle_rectangle(CollisionHit& hit, const Rect& r1,
-    const Vector& movement, const Rect& r2)
+bool intersects(const Rect& r1, const Rect& r2)
 {
   if(r1.p2.x < r2.p1.x || r1.p1.x > r2.p2.x)
     return false;
   if(r1.p2.y < r2.p1.y || r1.p1.y > r2.p2.y)
     return false;
 
-  if(movement.x > DELTA) {
-    hit.depth = r1.p2.x - r2.p1.x;
-    hit.time = hit.depth / movement.x;
-    hit.normal.x = -1;
-    hit.normal.y = 0;
-  } else if(movement.x < -DELTA) {
-    hit.depth = r2.p2.x - r1.p1.x;
-    hit.time = hit.depth / -movement.x;
-    hit.normal.x = 1;
-    hit.normal.y = 0;
-  } else {
-    if(movement.y > -DELTA && movement.y < DELTA) {
-      hit.time = 0;
-      hit.depth = 0;
-      hit.normal.x = 1;
-      hit.normal.y = 0;
-      return true;
-    }
-    hit.time = FLT_MAX;
-  }
-
-  if(movement.y > DELTA) {
-    float ydepth = r1.p2.y - r2.p1.y;
-    float yt = ydepth / movement.y;
-    if(yt < hit.time) {
-      hit.depth = ydepth;
-      hit.time = yt;
-      hit.normal.x = 0;
-      hit.normal.y = -1;
-    }
-  } else if(movement.y < -DELTA) {
-    float ydepth = r2.p2.y - r1.p1.y;
-    float yt = ydepth / -movement.y;
-    if(yt < hit.time) {
-      hit.depth = ydepth;
-      hit.time = yt;
-      hit.normal.x = 0;
-      hit.normal.y = 1;
-    }
-  }
-
   return true;
 }
 
 //---------------------------------------------------------------------------
 
-static void makePlane(const Vector& p1, const Vector& p2, Vector& n, float& c)
-{
-  n = Vector(p2.y-p1.y, p1.x-p2.x);
-  c = -(p2 * n);
-  float nval = n.norm();             
-  n /= nval;
-  c /= nval;
+namespace {
+  inline void makePlane(const Vector& p1, const Vector& p2, Vector& n, float& c)
+  {
+    n = Vector(p2.y-p1.y, p1.x-p2.x);
+    c = -(p2 * n);
+    float nval = n.norm();             
+    n /= nval;
+    c /= nval;
+  }
+
+  static const float DELTA = .0001;
 }
 
-bool
-Collision::rectangle_aatriangle(CollisionHit& hit, const Rect& rect,
-    const Vector& movement, const AATriangle& triangle)
+bool rectangle_aatriangle(Constraints* constraints, const Rect& rect,
+    const AATriangle& triangle)
 {
-  if(!rectangle_rectangle(hit, rect, movement, (const Rect&) triangle))
+  if(!intersects(rect, (const Rect&) triangle))
     return false;
 
   Vector normal;
   float c;
   Vector p1;
-  Vector tp1, tp2;
+  Rect area;
   switch(triangle.dir & AATriangle::DEFORM_MASK) {
     case 0:
-      tp1 = triangle.p1;
-      tp2 = triangle.p2;
+      area.p1 = triangle.p1;
+      area.p2 = triangle.p2;
       break;
     case AATriangle::DEFORM1:
-      tp1 = Vector(triangle.p1.x, triangle.p1.y + triangle.get_height()/2);
-      tp2 = triangle.p2;
+      area.p1 = Vector(triangle.p1.x, triangle.p1.y + triangle.get_height()/2);
+      area.p2 = triangle.p2;
       break;
     case AATriangle::DEFORM2:
-      tp1 = triangle.p1;
-      tp2 = Vector(triangle.p2.x, triangle.p1.y + triangle.get_height()/2);
+      area.p1 = triangle.p1;
+      area.p2 = Vector(triangle.p2.x, triangle.p1.y + triangle.get_height()/2);
       break;
     case AATriangle::DEFORM3:
-      tp1 = triangle.p1;
-      tp2 = Vector(triangle.p1.x + triangle.get_width()/2, triangle.p2.y);
+      area.p1 = triangle.p1;
+      area.p2 = Vector(triangle.p1.x + triangle.get_width()/2, triangle.p2.y);
       break;
     case AATriangle::DEFORM4:
-      tp1 = Vector(triangle.p1.x + triangle.get_width()/2, triangle.p1.y);
-      tp2 = triangle.p2;
+      area.p1 = Vector(triangle.p1.x + triangle.get_width()/2, triangle.p1.y);
+      area.p2 = triangle.p2;
       break;
     default:
       assert(false);
@@ -147,21 +98,21 @@ Collision::rectangle_aatriangle(CollisionHit& hit, const Rect& rect,
   switch(triangle.dir & AATriangle::DIRECTION_MASK) {
     case AATriangle::SOUTHWEST:
       p1 = Vector(rect.p1.x, rect.p2.y);
-      makePlane(tp1, tp2, normal, c);
+      makePlane(area.p1, area.p2, normal, c);
       break;
     case AATriangle::NORTHEAST:
       p1 = Vector(rect.p2.x, rect.p1.y);
-      makePlane(tp2, tp1, normal, c);
+      makePlane(area.p2, area.p1, normal, c);
       break;
     case AATriangle::SOUTHEAST:
       p1 = rect.p2;
-      makePlane(Vector(tp1.x, tp2.y),
-          Vector(tp2.x, tp1.y), normal, c);
+      makePlane(Vector(area.p1.x, area.p2.y),
+          Vector(area.p2.x, area.p1.y), normal, c);
       break;
     case AATriangle::NORTHWEST:
       p1 = rect.p1;
-      makePlane(Vector(tp2.x, tp1.y),
-          Vector(tp1.x, tp2.y), normal, c);
+      makePlane(Vector(area.p2.x, area.p1.y),
+          Vector(area.p1.x, area.p2.y), normal, c);
       break;
     default:
       assert(false);
@@ -171,13 +122,67 @@ Collision::rectangle_aatriangle(CollisionHit& hit, const Rect& rect,
   float depth = n_p1 - c;
   if(depth < 0)
     return false;
-  float time = depth / -(normal * movement);
-  if(time < hit.time) {
-    hit.depth = depth;
-    hit.time = time;
-    hit.normal = normal;
-  }
 
+#if 0
+  std::cout << "R: " << rect << " Tri: " << triangle << "\n";
+  std::cout << "Norm: " << normal << " Depth: " << depth << "\n";
+#endif
+
+  Vector outvec = normal * (depth + 0.2);
+
+  const float RDELTA = 3;
+  if(p1.x < area.p1.x - RDELTA || p1.x > area.p2.x + RDELTA
+        || p1.y < area.p1.y - RDELTA || p1.y > area.p2.y + RDELTA) {
+    set_rectangle_rectangle_constraints(constraints, rect, area);
+    constraints->hit.left = false;
+    constraints->hit.right = false;
+  } else {
+    if(outvec.x < 0) {
+      constraints->right = rect.get_right() + outvec.x;
+    } else {
+      constraints->left = rect.get_left() + outvec.x;
+    }
+
+    if(outvec.y < 0) {
+      constraints->bottom = rect.get_bottom() + outvec.y;
+      constraints->hit.bottom = true;
+    } else {
+      constraints->top = rect.get_top() + outvec.y;
+      constraints->hit.top = true;
+    }
+    constraints->hit.slope_normal = normal;
+  }
+  
   return true;
 }
 
+void set_rectangle_rectangle_constraints(Constraints* constraints,
+        const Rect& r1, const Rect& r2)
+{
+  float itop = r1.get_bottom() - r2.get_top();
+  float ibottom = r2.get_bottom() - r1.get_top();
+  float ileft = r1.get_right() - r2.get_left();
+  float iright = r2.get_right() - r1.get_left();
+
+  float vert_penetration = std::min(itop, ibottom);
+  float horiz_penetration = std::min(ileft, iright);
+  if(vert_penetration < horiz_penetration) {
+    if(itop < ibottom) {
+      constraints->bottom = std::min(constraints->bottom, r2.get_top());
+      constraints->hit.bottom = true;
+    } else {
+      constraints->top = std::max(constraints->top, r2.get_bottom());
+      constraints->hit.top = true;
+    }
+  } else {
+    if(ileft < iright) {
+      constraints->right = std::min(constraints->right, r2.get_left());
+      constraints->hit.right = true;
+    } else {
+      constraints->left = std::max(constraints->left, r2.get_right());
+      constraints->hit.left = true;
+    }
+  }
+}
+
+}
index 62f2145..cc5bcd0 100644 (file)
 #ifndef __COLLISION_H__
 #define __COLLISION_H__
 
+#include <float.h>
+#include "collision_hit.hpp"
+
 class Vector;
 class Rect;
 class AATriangle;
-class CollisionHit;
 
-class Collision
+namespace collision
+{
+
+class Constraints
 {
 public:
-  /** checks if 2 rectangle intersect each other */
-  static bool intersects(const Rect& r1, const Rect& r2);
-  
-  /** does collision detection between 2 rectangles. Returns true in case of
-   * collision and fills in the hit structure then.
-   */
-  static bool rectangle_rectangle(CollisionHit& hit, const Rect& r1,
-      const Vector& movement, const Rect& r2);
-
-  /** does collision detection between a rectangle and an axis aligned triangle
-   * Returns true in case of a collision and fills in the hit structure then.
-   */                                                                         
-  static bool rectangle_aatriangle(CollisionHit& hit, const Rect& rect,
-      const Vector& movement, const AATriangle& triangle);
+  Constraints() {
+    left = -INFINITY;
+    right = INFINITY;
+    top = -INFINITY;
+    bottom = INFINITY;
+  }
+
+  bool has_constraints() const {
+    return left > -INFINITY || right < INFINITY
+        || top > -INFINITY || bottom < INFINITY;
+  }
+
+  float left;
+  float right;
+  float top;
+  float bottom;
+  Vector ground_movement;
+  CollisionHit hit;
 };
 
+/** checks if 2 rectangle intersect each other */
+bool intersects(const Rect& r1, const Rect& r2);
+  
+/** does collision detection between a rectangle and an axis aligned triangle
+ * Returns true in case of a collision and fills in the hit structure then.
+ */                                                                         
+bool rectangle_aatriangle(Constraints* constraints, const Rect& rect,
+                                   const AATriangle& triangle);
+
+void set_rectangle_rectangle_constraints(Constraints* constraints,
+        const Rect& r1, const Rect& r2);
+
+}
+
 #endif
 
diff --git a/src/collision_grid.cpp b/src/collision_grid.cpp
deleted file mode 100644 (file)
index e53d18a..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-//  $Id$
-//
-//  SuperTux
-//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
-//
-//  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 2
-//  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, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-#include <config.h>
-
-#include <iostream>
-#include "collision_grid.hpp"
-#include "log.hpp"
-#include "collision.hpp"
-#include "sector.hpp"
-#include "collision_grid_iterator.hpp"
-
-static const float DELTA = .001;
-
-CollisionGrid::CollisionGrid(float newwidth, float newheight)
-  : width(newwidth), height(newheight), cell_width(128), cell_height(128),
-    iterator_timestamp(0)
-{
-  cells_x = size_t(width / cell_width) + 1;
-  cells_y = size_t(height / cell_height) + 1;
-  grid.resize(cells_x * cells_y);
-}
-
-CollisionGrid::~CollisionGrid()
-{
-  for(GridEntries::iterator i = grid.begin(); i != grid.end(); ++i) {
-    GridEntry* entry = *i;
-    while(entry) {
-      GridEntry* nextentry = entry->next;
-      delete entry;
-      entry = nextentry;
-    }
-  }
-}
-
-void
-CollisionGrid::add_object(MovingObject* object)
-{
-#ifdef DEBUG
-  // make sure the object isn't already in the grid
-  for(Objects::iterator i = objects.begin(); i != objects.end(); ++i) {
-    ObjectWrapper* wrapper = *i;
-    if(wrapper->object == object)
-      assert(false);
-  }
-  assert(object != 0);
-#endif
-  
-  ObjectWrapper* wrapper = new ObjectWrapper;
-  wrapper->object = object;
-  wrapper->timestamp = 0;
-  wrapper->dest = object->bbox;
-  objects.push_back(wrapper);
-  wrapper->id = objects.size()-1;
-  
-  const Rect& bbox = object->bbox;
-  for(float y = bbox.p1.y; y < bbox.p2.y; y += cell_height) {
-    for(float x = bbox.p1.x; x < bbox.p2.x; x += cell_width) {
-      int gridx = int(x / cell_width);
-      int gridy = int(y / cell_height);
-      if(gridx < 0 || gridy < 0 
-          || gridx >= int(cells_x) || gridy >= int(cells_y)) {
-        log_warning << "Object out of range: " << gridx << ", " << gridy << std::endl;
-        continue;
-      }
-      GridEntry* entry = new GridEntry;
-      entry->object_wrapper = wrapper;
-      entry->next = grid[gridy*cells_x + gridx];
-      grid[gridy*cells_x + gridx] = entry;
-    }
-  }
-}
-
-void
-CollisionGrid::remove_object(MovingObject* object)
-{
-  ObjectWrapper* wrapper = 0;
-  for(Objects::iterator i = objects.begin(); i != objects.end(); ++i) {
-    if((*i)->object == object) {
-      wrapper = *i;
-      objects.erase(i);
-      break;
-    }
-  }
-#ifdef DEBUG
-  assert(wrapper != 0);
-#else
-  if(wrapper == 0) {
-    log_warning << "Tried to remove nonexistant object" << std::endl;
-    return;
-  }
-#endif
-  
-  const Rect& bbox = wrapper->dest;
-  for(float y = bbox.p1.y; y < bbox.p2.y; y += cell_height) {
-    for(float x = bbox.p1.x; x < bbox.p2.x; x += cell_width) {
-      int gridx = int(x / cell_width);
-      int gridy = int(y / cell_height);
-      if(gridx < 0 || gridy < 0 
-          || gridx >= int(cells_x) || gridy >= int(cells_y)) {
-        log_warning << "Object out of range: " << gridx << ", " << gridy << std::endl;
-        continue;
-      }
-      remove_object_from_gridcell(gridy*cells_x + gridx, wrapper);
-    }
-  }
-
-  delete wrapper;
-}
-
-void
-CollisionGrid::move_object(ObjectWrapper* wrapper)
-{
-  // FIXME not optimal yet... should leave the gridcells untouched that don't
-  // need to be changed.
-  const Rect& obbox = wrapper->dest;
-  for(float y = obbox.p1.y; y < obbox.p2.y; y += cell_height) {
-    for(float x = obbox.p1.x; x < obbox.p2.x; x += cell_width) {
-      int gridx = int(x / cell_width);
-      int gridy = int(y / cell_height);
-      if(gridx < 0 || gridy < 0  ||
-         gridx >= int(cells_x) || gridy >= int(cells_y)) {
-        log_warning << "Object out of range: " << gridx << ", " << gridy << std::endl;
-        continue;
-      }
-      remove_object_from_gridcell(gridy*cells_x + gridx, wrapper);
-    }
-  }
-
-  const Rect& nbbox = wrapper->object->bbox;
-  for(float y = nbbox.p1.y; y < nbbox.p2.y; y += cell_height) {
-    for(float x = nbbox.p1.x; x < nbbox.p2.x; x += cell_width) {
-      int gridx = int(x / cell_width);
-      int gridy = int(y / cell_height);
-      if(gridx < 0 || gridy < 0 
-          || gridx >= int(cells_x) || gridy >= int(cells_y)) {
-        log_warning << "Object out of range: " << gridx << ", " << gridy << std::endl;
-        continue;
-      }
-
-      GridEntry* entry = new GridEntry;
-      entry->object_wrapper = wrapper;
-      entry->next = grid[gridy*cells_x + gridx];
-      grid[gridy*cells_x + gridx] = entry;
-    }
-  }
-
-  wrapper->dest = nbbox;
-}
-
-void
-CollisionGrid::check_collisions()
-{
-  std::vector<ObjectWrapper*> moved_objects;
-#if 0
-  CollisionGridIterator iter(*this, Sector::current()->get_active_region());
-  while(ObjectWrapper* wrapper = iter.next_wrapper()) {
-    MovingObject* object = wrapper->object;
-    if(!object->is_valid())
-      continue;
-    if(object->get_group() == COLGROUP_DISABLED) {
-      object->bbox.move(object->movement);
-      object->movement = Vector(0, 0);
-      moved_objects.push_back(wrapper);
-      continue;
-    }
-
-    // hack for now...
-    Sector::current()->collision_tilemap(object, 0);
-    
-    collide_object(wrapper);
-
-    if(object->movement != Vector(0, 0)) {
-      object->bbox.move(object->movement);
-      object->movement = Vector(0, 0);
-      moved_objects.push_back(wrapper);
-    }
-  }
-#endif
-
-  for(std::vector<ObjectWrapper*>::iterator i = moved_objects.begin();
-      i != moved_objects.end(); ++i) {
-    move_object(*i);
-  }
-}
-
-void
-CollisionGrid::collide_object(ObjectWrapper* wrapper)
-{
-  iterator_timestamp++;
-
-  const Rect& bbox = wrapper->object->bbox;
-  for(float y = bbox.p1.y - cell_height; y < bbox.p2.y + cell_height; y += cell_height) {
-    for(float x = bbox.p1.x - cell_width; x < bbox.p2.x + cell_width; x += cell_width) {
-      int gridx = int(x / cell_width);
-      int gridy = int(y / cell_height);
-      if(gridx < 0 || gridy < 0 
-          || gridx >= int(cells_x) || gridy >= int(cells_y)) {
-        //log_warning << "Object out of range: " << gridx << ", " << gridy << std::endl;
-        continue;
-      }
-  
-      for(GridEntry* entry = grid[gridy*cells_x + gridx]; entry;
-          entry = entry->next) {
-        ObjectWrapper* wrapper2 = entry->object_wrapper;
-        // only check each object once (even if it is in multiple cells)
-        if(wrapper2->timestamp == iterator_timestamp)
-          continue;
-        // don't collide with objects we already collided with
-        if(wrapper2->id <= wrapper->id)
-          continue;
-
-        wrapper->timestamp = iterator_timestamp;
-        collide_object_object(wrapper, wrapper2);
-      }
-    }
-  }
-}
-
-void
-CollisionGrid::collide_object_object(ObjectWrapper* wrapper,
-    ObjectWrapper* wrapper2)
-{
-  CollisionHit hit;
-  MovingObject* object1 = wrapper->object;
-  MovingObject* object2 = wrapper2->object;
-  
-  Rect dest1 = object1->get_bbox();
-  dest1.move(object1->get_movement());
-  Rect dest2 = object2->get_bbox();
-  dest2.move(object2->get_movement());
-
-  Vector movement = object1->get_movement() - object2->get_movement();
-  if(Collision::rectangle_rectangle(hit, dest1, movement, dest2)) {
-    HitResponse response1 = object1->collision(*object2, hit);
-    hit.normal *= -1;
-    HitResponse response2 = object2->collision(*object1, hit);
-
-    if(response1 != CONTINUE) {
-      if(response1 == ABORT_MOVE)
-        object1->movement = Vector(0, 0);
-      if(response2 == CONTINUE)
-        object2->movement += hit.normal * (hit.depth + DELTA);
-    } else if(response2 != CONTINUE) {
-      if(response2 == ABORT_MOVE)
-        object2->movement = Vector(0, 0);
-      if(response1 == CONTINUE)
-        object1->movement += -hit.normal * (hit.depth + DELTA);
-    } else {
-      object1->movement += -hit.normal * (hit.depth/2 + DELTA);
-      object2->movement += hit.normal * (hit.depth/2 + DELTA);
-    }
-  }
-}
-
-void
-CollisionGrid::remove_object_from_gridcell(int gridcell, ObjectWrapper* wrapper)
-{
-  GridEntry* lastentry = 0;
-  GridEntry* entry = grid[gridcell];
-
-  while(entry) {
-    if(entry->object_wrapper == wrapper) {
-      if(lastentry == 0) {
-        grid[gridcell] = entry->next;
-      } else {
-        lastentry->next = entry->next;
-      }
-      delete entry;
-      return;
-    }
-
-    lastentry = entry;
-    entry = entry->next;
-  };
-
-  log_warning << "Couldn't find object in cell" << std::endl;
-}
-
diff --git a/src/collision_grid.hpp b/src/collision_grid.hpp
deleted file mode 100644 (file)
index 9820b0d..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-//  $Id$
-//
-//  SuperTux
-//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
-//
-//  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 2
-//  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, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-#ifndef __COLLISION_GRID_H__
-#define __COLLISION_GRID_H__
-
-#include <vector>
-#include "moving_object.hpp"
-
-class CollisionGridIterator;
-
-/**
- * A rectangular grid to keep track of all moving game objects. It allows fast
- * queries for all objects in a rectangular area.
- */
-class CollisionGrid
-{
-public:
-  CollisionGrid(float width, float height);
-  ~CollisionGrid();
-
-  void add_object(MovingObject* object);
-  void remove_object(MovingObject* object);
-
-  void check_collisions();
-
-private:
-  friend class CollisionGridIterator;
-  
-  struct ObjectWrapper
-  {
-    MovingObject* object;
-    Rect dest;
-    /** (pseudo) timestamp. When reading from the grid the timestamp is
-     * changed so that you can easily avoid reading an object multiple times
-     * when it is in several cells that you check.
-     */
-    int timestamp;
-    /// index in the objects vector
-    int id;
-  };
-  /** Element for the single linked list in each grid cell */
-  struct GridEntry
-  {
-    GridEntry* next;
-    ObjectWrapper* object_wrapper;
-  };
-
-  void remove_object_from_gridcell(int gridcell, ObjectWrapper* wrapper);
-  void collide_object(ObjectWrapper* wrapper);
-  void collide_object_object(ObjectWrapper* wrapper, ObjectWrapper* wrapper2);
-  void move_object(ObjectWrapper* wrapper);
-  
-  typedef std::vector<GridEntry*> GridEntries;
-  GridEntries grid;
-  typedef std::vector<ObjectWrapper*> Objects;
-  Objects objects;
-  size_t cells_x, cells_y;
-  float width;
-  float height;
-  float cell_width;
-  float cell_height;
-  int iterator_timestamp;
-};
-
-extern CollisionGrid* bla;
-
-#endif
-
diff --git a/src/collision_grid_iterator.hpp b/src/collision_grid_iterator.hpp
deleted file mode 100644 (file)
index c73a533..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-//  $Id$
-//
-//  SuperTux
-//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
-//
-//  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 2
-//  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, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-//  02111-1307, USA.
-#ifndef __COLLISION_GRID_ITERATOR_H__
-#define __COLLISION_GRID_ITERATOR_H__
-
-#include "math/rect.hpp"
-#include "log.hpp"
-
-class CollisionGrid;
-
-class CollisionGridIterator
-{
-public:
-  CollisionGridIterator(CollisionGrid& newgrid, const Rect& bbox)
-    : grid(newgrid)
-  {
-    start_x = int(bbox.p1.x / grid.cell_width) - 2;
-    if(start_x < 0)
-      start_x = 0;
-    x = start_x;
-        
-    y = int(bbox.p1.y / grid.cell_height) - 2;
-    if(y < 0)
-      y = 0;
-    
-    end_x = int(bbox.p2.x / grid.cell_width) + 2;
-    if(end_x > (int) grid.cells_x)
-      end_x = grid.cells_x;
-    
-    end_y = int(bbox.p2.y / grid.cell_height) + 2;
-    if(end_y > (int) grid.cells_y)
-      end_y = grid.cells_y;
-    
-    timestamp = grid.iterator_timestamp++;
-    entry = 0;
-
-    if(start_x >= end_x) {
-      log_debug << "bad region" << std::endl;
-      y = 0;
-      end_y = 0;
-      return;
-    }
-  }
-
-  MovingObject* next()
-  {
-    CollisionGrid::ObjectWrapper* wrapper = next_wrapper();
-    if(wrapper == 0)
-      return 0;
-        
-    return wrapper->object;
-  }
-
-private:
-  friend class CollisionGrid;
-
-  CollisionGrid::ObjectWrapper* next_wrapper() 
-  {
-    CollisionGrid::ObjectWrapper* wrapper;
-    
-    do {
-      while(entry == 0) {
-        if(y >= end_y)
-          return 0;
-        
-        entry = grid.grid[y*grid.cells_x + x];
-        x++;
-        if(x >= end_x) {
-          x = start_x;
-          y++;
-        }
-      }
-      
-      wrapper = entry->object_wrapper;
-      entry = entry->next;
-    } while(wrapper->timestamp == timestamp);
-    
-    wrapper->timestamp = timestamp;
-    
-    return wrapper;
-  }
-    
-  CollisionGrid& grid;
-  CollisionGrid::GridEntry* entry;
-  int x, y;
-  int start_x, end_x, end_y;
-  int timestamp;
-};
-
-#endif
-
index b9ed4d5..ba29e9f 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef SUPERTUX_COLLISION_HIT_H
 #define SUPERTUX_COLLISION_HIT_H
 
+#include <float.h>
+#include <math.h>
 #include "math/vector.hpp"
 
 /**
@@ -35,7 +37,12 @@ enum HitResponse
   /// do the move ignoring the collision
   FORCE_MOVE,
   /// passes movement to collided object
-  PASS_MOVEMENT
+  PASS_MOVEMENT,
+
+  /// the object should not appear solid
+  PASSTHROUGH,
+  /// the object should appear solid
+  SOLID,
 };
 
 /**
@@ -44,12 +51,19 @@ enum HitResponse
 class CollisionHit
 {
 public:
-  /// penetration depth
-  float depth;
-  /// time of the collision (between 0 and 1 in relation to movement)
-  float time;
-  /// The normal of the side we collided with
-  Vector normal;
+  CollisionHit() {
+    left = false;
+    right = false;
+    top = false;
+    bottom = false;
+    crush = false;
+  }
+
+  bool left, right;
+  bool top, bottom;
+  bool crush;
+
+  Vector slope_normal;
 };
 
 #endif
index 086cfab..9b03ff8 100644 (file)
 
 #include "log.hpp"
 #include "math/vector.hpp"
+#include "math/rect.hpp"
 
 std::ostream& operator<<(std::ostream& out, const Vector& vector)
 {
-    out << '[' << vector.x << ',' << vector.y << ']';
-    return out;
+  out << '[' << vector.x << ',' << vector.y << ']';
+  return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const Rect& rect)
+{
+  out << "[" << rect.get_left() << "," << rect.get_top() << "   "
+             << rect.get_right() << "," << rect.get_bottom() << "]";
+  return out;
 }
 
index b26960a..4d4b74b 100644 (file)
@@ -81,6 +81,8 @@ inline std::ostream& log_fatal_f() {
 
 class Vector;
 std::ostream& operator<< (std::ostream& str, const Vector& vector);
+class Rect;
+std::ostream& operator<< (std::ostream& str, const Rect& rect);
 
 #endif
 
index 2a50dd9..79e422a 100644 (file)
@@ -95,11 +95,11 @@ public:
     p2 += v;
   }
 
-  bool inside(const Vector& v) const
+  bool contains(const Vector& v) const
   {
     return v.x >= p1.x && v.y >= p1.y && v.x < p2.x && v.y < p2.y;
   }
-  bool inside(const Rect& other) const
+  bool contains(const Rect& other) const
   {
     if(p1.x >= other.p2.x || other.p1.x >= p2.x)
       return false;
index e6ae483..46abffb 100644 (file)
@@ -79,11 +79,14 @@ class MovingObject : public GameObject
 public:
   MovingObject();
   virtual ~MovingObject();
-  
-  /** this function is called when the object collided with any other object
-   */
-  virtual HitResponse collision(GameObject& other,
-                                const CollisionHit& hit) = 0;
+
+  /** this function is called when the object collided with something solid */
+  virtual void collision_solid(const CollisionHit& hit)
+  {
+    (void) hit;
+  }
+  /** this function is called when the object collided with any other object */
+  virtual HitResponse collision(GameObject& other, const CollisionHit& hit) = 0;
   /** called when tiles with special attributes have been touched */
   virtual void collision_tile(uint32_t tile_attributes)
   {
index 3ab0d1b..95520d6 100644 (file)
@@ -64,12 +64,11 @@ Block::~Block()
 }
 
 HitResponse
-Block::collision(GameObject& other, const CollisionHit& hitdata)
+Block::collision(GameObject& other, const CollisionHit& )
 {
   Player* player = dynamic_cast<Player*> (&other);
   if(player) {
-    // collided from below?
-    if(hitdata.normal.x == 0 && hitdata.normal.y < 0) {
+    if(player->get_bbox().get_top() > get_bbox().get_bottom() - 7.0) {
       hit(*player);
     }
   }
@@ -85,7 +84,7 @@ Block::collision(GameObject& other, const CollisionHit& hitdata)
     }
   }
 
-  return FORCE_MOVE;
+  return SOLID;
 }
 
 void
@@ -225,7 +224,7 @@ BonusBlock::try_open()
         sector->add_object(riser);
       } else {
         SpecialRiser* riser = new SpecialRiser(
-            get_pos(), new Flower(Flower::FIREFLOWER));
+            get_pos(), new Flower(FIRE_BONUS));
         sector->add_object(riser);
       }
       sound_manager->play("sounds/upgrade.wav");
@@ -237,7 +236,7 @@ BonusBlock::try_open()
         sector->add_object(riser);                                            
       } else {
         SpecialRiser* riser = new SpecialRiser(
-            get_pos(), new Flower(Flower::ICEFLOWER));
+            get_pos(), new Flower(ICE_BONUS));
         sector->add_object(riser);
       }      
       sound_manager->play("sounds/upgrade.wav");
@@ -257,9 +256,6 @@ BonusBlock::try_open()
       sector->add_object(riser);
       sound_manager->play("sounds/upgrade.wav");
       break;
-
-    //default:
-      //assert(false);
   }
 
   start_bounce();
index a8b7cef..ef7b52f 100644 (file)
 #include "badguy/badguy.hpp"
 #include "main.hpp"
 
-static const float BULLET_XM = 600;
-static const float BULLET_STARTING_YM = 0;
+namespace {
+  const float BULLET_XM = 600;
+  const float BULLET_STARTING_YM = 0;
+}
 
-Bullet::Bullet(const Vector& pos, float xm, int dir, int kind_)
-  : kind(kind_), life_count(3), sprite(0)
+Bullet::Bullet(const Vector& pos, float xm, int dir)
+  : life_count(3)
 {
+  sprite.reset(sprite_manager->create("images/objects/bullets/firebullet.sprite"));
+  
   bbox.set_pos(pos);
-  bbox.set_size(4, 4);
+  bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
 
   float speed = dir == RIGHT ? BULLET_XM : -BULLET_XM;
   physic.set_velocity_x(speed + xm);
   physic.set_velocity_y(BULLET_STARTING_YM);
-
-  if (kind == ICE_BULLET) {
-    life_count = 6; //ice-bullets get "extra lives" for bumping off walls
-    sprite = sprite_manager->create("images/objects/bullets/icebullet.sprite");
-  } else if(kind == FIRE_BULLET) {
-    sprite = sprite_manager->create("images/objects/bullets/firebullet.sprite");
-  }
 }
 
 Bullet::~Bullet()
 {
-  delete sprite;
 }
 
 void
 Bullet::update(float elapsed_time)
 {
-  if(kind == FIRE_BULLET) {
-    // @not completely framerate independant :-/
-    physic.set_velocity_y(physic.get_velocity_y() + 50 * elapsed_time);
-  }
+  // @not completely framerate independant :-/
+  physic.set_velocity_y(physic.get_velocity_y() + 50 * elapsed_time);
+
   if(physic.get_velocity_y() > 900)
     physic.set_velocity_y(900);
   else if(physic.get_velocity_y() < -900)
@@ -88,30 +83,20 @@ Bullet::draw(DrawingContext& context)
   sprite->draw(context, get_pos(), LAYER_OBJECTS);
 }
 
-HitResponse
-Bullet::collision(GameObject& other, const CollisionHit& hit)
+void
+Bullet::collision_solid(const CollisionHit& hit)
 {
-  if(other.get_flags() & FLAG_SOLID) {
-    if(fabsf(hit.normal.y) > .5) { // roof or floor bump
-      physic.set_velocity_y(-physic.get_velocity_y());
-      life_count -= 1;
-    } else { // bumped left or right
-      if(kind == FIRE_BULLET)
-        remove_me();
-      else
-        physic.set_velocity_x(-physic.get_velocity_x());
-    }
-    
-    return CONTINUE;
-  }
-
-  // hit a Badguy
-  BadGuy* badguy = dynamic_cast<BadGuy*> (&other);
-  if(badguy) {
+  if(hit.top || hit.bottom) {
+    physic.set_velocity_y(-physic.get_velocity_y());
+    life_count--;
+  } else if(hit.left || hit.right) {
     remove_me();
-    return FORCE_MOVE;
   }
+}
+
+HitResponse
+Bullet::collision(GameObject& , const CollisionHit& )
+{
   return FORCE_MOVE;
 }
 
index 52becdd..3664f33 100644 (file)
 #include "physic.hpp"
 #include "sprite/sprite.hpp"
 
-enum BulletsKind {
-  FIRE_BULLET,
-  ICE_BULLET
-};
-
 class Bullet : public MovingObject
 {
 public:
-  Bullet(const Vector& pos, float xm, int dir, int kind);
+  Bullet(const Vector& pos, float xm, int dir);
   ~Bullet();
   
   void update(float elapsed_time);
   void draw(DrawingContext& context);
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision(GameObject& other, const CollisionHit& hit);
 
-  int kind;        
-  
 private:
   int life_count;
   Physic physic;
-  Sprite* sprite;
+  std::auto_ptr<Sprite> sprite;
 };
 
 #endif
index e11bcb6..0279167 100644 (file)
@@ -40,7 +40,7 @@ Candle::Candle(const lisp::Lisp& lisp)
 }
 
 HitResponse
-Candle::collision(GameObject& , const CollisionHit& )
+Candle::collision(GameObject&, const CollisionHit& )
 {
   return FORCE_MOVE;
 }
index 2684bcd..e9e0a0d 100644 (file)
 Coin::Coin(const Vector& pos)
        : MovingSprite(pos, "images/objects/coin/coin.sprite", LAYER_TILES, COLGROUP_TOUCHABLE)
 {
+  sound_manager->preload("sounds/coin.wav");
 }
 
 Coin::Coin(const lisp::Lisp& reader)
        : MovingSprite(reader, "images/objects/coin/coin.sprite", LAYER_TILES, COLGROUP_TOUCHABLE)
 {
+  sound_manager->preload("sounds/coin.wav");
 }
 
 void
index c595865..9c3106f 100644 (file)
@@ -28,7 +28,6 @@ class Coin : public MovingSprite
 public:
   Coin(const Vector& pos);
   Coin(const lisp::Lisp& reader);
-  virtual Coin* clone() const { return new Coin(*this); }
 
   HitResponse collision(GameObject& other, const CollisionHit& hit);
 
index 4e4c878..b5830e0 100644 (file)
@@ -20,6 +20,7 @@
 #include <config.h>
 
 #include <math.h>
+#include <assert.h>
 #include "flower.hpp"
 #include "resources.hpp"
 #include "camera.hpp"
 #include "audio/sound_manager.hpp"
 #include "sprite/sprite_manager.hpp"
 
-Flower::Flower(Type _type)
+Flower::Flower(BonusType _type)
   : type(_type)
 {
   bbox.set_size(32, 32);
 
-  if(_type == FIREFLOWER){
+  if(type == FIRE_BONUS) {
     sprite = sprite_manager->create("images/powerups/fireflower/fireflower.sprite");
     sound_manager->preload("sounds/fire-flower.wav");
   }
-  else
+  else if(type == ICE_BONUS) {
     sprite = sprite_manager->create("images/powerups/iceflower/iceflower.sprite"); 
+  } else {
+    assert(false);
+  }
 
   set_group(COLGROUP_TOUCHABLE);
 }
@@ -66,10 +70,8 @@ Flower::collision(GameObject& other, const CollisionHit& )
   if(!player)
     return ABORT_MOVE;
 
-  if(type == FIREFLOWER)
-    player->add_bonus(FIRE_BONUS, true);
-  else
-    player->add_bonus(ICE_BONUS, true);
+  if(!player->add_bonus(type, true))
+    return FORCE_MOVE;
   
   sound_manager->play("sounds/fire-flower.wav");
   remove_me();
index 637f1a9..4411ef9 100644 (file)
 #include "moving_object.hpp"
 #include "sprite/sprite.hpp"
 #include "physic.hpp"
+#include "player_status.hpp"
 
 class Flower : public MovingObject
 {
 public:
-  enum Type {
-    FIREFLOWER, ICEFLOWER
-  };
-  Flower(Type type);
+  Flower(BonusType type);
   ~Flower();
 
   virtual void update(float elapsed_time);
@@ -38,7 +36,7 @@ public:
   virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
 
 private:
-  Type type;
+  BonusType type;
   Sprite* sprite;
 };
 
index 32e3674..3a32bcf 100644 (file)
@@ -41,22 +41,23 @@ GrowUp::update(float elapsed_time)
   movement = physic.get_movement(elapsed_time);
 }
 
-HitResponse
-GrowUp::collision(GameObject& other, const CollisionHit& hit)
+void
+GrowUp::collision_solid(const CollisionHit& hit)
 {
-  if(other.get_flags() & FLAG_SOLID) {
-    if(fabsf(hit.normal.y) > .5) { // roof or ground
-      physic.set_velocity_y(0);
-    } else { // bumped left or right
-      physic.set_velocity_x(-physic.get_velocity_x());
-    }
+  if(hit.top || hit.bottom)
+    physic.set_velocity_y(0);
+  if(hit.left || hit.right)
+    physic.set_velocity_x(-physic.get_velocity_x());
+}
 
-    return CONTINUE;
-  }
-  
+HitResponse
+GrowUp::collision(GameObject& other, const CollisionHit& )
+{
   Player* player = dynamic_cast<Player*>(&other);
   if(player != 0) {
-    player->add_bonus(GROWUP_BONUS, true);
+    if(!player->add_bonus(GROWUP_BONUS, true))
+      return FORCE_MOVE;
+
     sound_manager->play("sounds/grow.wav");
     remove_me();
     
index 2405914..cad747b 100644 (file)
@@ -30,6 +30,7 @@ public:
   virtual GrowUp* clone() const { return new GrowUp(*this); }
 
   virtual void update(float elapsed_time);
+  virtual void collision_solid(const CollisionHit& hit);
   virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
   
 private:
index c730e18..59cbfdf 100644 (file)
@@ -1,4 +1,4 @@
-//  $Id: hurtingplatform.cpp 3506 2006-05-12 01:41:09Z sommer $
+//  $Id$
 //
 //  SuperTux - Hurting Platform
 //  Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
 HurtingPlatform::HurtingPlatform(const lisp::Lisp& reader)
        : Platform(reader)
 {
+  set_group(COLGROUP_TOUCHABLE);
 }
 
 HitResponse
-HurtingPlatform::collision(GameObject& other, const CollisionHit& hit)
+HurtingPlatform::collision(GameObject& other, const CollisionHit& )
 {
   Player* player = dynamic_cast<Player*>(&other);
   if (player) {
@@ -43,7 +44,8 @@ HurtingPlatform::collision(GameObject& other, const CollisionHit& hit)
   if (badguy) {
     badguy->kill_fall();
   }
-  return Platform::collision(other, hit);
+
+  return FORCE_MOVE;
 }
 
 IMPLEMENT_FACTORY(HurtingPlatform, "hurting_platform");
index d914b2b..fe17ba6 100644 (file)
 #include "video/drawing_context.hpp"
 #include "audio/sound_manager.hpp"
 #include "object_factory.hpp"
+#include "object/player.hpp"
 
 InvisibleBlock::InvisibleBlock(const Vector& pos)
   : Block(sprite_manager->create("images/objects/bonus_block/invisibleblock.sprite")), visible(false)
 {
   bbox.set_pos(pos);
-  flags &= ~FLAG_SOLID;
-  set_group(COLGROUP_MOVING);
+  sound_manager->preload("sounds/brick.wav");
   sound_manager->preload("sounds/brick.wav");
 }
 
@@ -43,14 +43,31 @@ InvisibleBlock::draw(DrawingContext& context)
     sprite->draw(context, get_pos(), LAYER_OBJECTS);
 }
 
+HitResponse
+InvisibleBlock::collision(GameObject& other, const CollisionHit& hit)
+{
+  if(!visible) {
+    Player* player = dynamic_cast<Player*> (&other);
+    if(player) {
+      if(player->get_movement().y > 0 ||
+          player->get_bbox().get_top() <= get_bbox().get_bottom() - 7.0) {
+        return PASSTHROUGH;
+      }
+    }
+  }
+
+  return Block::collision(other, hit);
+}
+
 void
 InvisibleBlock::hit(Player& )
 {
+  sound_manager->play("sounds/brick.wav"); 
+
   if(visible)
     return;
 
   sprite->set_action("empty");
-  sound_manager->play("sounds/brick.wav");
   start_bounce();
   flags |= FLAG_SOLID;
   set_group(COLGROUP_STATIC);
index bada73c..5607302 100644 (file)
@@ -28,6 +28,7 @@ public:
   InvisibleBlock(const Vector& pos);
 
   virtual void draw(DrawingContext& context);
+  virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
 
 protected:
   virtual void hit(Player& player);
index 0a9228a..e253a43 100644 (file)
@@ -74,6 +74,8 @@ void ParticleSystem_Interactive::draw(DrawingContext& context)
 int
 ParticleSystem_Interactive::collision(Particle* object, Vector movement)
 {
+  using namespace collision;
+    
   TileMap* solids = Sector::current()->solids;
   // calculate rectangle where the object will move
   float x1, x2;
@@ -90,19 +92,16 @@ ParticleSystem_Interactive::collision(Particle* object, Vector movement)
   int max_x = int(x2+1);
   int max_y = int(y2+1);
   
-  CollisionHit temphit, hit;
   Rect dest = Rect(x1, y1, x2, y2);
   dest.move(movement);
-  hit.time = -1; // represents an invalid value
+  Constraints constraints;
   for(int x = starttilex; x*32 < max_x; ++x) {
     for(int y = starttiley; y*32 < max_y; ++y) {
       const Tile* tile = solids->get_tile(x, y);
       if(!tile)
         continue;
       // skip non-solid tiles, except water
-      if (tile->getAttributes() & Tile::WATER)
-        water = true;
-      if(!water && !(tile->getAttributes() & Tile::SOLID))
+      if(! (tile->getAttributes() & (Tile::WATER | Tile::SOLID)))
         continue;
 
       if(tile->getAttributes() & Tile::SLOPE) { // slope tile
@@ -111,35 +110,39 @@ ParticleSystem_Interactive::collision(Particle* object, Vector movement)
         Vector p2((x+1)*32, (y+1)*32);
         triangle = AATriangle(p1, p2, tile->getData());
 
-        if(Collision::rectangle_aatriangle(temphit, dest, movement,
-              triangle)) {
-          if(temphit.time > hit.time)
-            hit = temphit;
+        if(rectangle_aatriangle(&constraints, dest, triangle)) {
+          if(tile->getAttributes() & Tile::WATER)
+            water = true;
         }
       } else { // normal rectangular tile
         Rect rect(x*32, y*32, (x+1)*32, (y+1)*32);
-        if(Collision::rectangle_rectangle(temphit, dest,
-              movement, rect)) {
-          if(temphit.time > hit.time)
-            hit = temphit;
+        if(intersects(dest, rect)) {
+          if(tile->getAttributes() & Tile::WATER)
+            water = true;
+          set_rectangle_rectangle_constraints(&constraints, dest, rect); 
         }
       }
     }
   }
+
+  // TODO don't use magic numbers here...
   
   // did we collide at all?
-  if(hit.time < 0) {
-    return -1; //no collision
-  }
-  else {
-    if (water)
-      return 0; //collision with water tile - don't draw splash
-    else {
-      if ((hit.normal.x == 1) && (hit.normal.y == 0))
-        return 2; //collision from right
-      else return 1; //collision from above
+  if(!constraints.has_constraints())
+    return -1;
+
+  const CollisionHit& hit = constraints.hit;
+  if (water) {
+    return 0; //collision with water tile - don't draw splash
+  } else {
+    if (hit.right || hit.left) {
+      return 2; //collision from right
+    } else {
+      return 1; //collision from above
     }
   }
+
+  return 0;
 }
 
 RainParticleSystem::RainParticleSystem()
@@ -270,6 +273,8 @@ CometParticleSystem::~CometParticleSystem()
 
 void CometParticleSystem::update(float elapsed_time)
 {
+  (void) elapsed_time;
+#if 0
     std::vector<Particle*>::iterator i;
     for(
         i = particles.begin(); i != particles.end(); ++i) {
@@ -291,4 +296,5 @@ void CometParticleSystem::update(float elapsed_time)
             particle->pos.y = new_y;
         }
     }
+#endif
 }
index 333fd07..08469b6 100644 (file)
@@ -59,24 +59,9 @@ Platform::Platform(const Platform& other)
   walker->path = &*path;
 }
 
-//TODO: Squish Tux when standing between platform and solid tile/object
-//      Improve collision handling
-//      Move all MovingObjects lying on the platform instead of only the player
 HitResponse
-Platform::collision(GameObject& other, const CollisionHit& hit)
+Platform::collision(GameObject& , const CollisionHit& )
 {
-  if (typeid(other) == typeid(Player)) {
-    if (hit.normal.y >= 0.9) {
-      //Tux is standing on the platform
-      //Player* player = (Player*) &other;
-      //player->add_velocity(speed * 1.5);
-      return PASS_MOVEMENT;
-    }
-  }
-  if(other.get_flags() & FLAG_SOLID) {
-    //Collision with a solid tile
-    return ABORT_MOVE;
-  }
   return FORCE_MOVE;
 }
 
index 4aab47f..8d81ec4 100644 (file)
@@ -158,8 +158,6 @@ Player::init()
   on_ground_flag = false;
   grabbed_object = NULL;
 
-  floor_normal = Vector(0,-1);
-
   physic.reset();
 }
 
@@ -188,7 +186,9 @@ Player::adjust_height(float new_height)
   Rect bbox2 = bbox;
   bbox2.move(Vector(0, bbox.get_height() - new_height));
   bbox2.set_height(new_height);
-  if (!Sector::current()->is_free_space(bbox2)) return false;
+  if (!Sector::current()->is_free_space(bbox2))
+    return false;
+
   // adjust bbox accordingly
   // note that we use members of moving_object for this, so we can run this during CD, too
   set_pos(bbox2.p1);
@@ -218,12 +218,11 @@ Player::update(float elapsed_time)
     set_width(31.8);
   }
 
-  // on downward slopes, adjust vertical velocity to match slope angle
+  // on downward slopes, adjust vertical velocity so tux walks smoothly down
   if (on_ground()) {
-    if (floor_normal.y != 0) {
-      if ((floor_normal.x * physic.get_velocity_x()) > 0) {
-        // we overdo it a little, just to be on the safe side
-        physic.set_velocity_y(-physic.get_velocity_x() * (floor_normal.x / floor_normal.y) * 2);
+    if(floor_normal.y != 0) {
+      if ((floor_normal.x * physic.get_velocity_x()) >= 0) {
+        physic.set_velocity_y(250);
       }
     }
   }
@@ -569,25 +568,8 @@ Player::handle_vertical_input()
   }
   
   /* When Down is not held anymore, disable butt jump */
-  if(butt_jump && !controller->hold(Controller::DOWN)) butt_jump = false;
-  /** jumping is only allowed if we're about to touch ground soon and if the
-   * button has been up in between the last jump
-   */
-  // FIXME
-#if 0
-  if ( (issolid(get_pos().x + bbox.get_width() / 2,
-          get_pos().y + bbox.get_height() + 64) ||
-        issolid(get_pos().x + 1, get_pos().y + bbox.get_height() + 64) ||
-        issolid(get_pos().x + bbox.get_width() - 1,
-          get_pos().y + bbox.get_height() + 64))
-       && jumping  == false
-       && can_jump == false
-       && input.jump && !input.old_jump)
-    {
-      can_jump = true;
-    }
-#endif
+  if(butt_jump && !controller->hold(Controller::DOWN))
+    butt_jump = false;
 }
 
 void
@@ -686,47 +668,57 @@ Player::add_coins(int count)
   player_status->add_coins(count);
 }
 
-void
+bool
 Player::add_bonus(const std::string& bonustype)
 {
+  BonusType type = NO_BONUS;
+  
   if(bonustype == "grow") {
-    add_bonus(GROWUP_BONUS);
+    type = GROWUP_BONUS;
   } else if(bonustype == "fireflower") {
-    add_bonus(FIRE_BONUS);
+    type = FIRE_BONUS;
   } else if(bonustype == "iceflower") {
-    add_bonus(ICE_BONUS);
+    type = ICE_BONUS;
   } else if(bonustype == "none") {
-    add_bonus(NO_BONUS);
+    type = NO_BONUS;
   } else {
     std::ostringstream msg;
     msg << "Unknown bonus type "  << bonustype;
     throw std::runtime_error(msg.str());
   }
+  
+  return add_bonus(type);
 }
 
-void
+bool
 Player::add_bonus(BonusType type, bool animate)
 {
   // always ignore NO_BONUS
   if (type == NO_BONUS) {
-    return;
+    return true;
   }
 
   // ignore GROWUP_BONUS if we're already big
   if (type == GROWUP_BONUS) {
-    if (player_status->bonus == GROWUP_BONUS) return; 
-    if (player_status->bonus == FIRE_BONUS) return;
-    if (player_status->bonus == ICE_BONUS) return;
+    if (player_status->bonus == GROWUP_BONUS)
+      return true; 
+    if (player_status->bonus == FIRE_BONUS)
+      return true;
+    if (player_status->bonus == ICE_BONUS)
+      return true;
   }
 
-  set_bonus(type, animate);
+  return set_bonus(type, animate);
 }
 
-void
+bool
 Player::set_bonus(BonusType type, bool animate)
 {
   if(player_status->bonus == NO_BONUS) {
-    if (!adjust_height(62.8)) return;
+    if (!adjust_height(62.8)) {
+      printf("can't adjust\n");
+      return false;
+    }
     if(animate)
       growing_timer.start(GROWING_TIME);
   }
@@ -747,6 +739,7 @@ Player::set_bonus(BonusType type, bool animate)
   if (type == ICE_BONUS) player_status->max_ice_bullets++;
 
   player_status->bonus = type;
+  return true;
 }
 
 void
@@ -910,8 +903,36 @@ Player::collision_tile(uint32_t tile_attributes)
     kill(false);
 }
 
+void
+Player::collision_solid(const CollisionHit& hit)
+{
+  if(hit.bottom) {
+    if(physic.get_velocity_y() > 0)
+      physic.set_velocity_y(0);
+
+    on_ground_flag = true;
+    floor_normal = hit.slope_normal;
+  } else if(hit.top) {
+    if(physic.get_velocity_y() < 0)
+      physic.set_velocity_y(.2);
+  }
+
+  if(hit.left || hit.right) {
+    physic.set_velocity_x(0);
+  }
+
+  // crushed?
+  if(hit.crush) {
+    if(hit.left || hit.right) {
+      kill(true);
+    } else if(hit.top || hit.bottom) {
+      kill(false);
+    }
+  }
+}
+
 HitResponse
-Player::collision(GameObject& other, const CollisionHit& hit)
+Player::collision(GameObject& other, const CollisionHit& )
 {
   Bullet* bullet = dynamic_cast<Bullet*> (&other);
   if(bullet) {
@@ -923,76 +944,12 @@ Player::collision(GameObject& other, const CollisionHit& hit)
     assert(portable != NULL);
     if(portable && grabbed_object == NULL
         && controller->hold(Controller::ACTION)
-        && fabsf(hit.normal.x) > .9) {
+        /*&& fabsf(hit.normal.x) > .9*/) {
       grabbed_object = portable;
       grabbed_object->grab(*this, get_pos(), dir);
       return CONTINUE;
     }
   }
-  if(other.get_flags() & FLAG_SOLID) {
-    /*
-    printf("Col %p: HN: %3.1f %3.1f D %.1f P: %3.1f %3.1f M: %3.1f %3.1f\n",
-        &other,
-        hit.normal.x, hit.normal.y, hit.depth,
-        get_pos().x, get_pos().y,
-        movement.x, movement.y);
-    */
-    
-    if(hit.normal.y < 0) { // landed on floor?
-      if(physic.get_velocity_y() > 0)
-        physic.set_velocity_y(0);
-
-      on_ground_flag = true;
-
-      // remember normal of this tile
-      if (hit.normal.y > -0.9) {
-        floor_normal.x = hit.normal.x;
-        floor_normal.y = hit.normal.y;
-      } else {
-        // slowly adjust to unisolid tiles. 
-        // Necessary because our bounding box sometimes reaches through slopes and thus hits unisolid tiles
-        floor_normal.x = (floor_normal.x * 0.9) + (hit.normal.x * 0.1);
-        floor_normal.y = (floor_normal.y * 0.9) + (hit.normal.y * 0.1);
-      }
-
-      // hack platforms so that we stand normally on them when going down...
-      Platform* platform = dynamic_cast<Platform*> (&other);
-      if(platform != NULL) {
-        if(platform->get_speed().y > 0)
-          physic.set_velocity_y(platform->get_speed().y);
-        //physic.set_velocity_x(platform->get_speed().x);
-      }
-    } else if(hit.normal.y > 0) { // bumped against the roof
-      physic.set_velocity_y(-.1);
-
-      // hack platform so that we are not glued to it from below
-      Platform* platform = dynamic_cast<Platform*> (&other);
-      if(platform != NULL) {
-        physic.set_velocity_y(platform->get_speed().y);
-      }      
-    }
-    
-    if(fabsf(hit.normal.x) > .9) { // hit on the side?
-      physic.set_velocity_x(0);
-    }
-
-    MovingObject* omov = dynamic_cast<MovingObject*> (&other);
-    if(omov != NULL) {
-      Vector mov = movement - omov->get_movement();
-      /*
-      printf("W %p - HITN: %3.1f %3.1f D:%3.1f TM: %3.1f %3.1f TD: %3.1f %3.1f PM: %3.2f %3.1f\n",
-          omov,
-          hit.normal.x, hit.normal.y,
-          hit.depth,
-          movement.x, movement.y,
-          dest.p1.x, dest.p1.y,
-          omov->get_movement().x, omov->get_movement().y);
-      */
-    }
-    
-    return CONTINUE;
-  }
 
 #ifdef DEBUG
   assert(dynamic_cast<MovingObject*> (&other) != NULL);
index b7fb3ac..bab2bc5 100644 (file)
@@ -135,6 +135,7 @@ public:
 
   virtual void update(float elapsed_time);
   virtual void draw(DrawingContext& context);
+  virtual void collision_solid(const CollisionHit& hit);
   virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
   virtual void collision_tile(uint32_t tile_attributes);
 
@@ -156,10 +157,21 @@ public:
   void check_bounds(Camera* camera);
   void move(const Vector& vector);
 
-  virtual void add_bonus(const std::string& bonus);
+  virtual bool add_bonus(const std::string& bonus);
   virtual void add_coins(int count);
-  void add_bonus(BonusType type, bool animate = false); /**< picks up a bonus, taking care not to pick up lesser bonus items than we already have */
-  void set_bonus(BonusType type, bool animate = false); /**< like add_bonus, but can also downgrade the bonus items carried */
+  
+  /**
+   * picks up a bonus, taking care not to pick up lesser bonus items than we already have
+   *
+   * @returns true if the bonus has been set (or was already good enough)
+   *          false if the bonus could not be set (for example no space for big tux)
+   */
+  bool add_bonus(BonusType type, bool animate = false); 
+  /**
+   * like add_bonus, but can also downgrade the bonus items carried
+   */  
+  bool set_bonus(BonusType type, bool animate = false); 
+
   PlayerStatus* get_status()
   {
     return player_status;
@@ -264,6 +276,7 @@ private:
   Sprite* smalltux_gameover;
   Sprite* smalltux_star;
   Sprite* bigtux_star;
+
   Vector floor_normal;
 
   bool ghost_mode; /**< indicates if Tux should float around and through solid objects */
index ebced41..b865ba8 100644 (file)
@@ -31,7 +31,7 @@
 #include "log.hpp"
 
 PowerUp::PowerUp(const lisp::Lisp& lisp)
-       : MovingSprite(lisp, LAYER_OBJECTS, COLGROUP_MOVING)
+  : MovingSprite(lisp, LAYER_OBJECTS, COLGROUP_MOVING)
 {
   lisp.get("script", script);
   no_physics = false;
@@ -41,43 +41,47 @@ PowerUp::PowerUp(const lisp::Lisp& lisp)
   sound_manager->preload("sounds/fire-flower.wav");
 }
 
-HitResponse
-PowerUp::collision(GameObject& other, const CollisionHit& hit)
+void
+PowerUp::collision_solid(const CollisionHit& hit)
 {
-  if(other.get_flags() & FLAG_SOLID) {
-    if(fabsf(hit.normal.y) > .5) { // roof or ground
-      physic.set_velocity_y(0);
-    } else { // bumped left or right
-      physic.set_velocity_x(-physic.get_velocity_x());
-    }
-
-    return CONTINUE;
+  if(hit.bottom) {
+    physic.set_velocity_y(0);
   }
-  
+  if(hit.right || hit.left) {
+    physic.set_velocity_x(-physic.get_velocity_x());
+  }
+}
+
+HitResponse
+PowerUp::collision(GameObject& other, const CollisionHit&)
+{
   Player* player = dynamic_cast<Player*>(&other);
   if(player == 0)
     return FORCE_MOVE;
 
-  remove_me();
-
   if (script != "") {
     std::istringstream stream(script);
     Sector::current()->run_script(stream, "powerup-script");
+    remove_me();
     return ABORT_MOVE;
   }
 
   // some defaults if no script has been set
   if (sprite_name == "images/powerups/egg/egg.sprite") {
-    player->add_bonus(GROWUP_BONUS, true);
+    if(!player->add_bonus(GROWUP_BONUS, true))
+      return FORCE_MOVE;
     sound_manager->play("sounds/grow.wav");
   } else if (sprite_name == "images/powerups/fireflower/fireflower.sprite") {
-    player->add_bonus(FIRE_BONUS, true);
+    if(!player->add_bonus(FIRE_BONUS, true))
+      return FORCE_MOVE;
     sound_manager->play("sounds/fire-flower.wav");
   } else if (sprite_name == "images/powerups/star/star.sprite") {
     player->make_invincible();
   } else if (sprite_name == "images/powerups/1up/1up.sprite") {
     player->get_status()->add_coins(100);
   }
+
+  remove_me();
   return ABORT_MOVE;
 }
 
index 59922a7..04ccb35 100644 (file)
@@ -29,9 +29,9 @@ class PowerUp : public MovingSprite
 {
 public:
   PowerUp(const lisp::Lisp& lisp);
-  virtual PowerUp* clone() const { return new PowerUp(*this); }
 
   virtual void update(float elapsed_time);
+  virtual void collision_solid(const CollisionHit& hit);
   virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
   
 private:
index 6ba11fc..1ffa231 100644 (file)
@@ -26,7 +26,7 @@
 #include "object_factory.hpp"
 
 Rock::Rock(const lisp::Lisp& reader)
-       : MovingSprite(reader, "images/objects/rock/rock.sprite", LAYER_OBJECTS+1, COLGROUP_MOVING)
+       : MovingSprite(reader, "images/objects/rock/rock.sprite", LAYER_OBJECTS+1, COLGROUP_STATIC)
 {
   grabbed = false;
   flags |= FLAG_SOLID | FLAG_PORTABLE;
@@ -48,7 +48,7 @@ Rock::update(float elapsed_time)
 {
   if(!grabbed) {
     flags |= FLAG_SOLID;
-    set_group(COLGROUP_MOVING);
+    set_group(COLGROUP_STATIC);
     movement = physic.get_movement(elapsed_time);
   } else {
     physic.set_velocity(0, 0);
@@ -64,19 +64,20 @@ Rock::update(float elapsed_time)
   */
 }
 
+void
+Rock::collision_solid(const CollisionHit& )
+{
+  physic.set_velocity(0, 0);
+}
+
 HitResponse
-Rock::collision(GameObject& object, const CollisionHit& )
+Rock::collision(GameObject& , const CollisionHit& )
 {
   if(grabbed) {
-    return FORCE_MOVE;
-  }
-
-  if(object.get_flags() & FLAG_SOLID) {
-    physic.set_velocity(0, 0);
-    return CONTINUE;
+    return PASSTHROUGH;
   }
 
-  return FORCE_MOVE;
+  return SOLID;
 }
 
 void
index ad4bebc..207095e 100644 (file)
@@ -34,6 +34,7 @@ public:
   Rock(const lisp::Lisp& reader);
   virtual Rock* clone() const { return new Rock(*this); }
 
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision(GameObject& other, const CollisionHit& hit);
   void update(float elapsed_time);
   void write(lisp::Writer& writer);
index ba0d114..90875f2 100644 (file)
@@ -16,7 +16,6 @@
 //  You should have received a copy of the GNU General Public License
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
 #include <config.h>
 
 #include <stdexcept>
@@ -179,30 +178,27 @@ ScriptedObject::draw(DrawingContext& context)
   sprite->draw(context, get_pos(), layer);
 }
 
-HitResponse
-ScriptedObject::collision(GameObject& other, const CollisionHit& hit)
+void
+ScriptedObject::collision_solid(const CollisionHit& hit)
 {
   if(!physic_enabled)
-    return FORCE_MOVE;
-
-  if(!(other.get_flags() & FLAG_SOLID))
-    return FORCE_MOVE;
-
-  if(other.get_flags() & FLAG_SOLID) {
-    if(hit.normal.y < 0) { // landed on floor
-      if(physic.get_velocity_y() > 0)
-        physic.set_velocity_y(0);
-    } else if(hit.normal.y > 0) { // bumped against roof
-      physic.set_velocity_y(.1);
-    }
-
-    if(fabsf(hit.normal.x) > .9) { // hit on side?
-      physic.set_velocity_x(0);
-    }
-        
-    return CONTINUE;
+    return;
+
+  if(hit.bottom) {
+    if(physic.get_velocity_y() > 0)
+      physic.set_velocity_y(0);
+  } else if(hit.top) {
+    physic.set_velocity_y(.1);
   }
 
+  if(hit.left || hit.right) {
+    physic.set_velocity_x(0);
+  }
+}
+
+HitResponse
+ScriptedObject::collision(GameObject& , const CollisionHit& )
+{
   return FORCE_MOVE;
 }
 
index 2243e3e..7231d3d 100644 (file)
@@ -39,6 +39,8 @@ public:
 
   void update(float elapsed_time);
   void draw(DrawingContext& context);
+  
+  void collision_solid(const CollisionHit& hit);
   HitResponse collision(GameObject& other, const CollisionHit& hit);
 
   // --- Scripting Interface stuff ---
index c4c36b1..abbddd8 100644 (file)
@@ -38,11 +38,8 @@ SkullTile::SkullTile(const lisp::Lisp& lisp)
 }
 
 HitResponse
-SkullTile::collision(GameObject& other, const CollisionHit& hitdata)
+SkullTile::collision(GameObject& other, const CollisionHit& )
 {
-  if(hitdata.normal.y < 0.8)
-    return FORCE_MOVE;
-
   Player* player = dynamic_cast<Player*> (&other);
   if(player)
     hit = true;
index e6ef934..e6fff5d 100644 (file)
@@ -42,21 +42,21 @@ Star::update(float elapsed_time)
   movement = physic.get_movement(elapsed_time);
 }
 
-HitResponse
-Star::collision(GameObject& other, const CollisionHit& hit)
+void
+Star::collision_solid(const CollisionHit& hit)
 {
-  if(other.get_flags() & FLAG_SOLID) {
-    if(hit.normal.y < -.5) { // ground
-      physic.set_velocity_y(JUMPSPEED);
-    } else if(hit.normal.y > .5) { // roof
-      physic.set_velocity_y(0);
-    } else { // bumped left or right
-      physic.set_velocity_x(-physic.get_velocity_x());
-    }
-
-    return CONTINUE;
+  if(hit.bottom) {
+    physic.set_velocity_y(JUMPSPEED);
+  } else if(hit.top) {
+    physic.set_velocity_y(0);
+  } else if(hit.left || hit.right) {
+    physic.set_velocity_x(-physic.get_velocity_x());
   }
-  
+}
+
+HitResponse
+Star::collision(GameObject& other, const CollisionHit& )
+{
   Player* player = dynamic_cast<Player*> (&other);
   if(player) {
     player->make_invincible();
index d0eed7c..fc01922 100644 (file)
@@ -30,6 +30,7 @@ public:
   virtual Star* clone() const { return new Star(*this); }
 
   virtual void update(float elapsed_time);
+  virtual void collision_solid(const CollisionHit& hit);
   virtual HitResponse collision(GameObject& other, const CollisionHit& hit);
 
 private:
index 1d08958..9780c73 100644 (file)
@@ -34,35 +34,20 @@ UnstableTile::UnstableTile(const lisp::Lisp& lisp)
   : MovingSprite(lisp, LAYER_TILES, COLGROUP_STATIC), state(STATE_NORMAL)
 {
   sprite->set_action("normal");
-  flags |= FLAG_SOLID;
 }
 
 HitResponse
-UnstableTile::collision(GameObject& other, const CollisionHit& hit)
+UnstableTile::collision(GameObject& other, const CollisionHit& )
 {
-  switch (state) {
-
-    case STATE_NORMAL:
-      if ((hit.normal.y >= 0.8 ) && (dynamic_cast<Player*>(&other))) {
-       state = STATE_CRUMBLING;
-       sprite->set_action("crumbling", 1);
-       return FORCE_MOVE;
-      }
-      return FORCE_MOVE;
-      break;
-
-    case STATE_CRUMBLING:
-      return FORCE_MOVE;
-      break;
-
-    case STATE_DISINTEGRATING:
-      return FORCE_MOVE;
-      break;
-
+  if(state == STATE_NORMAL) {
+    Player* player = dynamic_cast<Player*> (&other);
+    if(player != NULL &&
+        player->get_bbox().get_bottom() < get_bbox().get_top() + 7.0) {
+      state = STATE_CRUMBLING;
+      sprite->set_action("crumbling", 1);
+    }
   }
-
-  log_debug << "unhandled state" << std::endl;
-  return FORCE_MOVE;
+  return SOLID;
 }
 
 void
@@ -90,7 +75,6 @@ UnstableTile::update(float elapsed_time)
        return;
       }
       break;
-
   }
 }
 
index 2a08179..0ff0b91 100644 (file)
@@ -1,4 +1,4 @@
-//  $Id: weak_block.hpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $
+//  $Id$
 //
 //  SuperTux - Weak Block
 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
@@ -33,7 +33,6 @@ class WeakBlock : public MovingSprite
 {
 public:
   WeakBlock(const lisp::Lisp& lisp);
-  virtual WeakBlock* clone() const { return new WeakBlock(*this); }
 
   HitResponse collision(GameObject& other, const CollisionHit& hit);
   void update(float elapsed_time);
index 45f3d84..d90784c 100644 (file)
@@ -35,7 +35,7 @@ public:
    * Set tux bonus.
    * This can be "grow", "fireflower" or "iceflower" at the moment
    */
-  virtual void add_bonus(const std::string& bonus) = 0;
+  virtual bool add_bonus(const std::string& bonus) = 0;
   /**
    * Give tux more coins
    */
index 529d889..a175623 100644 (file)
@@ -1060,9 +1060,10 @@ static SQInteger Player_add_bonus_wrapper(HSQUIRRELVM vm)
   }
   
   try {
-    _this->add_bonus(arg0);
+    bool return_value = _this->add_bonus(arg0);
   
-    return 0;
+    sq_pushbool(vm, return_value);
+    return 1;
   
   } catch(std::exception& e) {
     sq_throwerror(vm, e.what());
index f0463d8..6a152e6 100644 (file)
 #include <sstream>
 #include <stdexcept>
 #include <float.h>
+#include <math.h>
 
 #include "sector.hpp"
-#include "player_status.hpp"
+#include "object/player.hpp"
 #include "object/gameobjs.hpp"
 #include "object/camera.hpp"
 #include "object/background.hpp"
@@ -45,8 +46,6 @@
 #include "game_session.hpp"
 #include "resources.hpp"
 #include "statistics.hpp"
-#include "collision_grid.hpp"
-#include "collision_grid_iterator.hpp"
 #include "object_factory.hpp"
 #include "collision.hpp"
 #include "spawn_point.hpp"
@@ -77,10 +76,6 @@ Sector::Sector(Level* parent)
   add_object(new DisplayEffect());
   add_object(new TextObject());
 
-#ifdef USE_GRID
-  grid.reset(new CollisionGrid(32000, 32000));
-#endif
-
   // create a new squirrel table for the sector
   using namespace Scripting;
 
@@ -555,15 +550,6 @@ Sector::update(float elapsed_time)
 {
   player->check_bounds(camera);
 
-#if 0
-  CollisionGridIterator iter(*grid, get_active_region());
-  while(MovingObject* object = iter.next()) {
-    if(!object->is_valid())
-      continue;
-
-    object->update(elapsed_time);
-  }
-#else
   /* update objects */
   for(GameObjects::iterator i = gameobjects.begin();
           i != gameobjects.end(); ++i) {
@@ -573,7 +559,6 @@ Sector::update(float elapsed_time)
     
     object->update(elapsed_time);
   }
-#endif
   
   /* Handle all possible collisions. */
   handle_collisions();
@@ -602,10 +587,6 @@ Sector::update_game_objects()
       continue;
     }
 
-#ifdef USE_GRID
-    grid->remove_object(moving_object);
-#endif
-    
     i = moving_objects.erase(i);
   }
   for(std::vector<GameObject*>::iterator i = gameobjects.begin();
@@ -646,9 +627,6 @@ Sector::before_object_add(GameObject* object)
   MovingObject* movingobject = dynamic_cast<MovingObject*> (object);
   if(movingobject) {
     moving_objects.push_back(movingobject);
-#ifdef USE_GRID
-    grid->add_object(movingobject);
-#endif
   }
   
   TileMap* tilemap = dynamic_cast<TileMap*> (object);
@@ -757,11 +735,82 @@ Sector::draw(DrawingContext& context)
   context.pop_transform();
 }
 
+/*-------------------------------------------------------------------------
+ * Collision Detection 
+ *-------------------------------------------------------------------------*/
+
+static const float SHIFT_DELTA = 7.0f;
+
+/** r1 is supposed to be moving, r2 a solid object */
+void check_collisions(collision::Constraints* constraints,
+                      const Vector& movement, const Rect& r1, const Rect& r2,
+                      GameObject* object = NULL, MovingObject* other = NULL)
+{
+  if(!collision::intersects(r1, r2))
+    return;
+
+  // calculate intersection
+  float itop = r1.get_bottom() - r2.get_top();
+  float ibottom = r2.get_bottom() - r1.get_top();
+  float ileft = r1.get_right() - r2.get_left();
+  float iright = r2.get_right() - r1.get_left();
+
+  if(fabsf(movement.y) > fabsf(movement.x)) {
+    if(ileft < SHIFT_DELTA) {
+      constraints->right = std::min(constraints->right, r2.get_left());
+      return;
+    } else if(iright < SHIFT_DELTA) {
+      constraints->left = std::max(constraints->left, r2.get_right());
+      return;
+    }
+  } else {
+    // shiftout bottom/top
+    if(itop < SHIFT_DELTA) {
+      constraints->bottom = std::min(constraints->bottom, r2.get_top());
+      return;
+    } else if(ibottom < SHIFT_DELTA) {
+      constraints->top = std::max(constraints->top, r2.get_bottom());
+      return;
+    }
+  }
+
+  if(other != NULL) {
+    CollisionHit dummy;
+    HitResponse response = other->collision(*object, dummy);
+    if(response == PASSTHROUGH)
+      return;
+    if(other->get_movement() != Vector(0, 0)) {
+      // TODO what todo when we collide with 2 moving objects?!?
+      constraints->ground_movement = other->get_movement();
+    }
+  }
+
+  float vert_penetration = std::min(itop, ibottom);
+  float horiz_penetration = std::min(ileft, iright);
+  if(vert_penetration < horiz_penetration) {
+    if(itop < ibottom) {
+      constraints->bottom = std::min(constraints->bottom, r2.get_top());
+      constraints->hit.bottom = true;
+    } else {
+      constraints->top = std::max(constraints->top, r2.get_bottom());
+      constraints->hit.top = true;
+    }
+  } else {
+    if(ileft < iright) {
+      constraints->right = std::min(constraints->right, r2.get_left());
+      constraints->hit.right = true;
+    } else {
+      constraints->left = std::max(constraints->left, r2.get_right());
+      constraints->hit.left = true;
+    }
+  }
+}
+
 static const float DELTA = .001;
 
 void
-Sector::collision_tilemap(const Rect& dest, const Vector& movement,
-                          CollisionHit& hit) const
+Sector::collision_tilemap(collision::Constraints* constraints,
+                          const Vector& movement, const Rect& dest) const
 {
   // calculate rectangle where the object will move
   float x1 = dest.get_left();
@@ -772,22 +821,21 @@ Sector::collision_tilemap(const Rect& dest, const Vector& movement,
   // test with all tiles in this rectangle
   int starttilex = int(x1) / 32;
   int starttiley = int(y1) / 32;
-  int max_x = int(x2 + (1 - DELTA));
-  int max_y = int(y2 + (1 - DELTA));
+  int max_x = int(x2);
+  int max_y = int(y2+1);
 
-  CollisionHit temphit;
   for(int x = starttilex; x*32 < max_x; ++x) {
     for(int y = starttiley; y*32 < max_y; ++y) {
       const Tile* tile = solids->get_tile(x, y);
       if(!tile)
         continue;
       // skip non-solid tiles
-      if(tile->getAttributes() == 0)
+      if((tile->getAttributes() & Tile::SOLID) == 0)
         continue;
       // only handle unisolid when the player is falling down and when he was
       // above the tile before
       if(tile->getAttributes() & Tile::UNISOLID) {
-        if(movement.y <= 0 || dest.get_top() - movement.y > y*32)
+        if(movement.y <= 0 || dest.get_bottom() - movement.y - SHIFT_DELTA > y*32)
           continue;
       }
 
@@ -797,19 +845,10 @@ Sector::collision_tilemap(const Rect& dest, const Vector& movement,
         Vector p2((x+1)*32, (y+1)*32);
         triangle = AATriangle(p1, p2, tile->getData());
 
-        if(Collision::rectangle_aatriangle(temphit, dest, movement,
-              triangle)) {
-          if(temphit.time > hit.time && (tile->getAttributes() & Tile::SOLID)) {
-            hit = temphit;
-          }
-        }
+        collision::rectangle_aatriangle(constraints, dest, triangle);
       } else { // normal rectangular tile
         Rect rect(x*32, y*32, (x+1)*32, (y+1)*32);
-        if(Collision::rectangle_rectangle(temphit, dest, movement, rect)) {
-          if(temphit.time > hit.time && (tile->getAttributes() & Tile::SOLID)) {
-            hit = temphit;
-          }
-        }
+        check_collisions(constraints, movement, dest, rect);
       }
     }
   }
@@ -842,99 +881,84 @@ Sector::collision_tile_attributes(const Rect& dest) const
   return result;
 }
 
+/** fills in CollisionHit and Normal vector of 2 intersecting rectangle */
+static void get_hit_normal(const Rect& r1, const Rect& r2, CollisionHit& hit,
+                           Vector& normal)
+{
+  float itop = r1.get_bottom() - r2.get_top();
+  float ibottom = r2.get_bottom() - r1.get_top();
+  float ileft = r1.get_right() - r2.get_left();
+  float iright = r2.get_right() - r1.get_left();
+
+  float vert_penetration = std::min(itop, ibottom);
+  float horiz_penetration = std::min(ileft, iright);
+  if(vert_penetration < horiz_penetration) {
+    if(itop < ibottom) {
+      hit.bottom = true;
+      normal.y = vert_penetration;
+    } else {
+      hit.top = true;
+      normal.y = -vert_penetration;
+    }
+  } else {
+    if(ileft < iright) {
+      hit.right = true;
+      normal.x = horiz_penetration;
+    } else {
+      hit.left = true;
+      normal.x = -horiz_penetration;
+    }
+  }
+}
+
 void
 Sector::collision_object(MovingObject* object1, MovingObject* object2) const
 {
+  using namespace collision;
+  
+  const Rect& r1 = object1->dest;
+  const Rect& r2 = object2->dest;
+
   CollisionHit hit;
+  if(intersects(object1->dest, object2->dest)) {
+    Vector normal;
+    get_hit_normal(r1, r2, hit, normal);
 
-  Vector movement = object1->get_movement() - object2->get_movement();
-  if(Collision::rectangle_rectangle(hit, object1->dest, movement, object2->dest)) {
     HitResponse response1 = object1->collision(*object2, hit);
-    hit.normal *= -1;
     HitResponse response2 = object2->collision(*object1, hit);
-
-    if(response1 != CONTINUE) {
-      if(response1 == ABORT_MOVE)
-        object1->dest = object1->get_bbox();
-      if(response2 == CONTINUE)
-        object2->dest.move(hit.normal * (hit.depth + DELTA));
-    } else if(response2 != CONTINUE) {
-      if(response2 == ABORT_MOVE)
-        object2->dest = object2->get_bbox();
-      if(response1 == CONTINUE)
-        object1->dest.move(-hit.normal * (hit.depth + DELTA));
-    } else {
-      object1->dest.move(-hit.normal * (hit.depth/2 + DELTA));
-      object2->dest.move(hit.normal * (hit.depth/2 + DELTA));
+    if(response1 == CONTINUE || response2 == CONTINUE) {
+      normal *= (0.5 + DELTA);
+      object1->dest.move(-normal);
+      object2->dest.move(normal);
     }
   }
 }
 
-bool
-Sector::collision_static(MovingObject* object, const Vector& movement)
+void
+Sector::collision_static(collision::Constraints* constraints,
+                         const Vector& movement, const Rect& dest,
+                         GameObject& object)
 {
-  GameObject* collided_with = solids;
-  CollisionHit hit;
-  hit.time = -1;
-
-  collision_tilemap(object->dest, movement, hit);
+  collision_tilemap(constraints, movement, dest);
 
   // collision with other (static) objects
-  CollisionHit temphit;
-  for(MovingObjects::iterator i2 = moving_objects.begin();
-      i2 != moving_objects.end(); ++i2) {
-    MovingObject* moving_object_2 = *i2;
-    if(moving_object_2->get_group() != COLGROUP_STATIC
-        || !moving_object_2->is_valid())
+  for(MovingObjects::iterator i = moving_objects.begin();
+      i != moving_objects.end(); ++i) {
+    MovingObject* moving_object = *i;
+    if(moving_object->get_group() != COLGROUP_STATIC
+        || !moving_object->is_valid())
       continue;
-        
-    Rect dest = moving_object_2->dest;
-
-    Vector rel_movement 
-      = movement - moving_object_2->get_movement();
-
-    if(Collision::rectangle_rectangle(temphit, object->dest, rel_movement, dest)
-        && temphit.time > hit.time) {
-      hit = temphit;
-      collided_with = moving_object_2;
-    }
-  }
-
-  if(hit.time < 0)
-    return true;
-
-  HitResponse response = object->collision(*collided_with, hit);
-  hit.normal *= -1;
-  if(collided_with != solids) {
-    MovingObject* moving_object = (MovingObject*) collided_with;
-    HitResponse other_response = moving_object->collision(*object, hit);
-    if(other_response == ABORT_MOVE) {
-      moving_object->dest = moving_object->get_bbox();
-    } else if(other_response == FORCE_MOVE) {
-      // the static object "wins" move tux out of the collision
-      object->dest.move(-hit.normal * (hit.depth + DELTA));
-      return false;
-    } else if(other_response == PASS_MOVEMENT) {
-      object->dest.move(moving_object->get_movement());
-      //object->movement += moving_object->get_movement();
-    }
-  }
-
-  if(response == CONTINUE) {
-    object->dest.move(-hit.normal * (hit.depth + DELTA));
-    return false;
-  } else if(response == ABORT_MOVE) {
-    object->dest = object->get_bbox();
-    return true;
-  }
   
-  // force move
-  return false;
+    check_collisions(constraints, movement, dest, moving_object->dest,
+        &object, moving_object);
+  }
 }
 
 void
 Sector::handle_collisions()
 {
+  using namespace collision;
+  
   // calculate destination positions of the objects
   for(MovingObjects::iterator i = moving_objects.begin();
       i != moving_objects.end(); ++i) {
@@ -945,8 +969,6 @@ Sector::handle_collisions()
   }
     
   // part1: COLGROUP_MOVING vs COLGROUP_STATIC and tilemap
-  //   we do this up to 4 times and have to sort all results for the smallest
-  //   one before we can continue here
   for(MovingObjects::iterator i = moving_objects.begin();
       i != moving_objects.end(); ++i) {
     MovingObject* moving_object = *i;
@@ -955,39 +977,86 @@ Sector::handle_collisions()
         || !moving_object->is_valid())
       continue;
 
+    Constraints constraints;
     Vector movement = moving_object->get_movement();
-
-    // test if x or y movement is dominant
-    if(fabsf(moving_object->get_movement().x) < fabsf(moving_object->get_movement().y)) {
-
-      // test in x direction first, then y direction
-      moving_object->dest.move(Vector(0, -movement.y));
-      for(int i = 0; i < 2; ++i) {
-        bool res = collision_static(moving_object, Vector(movement.x, 0));
-        if(res)
-          break;
+    Rect& dest = moving_object->dest;
+    float owidth = moving_object->get_bbox().get_width();
+    float oheight = moving_object->get_bbox().get_height();
+
+    for(int i = 0; i < 2; ++i) {
+      collision_static(&constraints, Vector(0, movement.y), dest, *moving_object);
+      if(!constraints.has_constraints())
+        break;
+
+      // apply calculated horizontal constraints
+      if(constraints.bottom < INFINITY) {
+        float height = constraints.bottom - constraints.top;
+        if(height < oheight) {
+          // we're crushed, but ignore this for now, we'll get this again
+          // later if we're really crushed or things will solve itself when
+          // looking at the vertical constraints
+        }
+        dest.p2.y = constraints.bottom - DELTA;
+        dest.p1.y = dest.p2.y - oheight;
+      } else if(constraints.top > -INFINITY) {
+        dest.p1.y = constraints.top + DELTA;
+        dest.p2.y = dest.p1.y + oheight;
       }
-      moving_object->dest.move(Vector(0, movement.y));
-      for(int i = 0; i < 2; ++i) {
-        bool res = collision_static(moving_object, Vector(0, movement.y));
-        if(res)
-          break;
+    }
+    if(constraints.has_constraints()) {
+      if(constraints.hit.bottom) {
+        dest.move(constraints.ground_movement);
       }
-      
-    } else {
+      if(constraints.hit.top || constraints.hit.bottom) {
+        constraints.hit.left = false;
+        constraints.hit.right = false;
+        moving_object->collision_solid(constraints.hit);
+      }
+    }
 
-      // test in y direction first, then x direction
-      moving_object->dest.move(Vector(-movement.x, 0));
-      for(int i = 0; i < 2; ++i) {
-        bool res = collision_static(moving_object, Vector(0, movement.y));
-        if(res)
-          break;
+    constraints = Constraints();
+    for(int i = 0; i < 2; ++i) {
+      collision_static(&constraints, movement, dest, *moving_object);
+      if(!constraints.has_constraints())
+        break;
+
+      // apply calculated vertical constraints
+      if(constraints.right < INFINITY) {
+        float width = constraints.right - constraints.left;
+        if(width + SHIFT_DELTA < owidth) {
+          printf("Object %p crushed horizontally... L:%f R:%f\n", moving_object,
+              constraints.left, constraints.right);
+          CollisionHit h;
+          h.left = true;
+          h.right = true;
+          h.crush = true;
+          moving_object->collision_solid(h);
+        } else {
+          dest.p2.x = constraints.right - DELTA;
+          dest.p1.x = dest.p2.x - owidth;
+        }
+      } else if(constraints.left > -INFINITY) {
+        dest.p1.x = constraints.left + DELTA;
+        dest.p2.x = dest.p1.x + owidth;
       }
-      moving_object->dest.move(Vector(movement.x, 0)); 
-      for(int i = 0; i < 2; ++i) {
-        bool res = collision_static(moving_object, Vector(movement.x, 0));
-        if(res)
-          break;
+    }
+   
+    if(constraints.has_constraints()) {
+      moving_object->collision_solid(constraints.hit);
+    }    
+    
+    // an extra pass to make sure we're not crushed horizontally
+    constraints = Constraints();
+    collision_static(&constraints, movement, dest, *moving_object);
+    if(constraints.bottom < INFINITY) {
+      float height = constraints.bottom - constraints.top;
+      if(height + SHIFT_DELTA < oheight) {
+        printf("Object %p crushed vertically...\n", moving_object);
+        CollisionHit h;
+        h.top = true;
+        h.bottom = true;
+        h.crush = true;
+        moving_object->collision_solid(h); 
       }
     }
   }
@@ -1022,7 +1091,14 @@ Sector::handle_collisions()
          || !moving_object_2->is_valid())
         continue;
 
-      collision_object(moving_object, moving_object_2);
+      if(intersects(moving_object->dest, moving_object_2->dest)) {
+        Vector normal;
+        CollisionHit hit;
+        get_hit_normal(moving_object->dest, moving_object_2->dest,
+                       hit, normal);
+        moving_object->collision(*moving_object_2, hit);
+        moving_object_2->collision(*moving_object, hit);
+      }
     } 
   }
 
@@ -1059,6 +1135,8 @@ Sector::handle_collisions()
 bool
 Sector::is_free_space(const Rect& rect) const
 {
+  using namespace collision;
+  
   // test with all tiles in this rectangle
   int starttilex = int(rect.p1.x) / 32;
   int starttiley = int(rect.p1.y) / 32;
@@ -1082,7 +1160,7 @@ Sector::is_free_space(const Rect& rect) const
         || !moving_object->is_valid())
       continue;
 
-    if(Collision::intersects(rect, moving_object->get_bbox()))
+    if(intersects(rect, moving_object->get_bbox()))
       return false;
   }
 
@@ -1095,17 +1173,9 @@ Sector::add_bullet(const Vector& pos, float xm, Direction dir)
   // TODO remove this function and move these checks elsewhere...
 
   Bullet* new_bullet = 0;
-  if(player_status->bonus == FIRE_BONUS) {
-    if((int)bullets.size() >= player_status->max_fire_bullets)
-      return false;
-    new_bullet = new Bullet(pos, xm, dir, FIRE_BULLET);
-  } else if(player_status->bonus == ICE_BONUS) {
-    if((int)bullets.size() >= player_status->max_ice_bullets)
-      return false;
-    new_bullet = new Bullet(pos, xm, dir, ICE_BULLET);
-  } else {
+  if((int)bullets.size() >= player_status->max_fire_bullets)
     return false;
-  }
+  new_bullet = new Bullet(pos, xm, dir);
   add_object(new_bullet);
 
   sound_manager->play("sounds/shoot.wav");
@@ -1121,12 +1191,6 @@ Sector::add_smoke_cloud(const Vector& pos)
 }
 
 void
-Sector::add_floating_text(const Vector& pos, const std::string& text)
-{
-  add_object(new FloatingText(pos, text));
-}
-
-void
 Sector::play_music(MusicType type)
 {
   currentmusic = type;
index b2ee219..0ed2f4c 100644 (file)
@@ -32,6 +32,9 @@ namespace lisp {
 class Lisp;
 class Writer;
 }
+namespace collision {
+class Constraints;
+}
 
 class Rect;
 class Sprite;
@@ -40,7 +43,6 @@ class Player;
 class Camera;
 class TileMap;
 class Bullet;
-class CollisionGrid;
 class ScriptInterpreter;
 class SpawnPoint;
 class MovingObject;
@@ -107,8 +109,7 @@ public:
   
   bool add_bullet(const Vector& pos, float xm, Direction dir);
   bool add_smoke_cloud(const Vector& pos);
-  void add_floating_text(const Vector& pos, const std::string& text);
-                                                                                
   /** get currently activated sector. */
   static Sector* current()
   { return _current; }
@@ -126,7 +127,8 @@ public:
     return total;
   }
 
-  void collision_tilemap(const Rect& dest, const Vector& movement, CollisionHit& hit) const;
+  void collision_tilemap(collision::Constraints* constraints,
+      const Vector& movement, const Rect& dest) const;
 
   /** Checks if at the specified rectangle are gameobjects with STATIC flag set
    * (or solid tiles from the tilemap).
@@ -177,8 +179,8 @@ private:
    * returns true if the collision detection should be aborted for this object
    * (because of ABORT_MOVE in the collision response or no collisions)
    */
-  bool collision_static(MovingObject* object, const Vector& movement);
-
+  void collision_static(collision::Constraints* constraints,
+      const Vector& movement, const Rect& dest, GameObject& object);
   
   GameObject* parse_object(const std::string& name, const lisp::Lisp& lisp);
 
@@ -197,8 +199,6 @@ private:
  
   MusicType currentmusic;
 
-  std::auto_ptr<CollisionGrid> grid;
-
   HSQOBJECT sector_table;
   /// sector scripts
   typedef std::vector<HSQOBJECT> ScriptList;