Kinematic Collisions in grouped bodies

Hello all,

I was wondering if someone could help me with regards to kinematic physics bodies that are placed in a display group that is animated via transitions.

Basically, I have several items (balls) that need to respond to collision events; those balls are housed within a display group. The display group is then animated with a transition.

If I animate the balls independently everything works fine. However, if I put the balls into a display group and animate the group, the collisions no longer fire.

My assumption is that the physics engine is not aware that the balls x/y position is changing when the ball’s parent group is animating. But I could be way wrong.

The following code is not taken directly from my project, but I put it together to show proof of concept (so it is by no means optimized). You can see that “Dynamic” and “Independent” collisions work fine, but once the items are grouped and then animated, they fail.

[lua]physics = require(“physics”);
widget = require(“widget”);
physics.start();physics.pause();

–Draw our main block.
local hitBlock = display.newRect(0,0,100,100);
hitBlock.x = display.contentCenterX;
hitBlock.y = display.contentCenterY;
hitBlock:setFillColor(0,255,0,255);
hitBlock.myName = “hitBlock”;

–Draw ground
local ground = display.newRect(0,0,display.contentWidth, 10);
ground.x = display.contentCenterX;
ground.y = hitBlock.y + hitBlock.height/2;
ground:setFillColor(255,0,0,255) ;
ground.myName = “ground”;
local debugText = display.newText(“DEBUG”,0, 0, display.contentWidth, display.contentHeight, native.systemFont,10)

–Add to the physics engine
physics.addBody(hitBlock, “dynamic”, {density=1, bounce=.5, friction=.5});
physics.addBody(ground, “static”, {density=1, bounce=.5, friction=.5});

–Ball functions
local function dynamicBalls()
debugText.text = “STARTING: DYNAMIC BALLS\n”…debugText.text;
local ballContainer = display.newGroup();
for i=1, 20 do
local ball = display.newCircle(0, 0, 5)
ball.x = display.contentCenterX + math.random(-50,50);
ball.y = 10;
ball.myName = “dynamic_ball” … i; --Give it a name
–Fill with random colors
ball:setFillColor(math.random(0,255),math.random(0,255),math.random(0,255),255)
–Ball collision event
function ball:collision(event)
if(event.other.myName == “ground”) then
debugText.text = "Removing ~~> " … self.myName … “\n” …debugText.text ;
self:removeSelf();
self = nil;
end
end
ball:addEventListener(“collision”, ball);

physics.addBody(ball, “dynamic”, {density=1, bounce=.3, friction=0});
ballContainer:insert(ball);
end
end

local function independentBalls()
debugText.text = “STARTING: INDEPENDENT ANIMATION\n”…debugText.text;
local ballContainer = display.newGroup();
for i=1, 20 do
local ball = display.newCircle(0, 0, 5)
ball.x = display.contentCenterX + math.random(-50,50);
ball.y = 10;
ball.myName = “indie_ball” … i;
–Ball collision event
function ball:collision(event)
if(event.other.bodyType == “dynamic”) then
debugText.text = "Removing~~> " … self.myName … “\n” … debugText.text;
self:removeSelf();
self = nil;
end
end
ball:addEventListener(“collision”, ball);

physics.addBody(ball, “kinematic”, {density=1, bounce=.3, friction=0, isSensor=true});
ballContainer:insert(ball);
–Move the individual (via transition)
transition.to(ball, {time=3000,y = display.contentHeight});
end
end

local function groupedBalls()
debugText.text = “STARTING: GROUP ANIMATION\n” …debugText.text;
local ballContainer = display.newGroup();
for i=1, 20 do
local ball = display.newCircle(0, 0, 5)
ball.x = display.contentCenterX + math.random(-50,50);
ball.y = 10;
ball.myName = “grouped_ball” … i;
–Ball collision event
function ball:collision(event)
if(event.other.bodyType == “dynamic”) then
debugText.text = "Removing~~> " … self.myName… “\n” … debugText.text;
self:removeSelf();
self = nil;
end
end
ball:addEventListener(“collision”, ball);

