* Added a boolean "disable-physics" property to powerups. We can't afford losing...
[supertux.git] / src / object / particlesystem_interactive.cpp
index d411f89..edb2cbc 100644 (file)
 #include <iostream>
 #include <cmath>
 
-#include "particlesystem_interactive.h"
-#include "video/drawing_context.h"
-#include "lisp/parser.h"
-#include "lisp/lisp.h"
-#include "lisp/writer.h"
-#include "resources.h"
-#include "main.h"
+#include "particlesystem_interactive.hpp"
+#include "video/drawing_context.hpp"
+#include "lisp/parser.hpp"
+#include "lisp/lisp.hpp"
+#include "lisp/writer.hpp"
+#include "resources.hpp"
+#include "main.hpp"
 
-#include "tile.h"
-#include "tilemap.h"
-#include "math/aatriangle.h"
-#include "collision.h"
-#include "collision_hit.h"
-#include "object/camera.h"
-#include "object/rainsplash.h"
-#include "badguy/bomb.h"
+#include "tile.hpp"
+#include "tilemap.hpp"
+#include "math/aatriangle.hpp"
+#include "collision.hpp"
+#include "collision_hit.hpp"
+#include "object/camera.hpp"
+#include "object/rainsplash.hpp"
+#include "badguy/bomb.hpp"
 
-//TODO: Dynamically create splashes at collision spots
-//      Find a way to make rain collide with objects like bonus blocks
+//TODO: Find a way to make rain collide with objects like bonus blocks
 //      Add an option to set rain strength
+//      Fix rain being "respawned" over solid tiles
 ParticleSystem_Interactive::ParticleSystem_Interactive()
 {
     virtual_width = SCREEN_WIDTH;
@@ -69,7 +69,7 @@ void ParticleSystem_Interactive::draw(DrawingContext& context)
     context.pop_transform();
 }
 
-bool
+int
 ParticleSystem_Interactive::collision(Particle* object, Vector movement)
 {
   TileMap* solids = Sector::current()->solids;
@@ -80,6 +80,7 @@ ParticleSystem_Interactive::collision(Particle* object, Vector movement)
   x2 = x1 + 32 + movement.x;
   y1 = object->pos.y;
   y2 = y1 + 32 + movement.y;
+  bool water = false;
   
   // test with all tiles in this rectangle
   int starttilex = int(x1-1) / 32;
@@ -96,8 +97,10 @@ ParticleSystem_Interactive::collision(Particle* object, Vector movement)
       const Tile* tile = solids->get_tile(x, y);
       if(!tile)
         continue;
-      // skip non-solid tiles
-      if(!(tile->getAttributes() & Tile::SOLID))
+      // skip non-solid tiles, except water
+      if (tile->getAttributes() & Tile::WATER)
+        water = true;
+      if(!water && !(tile->getAttributes() & Tile::SOLID))
         continue;
 
       if(tile->getAttributes() & Tile::SLOPE) { // slope tile
@@ -123,14 +126,24 @@ ParticleSystem_Interactive::collision(Particle* object, Vector movement)
   }
   
   // did we collide at all?
-  if(hit.time < 0)
-    return false; else return true;
+  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
+    }
+  }
 }
 
 RainParticleSystem::RainParticleSystem()
 {
-    rainimages[0] = new Surface("images/objects/particles/rain0.png", true);
-    rainimages[1] = new Surface("images/objects/particles/rain1.png", true);
+    rainimages[0] = new Surface("images/objects/particles/rain0.png");
+    rainimages[1] = new Surface("images/objects/particles/rain1.png");
 
     virtual_width = SCREEN_WIDTH * 2;
 
@@ -182,21 +195,23 @@ void RainParticleSystem::update(float elapsed_time)
         float abs_y = Sector::current()->camera->get_translation().y;
         particle->pos.y += movement;
         particle->pos.x -= movement;
-        if ((particle->pos.y > SCREEN_HEIGHT + abs_y) || (collision(particle, Vector(-movement, movement)))) {
+        int col = collision(particle, Vector(-movement, movement));
+        if ((particle->pos.y > SCREEN_HEIGHT + abs_y) || (col >= 0)) {
             //Create rainsplash
-            if (particle->pos.y <= SCREEN_HEIGHT + abs_y){
-              //TODO: Find out at which side of the tile the collision happens
-              bool vertical = false;
+            if ((particle->pos.y <= SCREEN_HEIGHT + abs_y) && (col >= 1)){
+              bool vertical = (col == 2);
               int splash_x, splash_y;
-              if (vertical) {
-                splash_x = int(particle->pos.x) - (int(particle->pos.x) % 32) + 32;
-                splash_y = int(particle->pos.y);                
-              }
-              else {
+              if (!vertical) { //check if collision happened from above
                 splash_x = int(particle->pos.x);
                 splash_y = int(particle->pos.y) - (int(particle->pos.y) % 32) + 32;
+                Sector::current()->add_object(new RainSplash(Vector(splash_x, splash_y),vertical));
               }
-              Sector::current()->add_object(new RainSplash(Vector(splash_x, splash_y),vertical));
+              // Uncomment the following to display vertical splashes, too
+              /* else {
+                splash_x = int(particle->pos.x) - (int(particle->pos.x) % 32) + 32;
+                splash_y = int(particle->pos.y);
+                Sector::current()->add_object(new RainSplash(Vector(splash_x, splash_y),vertical));
+              } */
             }
             int new_x = (rand() % int(virtual_width)) + int(abs_x);
             int new_y = 0;
@@ -209,8 +224,8 @@ void RainParticleSystem::update(float elapsed_time)
 
 CometParticleSystem::CometParticleSystem()
 {
-    cometimages[0] = new Surface("images/creatures/mr_bomb/exploding-left-0.png", true);
-    cometimages[1] = new Surface("images/creatures/mr_bomb/exploding-left-0.png", true);
+    cometimages[0] = new Surface("images/creatures/mr_bomb/exploding-left-0.png");
+    cometimages[1] = new Surface("images/creatures/mr_bomb/exploding-left-0.png");
 
     virtual_width = SCREEN_WIDTH * 2;
 
@@ -262,8 +277,9 @@ void CometParticleSystem::update(float elapsed_time)
         float abs_y = Sector::current()->camera->get_translation().y;
         particle->pos.y += movement;
         particle->pos.x -= movement;
-        if ((particle->pos.y > SCREEN_HEIGHT + abs_y) || (collision(particle, Vector(-movement, movement)))) {
-            if (particle->pos.y <= SCREEN_HEIGHT + abs_y) {
+        int col = collision(particle, Vector(-movement, movement));
+        if ((particle->pos.y > SCREEN_HEIGHT + abs_y) || (col >= 0)) {
+            if ((particle->pos.y <= SCREEN_HEIGHT + abs_y) && (col >= 1)) {
               Sector::current()->add_object(new Bomb(particle->pos, LEFT));
             }
             int new_x = (rand() % int(virtual_width)) + int(abs_x);