Hi.I recently learned about collision detection between circles. However, How can I detect a collision between the edge of the circle and a circle inside that circle? In my case I am using 2 ellipses to create a circular track. However, I want to know when a ellipse between those circles collides with one of the edges. Here is what my situation looks like:
(Note the ball can be dragged with your finger)
supportedOrientations(LANDSCAPE_RIGHT)
-- Use this function to perform your initial setup
function setup()
print("Hello World!")
start=0
lastx = 0
lasty = 0
initx = WIDTH/2+3
inity = 690
ellipsepositionx = 0
ellipsepositiony = 0
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
drawboard()
drawcharacter()
end
function drawcharacter()
if(start==1)then
ellipse(CurrentTouch.x,CurrentTouch.y,55)
lastx = CurrentTouch.x
lasty = CurrentTouch.y
ellipsepositionx = CurrentTouch.x
ellipsepositiony = CurrentTouch.y
end
if(start==0)then
ellipse(initx,inity,55)
ellipsepositionx = initx
ellipsepositiony = inity
end
if(start==-1)then
ellipse(lastx,lasty,55)
ellipsepositionx = lastx
ellipsepositiony = lasty
end
end
function touched(touch)
if(CurrentTouch.state==BEGAN)then
if(start==0 and CurrentTouch.x>initx-20 and CurrentTouch.x<initx+20 and CurrentTouch.y<inity+20 and CurrentTouch.y>inity-20)then
start=1
end
end
if(CurrentTouch.state==ENDED and start==1)then
start=-1
end
end
function drawboard()
fill(0, 196, 255, 255)
-- Do your drawing here
ellipse(WIDTH/2,HEIGHT/2,770)
ellipse(WIDTH/2,HEIGHT/2,500)
fill(30, 255, 0, 255)
noStroke()
smooth()
rect(WIDTH/2,HEIGHT/2+248.5,5,130.7)
end
Touch between the 2 circles and drag the smaller circle. If you touch the inside or outside circle a message will appear in the center of the screen. You don’t need to use physics for this.
supportedOrientations(LANDSCAPE_ANY)
function setup()
w=WIDTH/2
h=HEIGHT/2
end
function draw()
background(40, 40, 50)
noFill()
stroke(255)
strokeWidth(4)
ellipse(w,h,WIDTH)
ellipse(w,h,WIDTH-300)
x=CurrentTouch.x
y=CurrentTouch.y
ellipse(x,y,60)
checkSmall(x,y,w,h,(WIDTH-240)/2)
checkLarge(x,y,w,h,(WIDTH-60)/2)
fill(255,0,0)
if small or large then
text("outside track",w,h)
end
end
function checkSmall(x,y,xc,yc,a)
small=false
if (x-xc)^2/a^2+(y-yc)^2/a^2 <= 1 then
small=true
end
end
function checkLarge(x,y,xc,yc,a)
large=false
if (x-xc)^2/a^2+(y-yc)^2/a^2 >= 1 then
large=true
end
end
@dave1707 - it doesn’t matter for this simple example, but power functions can really hurt your speed when you’re using them so many time a second. Also, it is neater to use a single function when the two of them are so similar. So how about this (untested)?
-- in draw....
small = IsInside(x,y,w,h,(WIDTH-240)/2)
large = not IsInside(x,y,w,h,(WIDTH-60)/2)
--using this function
function IsInside(x,y,xc,yc,a)
local xx,yy=x-xc, y-yc
return (xx*xx+yy*yy) / (a*a) <=1
end
@Ignatz I agree with you about the power functions and you’re right that a simple program like this won’t be affected that much. I was also thinking about combining the 2 functions, but I was just pulling code from existing programs I have and didn’t feel like changing anything.
@austinmccoy - something you should look at is using the vec2 functions (they are just pairs of numbers used to store x,y positions). There are several special functions for them, such as distance.
So you can test for collisions by measuring the distance between the centre and the centre of the moving ellipse, and if it is less than (the radius of the inner circle plus its own radius) or greater than (the radius of the outer circle less its own radius), then you have collided.
I know this is pretty much what you are doing, but here is how it looks with vec2’s (untested). You can see the rest of the special vec2 functions in the vectors section of the Codea reference. The advantage is partly simplicity, also they are faster and more efficient than writing your own code.
--using dave's code
ellipse(w,h,WIDTH)
ellipse(w,h,WIDTH-300)
x=CurrentTouch.x
y=CurrentTouch.y
ellipse(x,y,60)
--now the test
vecCentre=vec2(w,h) --put this in setup if it's not going to change
local d = vecCentre:dist(vec2(x,y)) --calculate distance between ellipse centres
if d < (WIDTH-240)/2 or d > (WIDTH-60)/2) then
--collision
end
I’ve been busy lately and just got around to reading your post, but this looks interesting! I’ll definitely test out the use of vec2 functions to determine collisions between objects.