dispenser can now launch snowballs and bouncingsnowballs
[supertux.git] / src / sector.cpp
index e097420..c5b81a8 100644 (file)
@@ -44,6 +44,7 @@
 #include "math/aatriangle.h"
 #include "object/coin.h"
 #include "object/block.h"
+#include "object/invisible_block.h"
 #include "object/platform.h"
 #include "trigger/door.h"
 #include "object/bullet.h"
@@ -53,7 +54,9 @@
 #include "badguy/flame.h"
 #include "badguy/mriceblock.h"
 #include "badguy/mrbomb.h"
+#include "badguy/dispenser.h"
 #include "trigger/sequence_trigger.h"
+#include "trigger/secretarea_trigger.h"
 
 Sector* Sector::_current = 0;
 
@@ -121,6 +124,7 @@ Sector::parseObject(const std::string& name, LispReader& reader)
         return 0;
       }
       solids = tilemap;
+      fix_old_tiles();
     }
     return tilemap;
   } else if(name == "particles-snow") {
@@ -133,6 +137,8 @@ Sector::parseObject(const std::string& name, LispReader& reader)
     return partsys;
   } else if(name == "door") {
     return new Door(reader);
+  } else if(name == "secretarea") {
+    return new SecretAreaTrigger(reader);
   } else if(name == "platform") {
     return new Platform(reader);
   } else if(name == "jumpy" || name == "money") {
@@ -147,6 +153,8 @@ Sector::parseObject(const std::string& name, LispReader& reader)
     return new MrIceBlock(reader);
   } else if(name == "mrbomb") {
     return new MrBomb(reader);
+  } else if(name == "dispenser") {
+    return new Dispenser(reader);
   }
 #if 0
     else if(badguykind_from_string(name) != BAD_INVALID) {
@@ -157,8 +165,8 @@ Sector::parseObject(const std::string& name, LispReader& reader)
       return new FlyingPlatform(reader);
 #endif
 
-   std::cerr << "Unknown object type '" << name << "'.\n";
-   return 0;
+  std::cerr << "Unknown object type '" << name << "'.\n";
+  return 0;
 }
 
 void
@@ -275,31 +283,7 @@ Sector::parse_old_format(LispReader& reader)
     solids = tilemap;
     add_object(tilemap);
 
-    // hack for now...
-    for(size_t x=0; x < solids->get_width(); ++x) {
-      for(size_t y=0; y < solids->get_height(); ++y) {
-        const Tile* tile = solids->get_tile(x, y);
-
-        if(tile->attributes & Tile::COIN) {
-          Coin* coin = new Coin(Vector(x*32, y*32));
-          add_object(coin);
-          solids->change(x, y, 0);
-        } else if(tile->attributes & Tile::FULLBOX) {
-          BonusBlock* block = new BonusBlock(Vector(x*32, y*32), tile->data);
-          add_object(block);
-          solids->change(x, y, 0);
-        } else if(tile->attributes & Tile::BRICK) {
-          Brick* brick = new Brick(Vector(x*32, y*32), tile->data);
-          add_object(brick);
-          solids->change(x, y, 0);
-        } else if(tile->attributes & Tile::GOAL) {
-          SequenceTrigger* trigger = new SequenceTrigger(Vector(x*32, y*32),
-              "endsequence");
-          add_object(trigger);
-          solids->change(x, y, 0);
-        }
-      }                                                   
-    }
+    fix_old_tiles();
   }
 
   if(reader.read_int_vector("background-tm", tiles)) {
@@ -364,6 +348,35 @@ Sector::parse_old_format(LispReader& reader)
 }
 
 void
+Sector::fix_old_tiles()
+{
+  // hack for now...
+  for(size_t x=0; x < solids->get_width(); ++x) {
+    for(size_t y=0; y < solids->get_height(); ++y) {
+      const Tile* tile = solids->get_tile(x, y);
+      Vector pos(x*32, y*32);
+      
+      if(tile->id == 112) {
+        add_object(new InvisibleBlock(pos));
+        solids->change(x, y, 0);
+      } else if(tile->attributes & Tile::COIN) {
+        add_object(new Coin(pos));
+        solids->change(x, y, 0);
+      } else if(tile->attributes & Tile::FULLBOX) {
+        add_object(new BonusBlock(pos, tile->data));
+        solids->change(x, y, 0);
+      } else if(tile->attributes & Tile::BRICK) {
+        add_object(new Brick(pos, tile->data));
+        solids->change(x, y, 0);
+      } else if(tile->attributes & Tile::GOAL) {
+        add_object(new SequenceTrigger(pos, "endsequence"));
+        solids->change(x, y, 0);
+      }
+    }                                                   
+  }
+}
+
+void
 Sector::write(LispWriter& writer)
 {
   writer.write_string("name", name);
@@ -625,7 +638,7 @@ Sector::collision_tilemap(MovingObject* object, int depth)
   CollisionHit temphit, hit;
   Rectangle dest = object->get_bbox();
   dest.move(object->movement);
-  hit.depth = -1;
+  hit.time = -1; // represents an invalid value
   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);
