So I'm a beginner to ruby and I was playing around with collision detection in ruby 2d. I have a controllable square and a square that stays still. My question is how do to detect when the square collides with the circle.
This is my main code the rest is just controls to move the square
@square = Square.new(x: 10, y: 20, size: 25, color: 'blue')
@circle = Circle.new(x: 100, y: 100, radius: 10, color: 'red')
@x_speed = 0
@y_speed = 0
game = Game.new
class Game
@score = 0
end
and this is what is updating,
update do
if game.square_hit_circle?(square.x, square.y)
puts "hit"
end
end
Here is what square_hit_circle? means
def square_hit_circle?(x, y)
@circle_x == x && @circle_y == y
end
I thought it might be of interest to provide a solution that does not make use of the
ruby2dgem, so show how the required calculations are performed.Example data
Suppose
This looks like the following, with
Ythe center of the circle and theX's the corners of the square.Determine the sides of the rectangle
Select any of these corners (the first, say):
Determine which corner is farthest from
c1:Compute the sides of the square as arrays of endpoints:
Let's make a method to do this.
Compute intercept and slope for the lines coincident with the sides of the square
For each of these sides there is a line in space that is coincide with the side. Each of these lines is described by an intercept
iand a slopeb, such that for any value ofxthe point[x, y]is on the line ify = i + b*x. We can compute the intercept and slope for each of these lines.Note:
Compute the points where the circle intersects lines coincident with the sides
Let
Suppose we consider a side for which the coincident line has intercept
iand slopes. We then have the quadratic expression:(cx-x)2 + (cy-i-s*x)2 = radius2
By defining:
e = cy - i
the equation reduces to:
cx2 - 2*cx*x + x2 + e2 - 2*e*s*x + s2*x2 = radius2
or
(1 + s2)*x2 + 2*(-cx -e*s)*x + cx2 + e2 - radius2 = 0
or
ax2 + bx + c = 0
where:
a = (1 + s2)
b = -2*(cx + e*s)
c = cx2 + e2 - radius2
The real root or roots, if it/they exist, are given by the quadratic equation. First compute the discriminate:
d = b2 - 4*a*c
If the discriminate is negative the quadratic has no real roots (only complex roots). Here that means the circle is not large enough to intersect the line that is coincident with this side.
If the discriminate
dis positive, there are two real roots (one real root only ifdis zero). Let:w = d1/2
The roots (values of
x) are:(-b + w)/(2*a)
and
(-b - w)/(2*a)
Let's wrap this in a method:
It remains to do the following.
Determine if one of the points of intersection is on a side
That is simple and straightforward:
For example:
Putting it all together