Unwanted Bouncing Behavior When Converting Display Groups to Physics Bodies

I have been using display groups to try to integrate text and sprite display objects into a single entity and then converting the entire display group to a physics object, so the text and sprites behave as single, cohesive physics bodies. However, after converting the display groups to physics bodies, they exhibit bouncing behavior, even though I have set the ‘bounce’ to zero in the physics.addBody argument. I only see this bouncing behavior when converting display groups into physics bodies, and not when simply converting the sprites only to physics bodies separately without integrating with text objects using display groups.

Has anyone else experienced these issues or can offer a fix? Otherwise, I am also open to hearing about alternative methods to integrate text and sprite objects into a single physics body (I have already tried using weld joints, but have had some issues with that method as well).

Can you supply some basic sample code that shows this problem.  It sounds interesting, but without some code we will have trouble helping debug the issue.

I wrote this code to test and can’t reproduce the behavior you describe.

local physics = require("physics") physics.start() local floor = display.newRect(0, 100, 1000, 10) physics.addBody(floor, "static", {bounce = 0}) local box = display.newRect(100, 10, 20, 20) physics.addBody(box, "dynamic", {bounce = 0}) local grp = display.newGroup() local a = display.newRect(grp, 200, 10, 20, 20) local b = display.newRect(grp, 250, 10, 20, 20) physics.addBody(grp, "dynamic", {bounce = 0})

When running the example above, neither box nor grp exhibit bouncing behavior.

What are your objects bouncing off of? Did you remember to set the bounce to 0 for that object (wall/floor/whatever), too?

Also, do note that when creating a physics body out of groups like I did above, without specifying a shape, behavior will be unexpected and the physics body may end up being nowhere near the objects. You can check that by using physics.setDrawMode(“hybrid”)

Hi @crawfdc47,

I really don’t recommend applying physics bodies to entire display groups. This is technically “legal” but it usually opens up a pandora’s box of issues.

If you need to do something like this, I suggest you insert all of the display objects (text, sprites, etc.) into a display group, but then you just apply a multi-element body to one of the objects within, where each element represents one of the group’s children.

Brent

Thanks for the feedback/suggestions! Here is a sample of the code that I am using for my project. I am developing a word game, and am trying to combine text and rectangles (or image files) to create the letter tiles using display groups. When I place only one tile a time, no bouncing occurs, but bouncing (and other strange physics behavior) occurs when I place multiple tiles simultaneously with my createTile function, which is what I am trying to do for my app.

Thanks Brent for your suggestion about using multi-element bodies. I plan to look into this further, and it seems like it may be the best way to address my problem. I’ll post an update after I have had a chance to implement it.

 local physics = require( "physics" ) physics.start() --set true to prevent all bodies from sleeping physics.setGravity( 0, 50 ) physics.setScale( 10 ) local tileWidth = 40 local ptValue = 4 local spacing = 5 local letter = "W" local rows = 4 local columns = 5 local rightX = display.contentWidth - display.screenOriginX local leftX = display.screenOriginX local function createTile( xPosition, yPosition ) local tile = display.newRect( 0, 0, tileWidth, tileWidth ) tile.x, tile.y = xPosition, yPosition tile.isFixedRotation = true tile.letter = letter tile.letterText = display.newText( letter, 0, 0, native.systemFontBold, 25 ); tile.letterText:setTextColor( 0,0,0 ) tile.letterText.x = tile.x tile.letterText.y = tile.y tile.pointValue = display.newText( tostring(ptValue), 0, 0, native.systemFontBold, 8 ) tile.pointValue:setTextColor( 0,0,0 ) tile.pointValue.x = tile.x - 12 tile.pointValue.y = tile.y - 12 local tileGroup = display.newGroup() tileGroup:insert( tile ) tileGroup:insert( tile.letterText ) tileGroup:insert( tile.pointValue ) tileGroup.anchorChildren = true tileGroup.x = xPosition tileGroup.y = yPosition physics.addBody( tileGroup, 'dynamic', { friction = 0, bounce = 0, density = 0, radius = .5\*tileWidth + .5\*spacing } ) end local groundLine = display.newRect( .5\*display.contentWidth, 300, display.contentWidth, 10 ) groundLine.anchorY = 0 groundLine:setFillColor( 1, 1, 1 ) physics.addBody( groundLine, 'static', { bounce=0, friction = 1 } ) local function generateRowOfTiles() for c = 1, columns do -- print(c) x = .5\*(rightX - leftX) - (columns\*(tileWidth + spacing ) + spacing )/2 + (c-1)\*(tileWidth + spacing ) + spacing createTile( x, 0 ) end end local timer = timer.performWithDelay( 2000, generateRowOfTiles, rows )