physics.addBody(ball, “kinematic”, {density=1, bounce=.3, friction=0, isSensor=true});
ballContainer:insert(ball);
end
–Move the container (via transition) holding our elements
transition.to(ballContainer, {time=3000,y = display.contentHeight});
end

local btnDynamic = widget.newButton({
width = 100,
height = 50,
label = “Dynamic”,
onRelease = dynamicBalls,
top = display.contentHeight - 50,
left = 0;
})
local btnIndie = widget.newButton({
width = 100,
height = 50,
label = “Independent”,
onRelease = independentBalls,
top = display.contentHeight - 50,
left = 100;
})

local btnGroup = widget.newButton({
width = 100,
height = 50,
label = “Grouped”,
onRelease = groupedBalls,
top = display.contentHeight - 50,
left = 200
})
physics.start();[/lua]
[import]uid: 152300 topic_id: 32871 reply_id: 332871[/import]

“My assumption is that the physics engine is not aware that the balls x/y position is changing when the ball’s parent group is animating. But I could be way wrong.”

You are, in fact, 100% correct. The physics engine works on a “shared coordinate space” between groups… it is how the engine does its internal math to figure out collisions. If you move an entire display group, collisions won’t mesh properly, as you guessed.

Your solution is to move every ball individually, but transitions also don’t play nicely with collisions. Ultimately, your best bet would be to use physical forces on them… or if you absolutely need a flat “point to point” movement, you could use a custom Runtime movement which listens better to collisions along the way.

Brent [import]uid: 9747 topic_id: 32871 reply_id: 130667[/import]

“My assumption is that the physics engine is not aware that the balls x/y position is changing when the ball’s parent group is animating. But I could be way wrong.”

You are, in fact, 100% correct. The physics engine works on a “shared coordinate space” between groups… it is how the engine does its internal math to figure out collisions. If you move an entire display group, collisions won’t mesh properly, as you guessed.

Your solution is to move every ball individually, but transitions also don’t play nicely with collisions. Ultimately, your best bet would be to use physical forces on them… or if you absolutely need a flat “point to point” movement, you could use a custom Runtime movement which listens better to collisions along the way.

Brent [import]uid: 9747 topic_id: 32871 reply_id: 130667[/import]

Thanks for the reply, Brent. Admittedly, I am a little disappointed to read that I can’t animate parent groups of physics bodies and maintain collision detection. As such, how would you (or anyone else for that matter) recommend that I enable collisions on the “frog” in the following sample code:

[lua]physics = require(“physics”);
widget = require(“widget”);
physics.start();physics.pause();

–Create a falling log with animated frog
local function doLogAndFrog()
local myLog = display.newGroup();

local logGFX = display.newRect(0,0,math.random(100,150),20);
logGFX:setFillColor(102, 102, 0, 255);

local frog = display.newCircle(0,0,10);
frog.y = 10; --Place it
frog:setFillColor(51, 255, 51, 255); --Paint it

local function moveFrog()
local targetX = logGFX.width;
if(frog.x ~= 0)then targetX = 0 end
transition.to(frog, {x=targetX, time=1000, onComplete=moveFrog});
end

–Add to display.
myLog:insert(logGFX);
myLog:insert(frog);

–position log
myLog.x = math.random(100,display.contentWidth-100);
myLog.y = -10;

–Start the falling log
transition.to(myLog, {time=6000, y= display.contentHeight + 20, onComplete=function()
myLog:removeSelf();
myLog = nil;
end
})
–Start the moving frog
moveFrog();

end

local btnLogAndFrog = widget.newButton({
width = 100,
height = 50,
label = “Drop Log”,
onRelease = doLogAndFrog,
top = display.contentHeight - 50,
left = display.contentWidth/2 - 50
})[/lua]

