Skip to content

Resolving Collisions

noooway edited this page Jan 11, 2017 · 12 revisions

Ok, we can detect collisions. Now it's time to deal with how our objects react on them, i.e. with the collision resolution.

We detect an overlap and then react somehow. It turns out convenient to return from the collisions.check_rectangles_overlap not only the fact of the overlap but also a displacement necessary to resolve the overlap. I suppose that the shape b is the one that has to be displaced, and the a should remain in place. If the center of the a is to the left from the center of b, the b is shifted right to resolve the overlap, in the other case - left ( shift is negative ). Same for y-axis.

function collisions.check_rectangles_overlap( a, b )
   local overlap = false
   local shift_b_x, shift_b_y = 0, 0
   if not( a.x + a.width < b.x  or b.x + b.width < a.x  or
           a.y + a.height < b.y or b.y + b.height < a.y ) then
      overlap = true
      if ( a.x + a.width / 2 ) < ( b.x + b.width / 2 ) then
         shift_b_x = ( a.x + a.width ) - b.x                    --(*1a)
      else 
         shift_b_x = a.x - ( b.x + b.width )                    --(*1b)
      end
      if ( a.y + a.height / 2 ) < ( b.y + b.height / 2 ) then
         shift_b_y = ( a.y + a.height ) - b.y                   --(*2) 
      else
         shift_b_y = a.y - ( b.y + b.height )                   --(*2)
      end      
   end
   return overlap, shift_b_x, shift_b_y                         --(*3)
end

(*1a): b to the right from the center of a; shift b to the right
(*1b): b to the left from a; shift to the left.
(*2): same for y axis.
(*3): shift is returned along with the fact of the overlap

Now, in collision-resolution functions we need to check for overlap, and if it happes - react on in. For platform-ball collision, there is no need to modify the platform, but it is necessary to change the ball direction.

function collisions.ball_platform_collision( ball, platform )
   local overlap, shift_ball_x, shift_ball_y
   local a = { x = platform.position_x,
	       y = platform.position_y,
	       width = platform.width,
	       height = platform.height }
   local b = { x = ball.position_x - ball.radius,
	       y = ball.position_y - ball.radius,
	       width = 2 * ball.radius,
	       height = 2 * ball.radius }
   overlap, shift_ball_x, shift_ball_y =
      collisions.check_rectangles_overlap( a, b )   
   if overlap then
      ball.rebound( shift_ball_x, shift_ball_y )
   end      
end

In ball.rebound function the overlap values are passed. I determine the minimal one of them, zero the other one and shift the ball by that value. Besides, the speed direction along the shift axis is reversed.

function ball.rebound( shift_ball_x, shift_ball_y )
   local big_enough_overlap = 0.5
   local min_shift = math.min( math.abs( shift_ball_x ), math.abs( shift_ball_y ) )
   if math.abs( shift_ball_x ) == min_shift then
      shift_ball_y = 0
   else
      shift_ball_x = 0
   end
   ball.position_x = ball.position_x + shift_ball_x
   ball.position_y = ball.position_y + shift_ball_y
   if math.abs( shift_ball_x ) > big_enough_overlap then
      ball.speed_x  = -ball.speed_x
   end
   if math.abs( shift_ball_y ) > big_enough_overlap then
      ball.speed_y  = -ball.speed_y
   end
end

Other collisions are resolved in a similar fashion. I'll mention ball-brick collision.

function collisions.ball_bricks_collision( ball, bricks )
   .....
   for i, brick in pairs( bricks.current_level_bricks ) do   
      .....
      overlap, shift_ball_x, shift_ball_y =
      	 collisions.check_rectangles_overlap( a, b )
      if overlap then	 
	 ball.rebound( shift_ball_x, shift_ball_y )
	 bricks.brick_hit_by_ball( i, brick,
				   shift_ball_x, shift_ball_y )
      end
   end
end

The brick is removed on collision. This is done by table.remove function. It is also necessary to pass the index of the brick.

function bricks.brick_hit_by_ball( i, brick,
				   shift_ball_x, shift_ball_y )
   local big_enough_overlap = 0.5
   if math.abs( shift_ball_x ) > big_enough_overlap or
      math.abs( shift_ball_y ) > big_enough_overlap then
	 table.remove( bricks.current_level_bricks, i )
   end
end

    Home
    Acknowledgements
    Todo

Chapter 1: Prototype

  1. The Ball, The Brick, The Platform
  2. Game Objects as Lua Tables
  3. Bricks and Walls
  4. Detecting Collisions
  5. Resolving Collisions
  6. Levels

    Appendix A: Storing Levels as Strings
    Appendix B: Optimized Collision Detection (draft)

Chapter 2: General Code Structure

  1. Splitting Code into Several Files
  2. Loading Levels from Files
  3. Straightforward Gamestates
  4. Advanced Gamestates
  5. Basic Tiles
  6. Different Brick Types
  7. Basic Sound
  8. Game Over

    Appendix C: Stricter Modules (draft)
    Appendix D-1: Intro to Classes (draft)
    Appendix D-2: Chapter 2 Using Classes.

Chapter 3 (deprecated): Details

  1. Improved Ball Rebounds
  2. Ball Launch From Platform (Two Objects Moving Together)
  3. Mouse Controls
  4. Spawning Bonuses
  5. Bonus Effects
  6. Glue Bonus
  7. Add New Ball Bonus
  8. Life and Next Level Bonuses
  9. Random Bonuses
  10. Menu Buttons
  11. Wall Tiles
  12. Side Panel
  13. Score
  14. Fonts
  15. More Sounds
  16. Final Screen
  17. Packaging

    Appendix D: GUI Layouts
    Appendix E: Love-release and Love.js

Beyond Programming:

  1. Game Design
  2. Minimal Marketing (draft)
  3. Finding a Team (draft)

Archive

Clone this wiki locally