no idea re the grouping aspect of your problem, but other things of note…

high gravity

small scale

zero density bodies

which might cause instability in the simulation (regardless of the grouping aspect)

I have tried manipulating the values for gravity, scale, and density and tried different combinations of values for each of these, but this does not seem to eliminate/diminish the bouncing behavior.

Regarding Brent’s previous suggestion to implement multi-element bodies, I had a chance to look over the documentation for multi-element bodies. Unless I am misreading the documentation, it does not look like the multi-element bodies api supports the construction of multi-element bodies using multiple display objects (e.g. text, geometric shapes, images, sprites, etc.). Rather, it looks like this api only supports the construction of multi-element bodies using a single display object and then carving out and defining the boundaries of a multi-element object within the existing space of a single image or shape.

Hi @crawfdc47,

Yes, the multi-element body must be associated with only one object. However, if the objects in your “group” are going to remain unified in position/relation, then you can use any one of those bodies as the basic to construct that body’s element and additional elements representing the other objects in the group.

Of course, if your group objects will move independently of each other, then they should obviously be individual physics objects.

Brent

Hi Brent,

Yes, I would like the objects in the group to remain unified in position/relation so that they behave as a single body. However, I am still not sure exactly how to write the code to apply the multi-element body to one of my objects, while adding the rest of the child objects of my display group as elements to that body I am apply physics to. The objects that I am trying to unify using display groups from the code I provided before are:

tile

tile.letterText

tile.pointValue

I could not find any examples or documentation online that shows specifically how to construct multi-element bodies from separate display objects. But, if I try applying the multi-element body to the ‘tile’ object, and then add the rest of these objects as elements to the ‘tile’ object multi-element body, the below code is what I come up with:

physics.addBody( tile, 'dynamic', {shape = tile}, {shape = tile.letterText}, {shape = tile.pointValue }, { friction = 0, bounce = 0, density = 0, radius = .5\*tileWidth } )

However, this code does not look right to me, and the grouped objects do not behave as a unified, single bodies in the simulator. Am I missing something?

Hi @crawfdc47,

I should ask another question: is this simulation going to work under the effect of gravity and other forces?

Brent

Hi Brent,

Yes, this simulation is supposed to work under the effect of gravity, but it is unlikely that I will be applying any other kinds of forces to the objects/bodies in this simulation. The only purpose really for adding gravity, is so that when one or more of the letter tiles is removed (when the user finds a word) the next tile on top of the removed tile falls in to replace the position of the removed tiles. This is the reason why the tiles are arranged in a grid-like manner. I hope that makes sense…

there are (at least?) two conceptual ways to use display groups:

  1. the stuff they contain are positioned individually to screen coordinates, group itself is left at 0,0 - this is fine for controlling visual “layering” but isn’t the way you’d want to do it for physics

  2. the stuff they contain are positioned relative to 0,0 origin of the group, then the group is positioned at screen coordinates - this is how you want to use it for physics

adding a physics body will “control” the xy of one display object.  if that object is a group, then its bounds needs to match its position - which only happens with setup 2) above.

An analogy for 2) is to think of your group as a small box sliding around a table:  first you put stuff “IN” the box (by giving them 0,0 relative coords), then you slide the box to where you want it - that makes physics happy and looks right on screen.  The analogy for 1) is a big sheet of clear plastic with its corner at the table’s corner, it’s contents spread all over the table - yes, sliding the plastic will slide the objects too, but not in a way that physics “likes”.

Hi davebollinger. Thanks for your input about using display groups. I tried implementing your second suggestion by changing line 17 of the code I provided above to:

tile.x, tile.y = .5\*tileWidth, .5\*tileWidth

However, this did not seem to improve the issue with bouncing behavior that I have been having. Thanks for the tip though!

I still have not found a way to fix the problem I was having with display groups, so I instead implemented sprites to achieve the type of physics behavior I wanted for the app. Rather than combining text with shapes into display groups, I instead created a 26 frame image sheet, with each frame representing a letter of the alphabet. I am guessing this method is less memory efficient than using display groups, but the physics seems to be working better. 

Can you supply some basic sample code that shows this problem.  It sounds interesting, but without some code we will have trouble helping debug the issue.

I wrote this code to test and can’t reproduce the behavior you describe.

