Package: tecnoballz
Version: 0.92-2.1
Severity: normal
Tags: patch

The actual collision check between two sprites just check if their
"bounding box" intersects.
For fast moving object like balls, this is not enough since a ball can
go through another object if there is no step that intersect the other
object.
I tried to improve the collision detection for balls using some
polymorphic behaviour. ;) Just see the patch.

I'm not sure it is 100% ok since this is quite hard to test. But it just
looks good.

I also fixed another issue that made some balls lost even when the
bottom wall was activated.
Actually the top of the wall was under the "lost ball line", thus, some
balls were lost if they had a step between the "lost ball line" and the
top of the wall.


That's all

Celelibi

PS : I think this will be my last patch for tecnoballz. Or at least, my
last bug-fix. ;)


-- System Information:
Debian Release: 5.0
  APT prefers testing
  APT policy: (990, 'testing'), (600, 'unstable')
Architecture: i386 (i686)

Kernel: Linux 2.6.23.9 (SMP w/2 CPU cores; PREEMPT)
Locale: LANG=fr_FR, LC_CTYPE=fr_FR (charmap=ISO-8859-1)
Shell: /bin/sh linked to /bin/bash

Versions of packages tecnoballz depends on:
ii  libc6              2.7-16                GNU C Library: Shared libraries
ii  libgcc1            1:4.3.2-1             GCC support library
ii  libmikmod2         3.1.11-a-6            A portable sound library
ii  libogg0            1.1.3-4               Ogg Bitstream Library
ii  libsdl-image1.2    1.2.6-3               image loading library for Simple D
ii  libsdl-mixer1.2    1.2.8-4               mixer library for Simple DirectMed
ii  libsdl1.2debian    1.2.13-2              Simple DirectMedia Layer
ii  libsmpeg0          0.4.5+cvs20030824-2.2 SDL MPEG Player Library - shared l
ii  libstdc++6         4.3.2-1               The GNU Standard C++ Library v3
ii  libvorbisfile3     1.2.0.dfsg-3.1        The Vorbis General Audio Compressi
ii  tecnoballz-data    0.92-2.1              graphic, sound and music files for

tecnoballz recommends no packages.

tecnoballz suggests no packages.

-- no debconf information
diff -Naur tecnoballz-move-inverted/include/sprite_ball.h tecnoballz-collision-check/include/sprite_ball.h
--- tecnoballz-move-inverted/include/sprite_ball.h	2009-01-03 16:51:54.000000000 +0100
+++ tecnoballz-collision-check/include/sprite_ball.h	2009-01-04 20:24:58.000000000 +0100
@@ -84,7 +84,13 @@
     /** Top limit of ball in low-res */
     static const Sint32 Y_MINIMUM = 0;
     /** Bottom limit of ball low-res */
-    static const Sint32 Y_MAXIMUM = 230;
+    static const Sint32 Y_MAXIMUM = 232;
+
+
+    /** Previous X coordinate */
+    Sint32 previous_x_coord;
+    /** Previous Y coordinate */
+    Sint32 previous_y_coord;
 
   private:
     /** Ball direction from 0 to 64 step 4
@@ -107,9 +113,9 @@
     Sint16 *initial_velocities;
     /** Pointer to the current points of collision with a brick */
     Sint32 *brick_collision_points;
-    /* Strength of ball 1, 2 or 3 to decreasing brick strength */
+    /* Strength of ball 1, 2 or 3 to decrease brick strength */
     Sint32 strength1;
-    /* Strength of ball 32, 64 or 96 to decreasing brick address */
+    /* Strength of ball 32, 64 or 96 to decrease brick address */
     Sint32 strength2;
     /** Time delay before ejection of the ball */
     Sint32 ejector_delay;
@@ -195,7 +201,7 @@
     void set_on_ejector (Uint32 eject_id, Uint32 otime = 1);
     void disable_stick ();
     void accelerate ();
-
+    virtual bool collision (sprite_object * sprite);
   private:
     void set_initial_values (sprite_paddle * paddle);
     void select_image ();
diff -Naur tecnoballz-move-inverted/include/sprite_object.h tecnoballz-collision-check/include/sprite_object.h
--- tecnoballz-move-inverted/include/sprite_object.h	2009-01-03 16:51:54.000000000 +0100
+++ tecnoballz-collision-check/include/sprite_object.h	2009-01-04 20:24:58.000000000 +0100
@@ -387,7 +387,8 @@
     void restore_rectangle_background ();
     void pull (sprite_object * sprite, Sint32 xoffset = 0, Sint32 yoffset = 0);
     void attract (sprite_object * sprite, Sint32 xoffset = 0, Sint32 yoffset = 0);
-    bool collision (sprite_object * sprite);
+    virtual bool collision (sprite_object * sprite);
+    virtual bool collision (Sint32 x1, Sint32 y1, Sint32 x2, Sint32 y2);
     void set_frame_delay (Sint32 delay);
     void set_frame_period (Sint32 period);
     bool play_animation_once ();
