Expanding and contracting circles, collision issues!

I have a problem keeping these circles tame. Below is the source for an experiment another forum user and I have been experimenting with. The primary problem being that the circles have a tendency to overlap if multiple collisions occur too quickly or too slowly or just because. Also there’s a more efficient way of accomplishing our task, I just haven’t come up with it yet. Physic collision detection is out of the question because of constant scaling and all accompanying issues. Any and all help would be incredibly appreciated! The image needed for the project and the project itself can be found here (under DOWNLOAD PACKAGES): https://github.com/Cellaflora/Circles

Thanks Guys!

[lua]display.setStatusBar( display.HiddenStatusBar )
local abs = math.abs
local rand = math.random

local r = 55
local maxScale = 2
local minScale = 0.2
local transferFactor = 0.40

local circles = {}

local function addCircle(e)
local x = e.x
local y = e.y

–local circle = display.newCircle(x,y,r)
local circle = display.newImage( “circ9ge.png”)
circle.alpha = 1
circle.x = e.x
circle.y = e.y
circle.speed = .3
circle.t = nil
circle.direction = “expand”
–circle:setFillColor(180,180,180)
–circle:setStrokeColor(255, 255, 255)
–circle.strokeWidth = 5
circle:scale(minScale,minScale)

function circle:change(direction)
if self.t ~= nil then
transition.cancel(self.t)
self.t = nil
end
if direction == “expand” then
self.t = transition.to(self, {time = 1000 * (maxScale-self.xScale)/self.speed, xScale = maxScale, yScale = maxScale, onComplete=self.change})
self.direction = “expand”
elseif direction == “shrink” then
self.t = transition.to(self, {time = 1000*(self.xScale-minScale)/self.speed, xScale = minScale, yScale = minScale, onComplete=self.change})
self.direction = “shrink”
else
if self.direction == “shrink” then
self.t = transition.to(self, {time = 1000 * (maxScale-self.xScale)/self.speed, xScale = maxScale, yScale = maxScale, onComplete=self.change})
self.direction = “expand”
elseif self.direction == “expand” then
self.t = transition.to(self, {time = 1000*(self.xScale-minScale)/self.speed, xScale = minScale, yScale = minScale, onComplete=self.change, onComplete=self.change})
self.direction = “shrink”
end
end
–self:setFillColor(rand(255),rand(255),rand(255))
–self:setFillColor(0,0,0)

end

function circle:tap(e)
print(“circle tapped”)
return true
end

circle:addEventListener(“tap”,circle)
table.insert(circles , circle )
circle:change(“expand”)
print("no. of circles : " , #circles)

return true
end

Runtime:addEventListener(“tap”,addCircle)

local function distanceBetween( point1, point2 )

local xfactor = point2.x-point1.x ; local yfactor = point2.y-point1.y
local distanceBetween = math.sqrt((xfactor*xfactor) + (yfactor*yfactor))
return distanceBetween
end

local timers = {}

local function gameLoop(e)
for i = 1, #circles do
for j = i+1, #circles do
–print(“dist”, i, j, abs( (circles[i].xScale + circles[j].xScale)*r - distanceBetween(circles[i],circles[j])))
if timers[tostring(i)…","…tostring(j)] == nil then

– if ((abs( (circles[i].xScale + circles[j].xScale)*r - distanceBetween(circles[i],circles[j])) < 2) and (abs( (circles[i].xScale + circles[j].xScale)*r - distanceBetween(circles[i],circles[j])) > 1)) then
if ( (circles[i].xScale + circles[j].xScale)*r - distanceBetween(circles[i],circles[j])) >= 1 then

–local speeddif = circles[i].speed - circles[j].speed
–circles[i].speed = circles[i].speed - speeddif * transferFactor
–circles[j].speed = circles[j].speed + speeddif * transferFactor
circles[i]:change()
circles[j]:change()
timers[tostring(i)…","…tostring(j)] = e.time
end

elseif e.time - timers[tostring(i)…","…tostring(j)] > 50 then

–if ((abs( (circles[i].xScale + circles[j].xScale)*r - distanceBetween(circles[i],circles[j])) < 2) and (abs( (circles[i].xScale + circles[j].xScale)*r - distanceBetween(circles[i],circles[j])) > 1)) then
if ( (circles[i].xScale + circles[j].xScale)*r - distanceBetween(circles[i],circles[j])) >= 1 then

–local speeddif = circles[i].speed - circles[j].speed
–circles[i].speed = circles[i].speed - speeddif * transferFactor
–circles[j].speed = circles[j].speed + speeddif * transferFactor
circles[i]:change()
circles[j]:change()
timers[tostring(i)…","…tostring(j)] = e.time
end
end
end
end
end

Runtime:addEventListener(“enterFrame”,gameLoop)local abs = math.abs
local rand = math.random

[lua] [import]uid: 13050 topic_id: 11094 reply_id: 311094[/import]

@icarusFalling,

from a quick glance, the issue is transitions, you are having a loop with enterFrame but the transitions will change only when completed, so the transition might be expanding where as on collision you have asked it to shrink, but it will only start when the transition is complete, by then the status might have changed again.

so you might want to store the transition handle in the object and then cancel transition to ensure that the transition is stopped and a new one started immediately, rather than later.

hope that helps,

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 11094 reply_id: 40331[/import]

Thanks for your reply! I’m not certain I follow. If the transitions ran to completion then they won’t stop expanding, as they do most of the time, and instead expand to the max value. My issue is that, at times, the circles break free of their bounds and expand past the collision point (usually when more than two circles are involved in a collision). Have I understood your suggestion? [import]uid: 13050 topic_id: 11094 reply_id: 40365[/import]

Likely, this existing transition canceling is already doing what you believed was missing from the existing code.

[code]
function circle:change(direction)

if self.t ~= nil then
transition.cancel(self.t)
self.t = nil
end
[import]uid: 13050 topic_id: 11094 reply_id: 40382[/import]

icarusfalling,

change all the calls to change() function to change(“shrink”) after as you want all the circles to shrink on collision. [import]uid: 48521 topic_id: 11094 reply_id: 40457[/import]

Like magic! [import]uid: 13050 topic_id: 11094 reply_id: 40476[/import]