local physics = require("physics") physics.start() local floor = display.newRect(0, 100, 1000, 10) physics.addBody(floor, "static", {bounce = 0}) local box = display.newRect(100, 10, 20, 20) physics.addBody(box, "dynamic", {bounce = 0}) local grp = display.newGroup() local a = display.newRect(grp, 200, 10, 20, 20) local b = display.newRect(grp, 250, 10, 20, 20) physics.addBody(grp, "dynamic", {bounce = 0})

When running the example above, neither box nor grp exhibit bouncing behavior.

What are your objects bouncing off of? Did you remember to set the bounce to 0 for that object (wall/floor/whatever), too?

Also, do note that when creating a physics body out of groups like I did above, without specifying a shape, behavior will be unexpected and the physics body may end up being nowhere near the objects. You can check that by using physics.setDrawMode(“hybrid”)

Hi @crawfdc47,

I really don’t recommend applying physics bodies to entire display groups. This is technically “legal” but it usually opens up a pandora’s box of issues.

If you need to do something like this, I suggest you insert all of the display objects (text, sprites, etc.) into a display group, but then you just apply a multi-element body to one of the objects within, where each element represents one of the group’s children.

Brent

Thanks for the feedback/suggestions! Here is a sample of the code that I am using for my project. I am developing a word game, and am trying to combine text and rectangles (or image files) to create the letter tiles using display groups. When I place only one tile a time, no bouncing occurs, but bouncing (and other strange physics behavior) occurs when I place multiple tiles simultaneously with my createTile function, which is what I am trying to do for my app.

Thanks Brent for your suggestion about using multi-element bodies. I plan to look into this further, and it seems like it may be the best way to address my problem. I’ll post an update after I have had a chance to implement it.

 local physics = require( "physics" ) physics.start() --set true to prevent all bodies from sleeping physics.setGravity( 0, 50 ) physics.setScale( 10 ) local tileWidth = 40 local ptValue = 4 local spacing = 5 local letter = "W" local rows = 4 local columns = 5 local rightX = display.contentWidth - display.screenOriginX local leftX = display.screenOriginX local function createTile( xPosition, yPosition ) local tile = display.newRect( 0, 0, tileWidth, tileWidth ) tile.x, tile.y = xPosition, yPosition tile.isFixedRotation = true tile.letter = letter tile.letterText = display.newText( letter, 0, 0, native.systemFontBold, 25 ); tile.letterText:setTextColor( 0,0,0 ) tile.letterText.x = tile.x tile.letterText.y = tile.y tile.pointValue = display.newText( tostring(ptValue), 0, 0, native.systemFontBold, 8 ) tile.pointValue:setTextColor( 0,0,0 ) tile.pointValue.x = tile.x - 12 tile.pointValue.y = tile.y - 12 local tileGroup = display.newGroup() tileGroup:insert( tile ) tileGroup:insert( tile.letterText ) tileGroup:insert( tile.pointValue ) tileGroup.anchorChildren = true tileGroup.x = xPosition tileGroup.y = yPosition physics.addBody( tileGroup, 'dynamic', { friction = 0, bounce = 0, density = 0, radius = .5\*tileWidth + .5\*spacing } ) end local groundLine = display.newRect( .5\*display.contentWidth, 300, display.contentWidth, 10 ) groundLine.anchorY = 0 groundLine:setFillColor( 1, 1, 1 ) physics.addBody( groundLine, 'static', { bounce=0, friction = 1 } ) local function generateRowOfTiles() for c = 1, columns do -- print(c) x = .5\*(rightX - leftX) - (columns\*(tileWidth + spacing ) + spacing )/2 + (c-1)\*(tileWidth + spacing ) + spacing createTile( x, 0 ) end end local timer = timer.performWithDelay( 2000, generateRowOfTiles, rows )

no idea re the grouping aspect of your problem, but other things of note…

high gravity

small scale

zero density bodies

which might cause instability in the simulation (regardless of the grouping aspect)

I have tried manipulating the values for gravity, scale, and density and tried different combinations of values for each of these, but this does not seem to eliminate/diminish the bouncing behavior.

Regarding Brent’s previous suggestion to implement multi-element bodies, I had a chance to look over the documentation for multi-element bodies. Unless I am misreading the documentation, it does not look like the multi-element bodies api supports the construction of multi-element bodies using multiple display objects (e.g. text, geometric shapes, images, sprites, etc.). Rather, it looks like this api only supports the construction of multi-element bodies using a single display object and then carving out and defining the boundaries of a multi-element object within the existing space of a single image or shape.