@@ -658,14 +671,16 @@ Sector::collision_tilemap(MovingObject* object, int depth)
             break;
         }
 
-        if(Collision::rectangle_aatriangle(temphit, dest, triangle)) {
-          if(temphit.depth > hit.depth)
+        if(Collision::rectangle_aatriangle(temphit, dest, object->movement,
+              triangle)) {
+          if(temphit.time > hit.time)
             hit = temphit;
         }
       } else { // normal rectangular tile
         Rectangle rect(x*32, y*32, (x+1)*32, (y+1)*32);
-        if(Collision::rectangle_rectangle(temphit, dest, rect)) {
-          if(temphit.depth > hit.depth)
+        if(Collision::rectangle_rectangle(temphit, dest,
+              object->movement, rect)) {
+          if(temphit.time > hit.time)
             hit = temphit;
         }
       }
@@ -673,7 +688,7 @@ Sector::collision_tilemap(MovingObject* object, int depth)
   }
 
   // did we collide at all?
-  if(hit.depth == -1)
+  if(hit.time < 0)
     return;
  
   // call collision function
@@ -686,7 +701,7 @@ Sector::collision_tilemap(MovingObject* object, int depth)
       return;
   }
   // move out of collision and try again
-  object->movement += hit.normal * (hit.depth + .001);
+  object->movement += hit.normal * (hit.depth + .05);
   collision_tilemap(object, depth+1);
 }
 
@@ -698,19 +713,26 @@ Sector::collision_object(MovingObject* object1, MovingObject* object2)
   dest1.move(object1->get_movement());
   Rectangle dest2 = object2->get_bbox();
   dest2.move(object2->get_movement());
-  if(Collision::rectangle_rectangle(hit, dest1, dest2)) {
-    HitResponse response = object1->collision(*object2, hit);
-    if(response == ABORT_MOVE) {
-      object1->movement = Vector(0, 0);
-    } else if(response == CONTINUE) {
-      object1->movement += hit.normal * (hit.depth/2 + .001);
-    }
+
+  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;
-    response = object2->collision(*object1, hit);
-    if(response == ABORT_MOVE) {
-      object2->movement = Vector(0, 0);
-    } else if(response == CONTINUE) {
-      object2->movement += hit.normal * (hit.depth/2 + .001);
+    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 + .05);
+    } else if(response2 != CONTINUE) {
+      if(response2 == ABORT_MOVE)
+        object2->movement = Vector(0, 0);
+      if(response1 == CONTINUE)
+        object1->movement += -hit.normal * (hit.depth + .05);
+    } else {
+      object1->movement += -hit.normal * (hit.depth/2 + .05);
+      object2->movement += hit.normal * (hit.depth/2 + .05);
     }
   }
 }
@@ -727,7 +749,7 @@ Sector::collision_handler()
     MovingObject* movingobject = dynamic_cast<MovingObject*> (gameobject);
     if(!movingobject)
       continue;
-  
+
     // collision with tilemap
     if(! (movingobject->movement == Vector(0, 0)))
       collision_tilemap(movingobject, 0);
@@ -745,7 +767,7 @@ Sector::collision_handler()
 
       collision_object(movingobject, movingobject2);
     }
-    
+
     movingobject->bbox.move(movingobject->get_movement());
     movingobject->movement = Vector(0, 0);
   }
@@ -791,13 +813,6 @@ Sector::add_smoke_cloud(const Vector& pos)
   return true;
 }
 
-bool
-Sector::add_particles(const Vector& epicenter, int min_angle, int max_angle, const Vector& initial_velocity, const Vector& acceleration, int number, Color color, int size, int life_time, int drawing_layer)
-{
-  add_object(new Particles(epicenter, min_angle, max_angle, initial_velocity, acceleration, number, color, size, life_time, drawing_layer));
-  return true;
-}
-
 void
 Sector::add_floating_text(const Vector& pos, const std::string& text)
 {