line with ellipse/circle collision

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
NotARaptor
Citizen
Posts: 59
Joined: Thu Feb 22, 2018 3:15 pm

Re: line with ellipse/circle collision

Post by NotARaptor » Thu Mar 01, 2018 2:50 pm

Hello!

Sorry, new here - first post and all that. I saw this thread and thought I'd give it a go.

Treating the ellipses as polylines, this code calculates the intersections of line segments and ellipses - it seems pretty efficient for most use-cases, but I'm sure it could be improved.

Screenshot:
ellipses-and-segments.png
ellipses-and-segments.png (183.17 KiB) Viewed 1078 times
Code:
main.lua
(11.08 KiB) Downloaded 46 times

p0co
Prole
Posts: 3
Joined: Tue Mar 06, 2018 1:11 am

Re: line with ellipse/circle collision

Post by p0co » Mon Mar 19, 2018 12:41 am

Hi Guys,

I need a ball to go through a line, when it does I increase the player's score. Similar to a soccer goal, but the line is moving.

I dont want the ball to bounce off the line, I need it to go through it, but still trigger a collision so I can increase the players score.

I want to use physics. The ball has a body and shape of a circle - but how shall I do the line ?

I have considered not using physics but the maths calculations for this may seem over kill and slow the game down ?

How shall I do this ?


The game is attached. .. to play just click drag the mouse to move the white ball. between the red and blue ball to score the goal past that line. In the attached example, I far I have tried newEdgeShape for the line, but that doesnt seem to be working ...

Please help
Attachments
happymoon.love
(1.47 MiB) Downloaded 32 times

User avatar
ivan
Party member
Posts: 1526
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: line with ellipse/circle collision

Post by ivan » Mon Mar 19, 2018 6:08 am

With "EdgeShape" you have to destroy and create the fixture each frame as the balls move around.
Luckily, this isn't very expensive as you are dealing with just one edge.

User avatar
pgimeno
Party member
Posts: 1896
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

Re: line with ellipse/circle collision

Post by pgimeno » Mon Mar 19, 2018 12:45 pm

I wouldn't use collisions for this. Instead, I suggest using intersection of two segments. Let me explain.

While playing I ran into this situation:
HappyMoon-shortshot.png
HappyMoon-shortshot.png (45.87 KiB) Viewed 979 times
I fell short of crossing the line. If you consider a collision as scoring, you would be granting a point there. You should then ignore subsequent collisions until it stops colliding, in order to not grant more than one point every time.

My suggestion, however, is to score a point whenever the ball's centre crosses the line. To detect that, imagine the line between the ball's position in the previous frame and the ball's position in the current frame. If that (short) line segment crosses the goal line, make the player score. Here's an algorithm for detecting intersection of two line segments:

https://stackoverflow.com/questions/563 ... -intersect

Note however that in the case I ran into above, it is very easy to score multiple times, by making the shots very short so they cross the line.

Edit: One suggestion to prevent cheating like that is to score only when the goal line is crossed in one direction, e.g. with the blue ball on the left, and to remove a point when it's crossed in the other direction. I've not done the math to confirm, but that can probably be detected using the sign of rxs.

p0co
Prole
Posts: 3
Joined: Tue Mar 06, 2018 1:11 am

Re: line with ellipse/circle collision

Post by p0co » Tue Mar 20, 2018 8:59 am

pgimeno wrote:
Mon Mar 19, 2018 12:45 pm
I wouldn't use collisions for this. Instead, I suggest using intersection of two segments. Let me explain.

My suggestion, however, is to score a point whenever the ball's centre crosses the line. To detect that, imagine the line between the ball's position in the previous frame and the ball's position in the current frame. If that (short) line segment crosses the goal line, make the player score. Here's an algorithm for detecting intersection of two line segments:

https://stackoverflow.com/questions/563 ... -intersect

Note however that in the case I ran into above, it is very easy to score multiple times, by making the shots very short so they cross the line.
Initially I wanted to use collisions, because I thought using my intersection function would be computationally too slow ??

Regarding the cheating aspect: I intend to swap the position of the white ball, with the blue or red, after each turn. So the play doesn't cheat by making short pushes back and forward.

So I don't need the centre of the ball as the point of collision with the line. As I eliminate cheating in other ways.

I need the edge of the ball to touch the line to score.

I have tried making the line a EdgeShape, but that doesn't seem to act like a line for my case.

Below is the code for the goal / line .. Can you please help? And many thanks in advanced, I hope to use shaders and make this look beautiful after this 1 hurdle is resolved.

Code: Select all

goal = {}

goal.x1 = 0
goal.y1 = 0
goal.x2 = 0
goal.y2 = 0

goal.message = "goal: "
goal.drawMessage = function (self)
	love.graphics.print(self.message, 20, 60)
end

goal.body = love.physics.newBody(world, goal.x1, goal.y1, "dynamic")
goal.shape = love.physics.newEdgeShape( red.body:getX(),red.body:getY(), blue.body:getX(), blue.body:getY() )
goal.fixture = love.physics.newFixture(goal.body, goal.shape)

goal.fixture:setUserData("Goal")

goal.update = function(self)
	self.x1 = red.body:getX()
	self.y1 = red.body:getY()
	self.x2 = blue.body:getX()
	self.y2 = blue.body:getY()
end

goal.draw = function(self)
	love.graphics.setColor(55, 150, 150)
	love.graphics.setLineStyle( 'smooth' )
	love.graphics.setLineWidth( 1 )
	love.graphics.line( self.x1 , self.y1 , self.x2 , self.y2 )
	love.graphics.setColor(250, 250, 250)
end

goal.updateMessage = function (self)
	self.x1, self.y1, self.x2, self.y2 = goal.shape:getPoints( )
	goal.message = 	"x1: " .. self.x1 .. 
					"\ny1: " .. self.y1 .. 
					"\nx2: " .. self.x2 .. 
					"\ny2: " .. self.y2 .. 
					"\n\n World" .. goal.body:getWorldPoints(goal.shape:getPoints()) .. "\n "
end

User avatar
pgimeno
Party member
Posts: 1896
Joined: Sun Oct 18, 2015 2:58 pm
Location: Valencia, ES

Re: line with ellipse/circle collision

Post by pgimeno » Tue Mar 20, 2018 12:34 pm

p0co wrote:
Tue Mar 20, 2018 8:59 am
Initially I wanted to use collisions, because I thought using my intersection function would be computationally too slow ??
I don't think so. You probably can sustain hundreds of such calculations per frame.
p0co wrote:
Tue Mar 20, 2018 8:59 am
Regarding the cheating aspect: I intend to swap the position of the white ball, with the blue or red, after each turn. So the play doesn't cheat by making short pushes back and forward.
Nice solution too. I like yours better than mine.
p0co wrote:
Tue Mar 20, 2018 8:59 am
So I don't need the centre of the ball as the point of collision with the line. As I eliminate cheating in other ways.
Well, that solution was not about cheating; my proposal about cheating had to do with crossing the line in one sense only. That solution was about solving the scoring problem. It's intuitive for players to score a goal when your ball's centre crosses the line. To me, just touching the line does not feel so much like a reason to score. It's also a very lightweight calculation and I still recommend it over using physics.

You can still make the collision detection the way you want, by finding the point that is closest to the line from the centre of the ball, checking that it's within the segment limits, and then measuring the distance and comparing it to the radius. That's also lightweight (not so much as the centre crossing one but still doable many times per frame).

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 8 guests