diff -Naur tecnoballz-move-inverted/src/controller_balls.cc tecnoballz-collision-check/src/controller_balls.cc
--- tecnoballz-move-inverted/src/controller_balls.cc	2009-01-03 16:51:54.000000000 +0100
+++ tecnoballz-collision-check/src/controller_balls.cc	2009-01-04 20:24:58.000000000 +0100
@@ -366,6 +366,10 @@
 	  continue;
 	}
 
+      /* Save previous position */
+      ball->previous_x_coord = ball->x_coord;
+      ball->previous_y_coord = ball->y_coord;
+
       /*  the ball is not sticked */
       if (ball->sticky_paddle_num == 0)
 	{
@@ -926,7 +930,7 @@
 }
 
 /**
- * Collisions of the balls with the 3 sides in the guarduans levels
+ * Collisions of the balls with the 3 sides in the guardians levels
  */
 void
 controller_balls::collisions_with_sides ()
diff -Naur tecnoballz-move-inverted/src/sprite_ball.cc tecnoballz-collision-check/src/sprite_ball.cc
--- tecnoballz-move-inverted/src/sprite_ball.cc	2009-01-03 16:51:53.000000000 +0100
+++ tecnoballz-collision-check/src/sprite_ball.cc	2009-01-04 20:24:57.000000000 +0100
@@ -360,6 +360,29 @@
     }
 }
 
+/**
+ * Check collision beetween a ball and another sprite.
+ * Override sprite_object::collision(sprite_object *).
+ * @param sprite Pointer to a sprite object
+ * @return true if collision occurs, otherwise false
+ */
+bool
+sprite_ball::collision (sprite_object * sprite)
+{
+  Sint32 x1 = previous_x_coord;
+  Sint32 y1 = previous_y_coord;
+  Sint32 x2 = x_coord;
+  Sint32 y2 = y_coord;
+  Sint32 w = collision_width;
+
+  /* Check collision between the four segments made by
+   * the "ball-box" during its motion */
+  return sprite->collision(x1, y1, x2, y2) ||
+         sprite->collision(x1 + w, y1, x2 + w, y2) ||
+         sprite->collision(x1, y1 + w, x2, y2 + w) ||
+         sprite->collision(x1 + w, y1 + w, x2 + w, y2 + w);
+}
+
 /** Collision points of the ball 1 with a brick */
 Sint32
 sprite_ball::brick_collision_points_1[8] = {
diff -Naur tecnoballz-move-inverted/src/sprite_object.cc tecnoballz-collision-check/src/sprite_object.cc
--- tecnoballz-move-inverted/src/sprite_object.cc	2009-01-03 16:51:54.000000000 +0100
+++ tecnoballz-collision-check/src/sprite_object.cc	2009-01-04 20:24:58.000000000 +0100
@@ -1720,6 +1720,84 @@
           y2 - (Sint32)collision_height < y1);
 }
 
+
+/**
+ * Check collision beetween a sprite and a segment
+ * @param sprite Pointer to a sprite object
+ * @return true if collision occurs, otherwise false
+ */
+bool
+sprite_object::collision (Sint32 x1, Sint32 y1, Sint32 x2, Sint32 y2)
+{
+  Sint32 xmin, xmax;
+  Sint32 ymin, ymax;
+
+  /* Swap points for x1 < x2 to be true */
+  if (x1 > x2)
+    {
+      Sint32 tmp = x2;
+      x2 = x1;
+      x1 = tmp;
+
+      tmp = y2;
+      y2 = y1;
+      y1 = tmp;
+    }
+  xmin = x1;
+  xmax = x2;
+
+  if (y1 < y2)
+    {
+      ymin = y1;
+      ymax = y2;
+    }
+  else
+    {
+      ymin = y2;
+      ymax = y1;
+    }
+
+  /* Condition sine qua none */
+  if (!(xmin < x_coord + collision_width &&
+        ymin < y_coord + collision_height &&
+        xmax > x_coord &&
+        ymax > y_coord))
+    {
+      return false;
+    }
+
+  /* Both points are in the "vertical band" */
+  if (xmin > x_coord && xmin < x_coord + collision_width &&
+      xmax > x_coord && xmax < x_coord + collision_width)
+    {
+      return true;
+    }
+
+  /* Check for diagonals and every remaining cases */
+  float alpha = (y2 - y1) / (x2 - x1);
+  Sint32 x0 = -alpha * x1 + y1;
+
+  if (x1 < x_coord)
+    {
+      Sint32 ytest = alpha * x_coord + x0;
+      if (ytest > y_coord && ytest < y_coord + collision_height)
+        {
+          return true;
+        }
+    }
+
+  if (x2 > x_coord + collision_width)
+    {
+      Sint32 ytest = alpha * (x_coord + collision_width) + x0;
+      if (ytest > y_coord && ytest < y_coord + collision_height)
+        {
+          return true;
+        }
+    }
+
+  return false;
+}
+
 /**
  * Set the frame delay and period, the speed of animation
  * @param delay time delay before next image

Reply via email to