Any thoughts, tips or suggestions would be much appreciated!
[import]uid: 152300 topic_id: 32871 reply_id: 130691[/import]

Thanks for the reply, Brent. Admittedly, I am a little disappointed to read that I can’t animate parent groups of physics bodies and maintain collision detection. As such, how would you (or anyone else for that matter) recommend that I enable collisions on the “frog” in the following sample code:

[lua]physics = require(“physics”);
widget = require(“widget”);
physics.start();physics.pause();

–Create a falling log with animated frog
local function doLogAndFrog()
local myLog = display.newGroup();

local logGFX = display.newRect(0,0,math.random(100,150),20);
logGFX:setFillColor(102, 102, 0, 255);

local frog = display.newCircle(0,0,10);
frog.y = 10; --Place it
frog:setFillColor(51, 255, 51, 255); --Paint it

local function moveFrog()
local targetX = logGFX.width;
if(frog.x ~= 0)then targetX = 0 end
transition.to(frog, {x=targetX, time=1000, onComplete=moveFrog});
end

–Add to display.
myLog:insert(logGFX);
myLog:insert(frog);

–position log
myLog.x = math.random(100,display.contentWidth-100);
myLog.y = -10;

–Start the falling log
transition.to(myLog, {time=6000, y= display.contentHeight + 20, onComplete=function()
myLog:removeSelf();
myLog = nil;
end
})
–Start the moving frog
moveFrog();

end

local btnLogAndFrog = widget.newButton({
width = 100,
height = 50,
label = “Drop Log”,
onRelease = doLogAndFrog,
top = display.contentHeight - 50,
left = display.contentWidth/2 - 50
})[/lua]

Any thoughts, tips or suggestions would be much appreciated!
[import]uid: 152300 topic_id: 32871 reply_id: 130691[/import]

Hello JBee,
So you’re only moving the “frog” and “log” together? In this case, the best method would be to join the two objects together using a physics joint… a “weld” joint is the most rigid of these and locks the two items together essentially like cement. Other joints do other things and you might find those preferable.

http://developer.coronalabs.com/content/game-edition-physics-joints

I assume at some point the frog can become separated from the log? A joint can be broken and allow for that. On the other hand, if this a continual “one piece” object like a spaceship with the wings as separate pieces, your best option is a multi-part physics body instead of joints.

Brent
[import]uid: 9747 topic_id: 32871 reply_id: 130821[/import]

I would also suggest moving the log through physical means, not transitions. A simulated physical world just seems to work better when you use physical objects and forces in unison. If your log is falling, you’ll want to turn on gravity anyway to make the fall seem natural. A standard A-to-B transition won’t give you the proper gravitational acceleration effect. If for some reason you’re NOT using gravity, then you can move the log through a simple linear velocity action.
[import]uid: 9747 topic_id: 32871 reply_id: 130822[/import]

Hello JBee,
So you’re only moving the “frog” and “log” together? In this case, the best method would be to join the two objects together using a physics joint… a “weld” joint is the most rigid of these and locks the two items together essentially like cement. Other joints do other things and you might find those preferable.

http://developer.coronalabs.com/content/game-edition-physics-joints

I assume at some point the frog can become separated from the log? A joint can be broken and allow for that. On the other hand, if this a continual “one piece” object like a spaceship with the wings as separate pieces, your best option is a multi-part physics body instead of joints.

Brent
[import]uid: 9747 topic_id: 32871 reply_id: 130821[/import]

I would also suggest moving the log through physical means, not transitions. A simulated physical world just seems to work better when you use physical objects and forces in unison. If your log is falling, you’ll want to turn on gravity anyway to make the fall seem natural. A standard A-to-B transition won’t give you the proper gravitational acceleration effect. If for some reason you’re NOT using gravity, then you can move the log through a simple linear velocity action.
[import]uid: 9747 topic_id: 32871 reply_id: 130822[/import]