Pages

Tuesday, July 7, 2020

Detecting collision algorithm

In the previous post, I talked about how I learned to build a basic game.

Take a look at the game here, play it, and come back.

One challenge I had while developing it, was how can I detect the collision between the square and the balls (I didn't give them cute names yet?!).

I held a paper and drew an imaginary frame that captures the square with a group of balls in different positions:
1- A square surrounded by 7 balls


I wanted to understand how I can know if any of these balls are touching the edges of the square.
Clearly, if the ball touches the square, then the distance between the centerline of the circle and the centerline of the square should equal (diameter+side)/2.
So, let's have a variable named touching that holds that distance. The problem was: which centerline should I consider: the horizontal or the vertical?
Consider this frame:

2- Vertical and horizontal centerlines


Each one gives different distances, and only one is a correct indication to a no collision, but using our human intuition is a start to understand how the natural algorithm works.

They are not touching, which means that the distance between the two centerlines should be greater than touching, which means that the natural algorithm picks the horizontal centerlines (the vertical centerlines says there's a collision!). By noticing multiple circles, I noticed a pattern: if the circle intersects with the vertical extension of the square, then we pick the vertical distance (between the horizontal centerlines), and if the circle intersects with the horizontal extension, we pick the horizontal distance:
3- The circle intersects with the vertical extension
Another example, ball number 4: it intersects with the horizontal extension of the square, then we consider the horizontal distance which is equal to touching.

Ok, the tough part is demystified, now we know how the algorithm will work, but how we know with which extension the circle intersects?
It's easy actually: we calculate the distance between the most right x and the most left x (of both the circle and the square), and the same for the y-axis, the one with greater value is the axis with the extension that intersects with the circle (if it's greater than diameter+side then the circle is outside the two square extensions, like circle #7). The code looks like:

right = Math.max(square.x+square.side, circle.x+circle.rad);
left = Math.min(square.x, circle.x-circle.rad);

bottom = Math.max(square.y+square.side, circle.y+circle.rad);
top = Math.min(square.y, circle.y-circle.rad);

if (right - left > down - top) {
//compare with horizontal distance
}
else {
//compare with vertical distance
}

/*These equations assume that the reference point of the square is at its top left corner, and the reference point of the circle is at its center*/

And that ends the collision algorithm. Maybe there's a known algorithm for this, maybe it's simpler, I didn't search, I got excited with the problem and started solving it my self.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.

How to do code reviews correctly

Introduction Code review is a special event in the life cycle of software development, it's where ownership is transferred from the deve...