Does the physics engine handle the squish of a physics body?

The following code is a basic drop of a ball. But the ball does not squish before bouncing back up. First, does the Corona physics engine have the ability to do the squish, and Secondly, what physics body properties need to be set to make this happen? Can someone add to my code to make this work?

--hide status background display.setStatusBar(display.HiddenStatusBar) --ball local h=display.contentHeight local circl = display.newCircle( h\*.05,h\*.05,h\*.06,h\*.06) circl:setFillColor( .1,.8,.5 ) circl.anchorX = 0; circl.anchorY = 0 --floor local rect = display.newRect( 0,h-(h\*.05),display.contentWidth,h) rect:setFillColor( .8,.5,.1 ) rect.anchorX = 0; rect.anchorY = 0 -- physics local physics = require("physics") physics.start() physics.setGravity(0,9.8) physics.addBody(circl, {bounce = 0.7}) physics.addBody(rect,"static",{bounce = 0.2})

No.  Box2D (which Corona uses) is a rigid body engine.

However, there are physics particles that may deform.  I’m not sure about this though as I have never used them except to toy with.

Note: You can achieve this affect visually, but making the object a animated sprite and playing the right sequence at collision time.

Alternately, you can use scaling to squish the image.  This won’t affect the body shape.

You can’t deform the physics object as, once set, its size and scale remain constant but you can alter the display object.

Here is a quick and dirty “squish” effect.  I added a yScale transition that adjusts to the y-velocity of the circle.  I decreased slightly the radius of the circle’s physics definition so it “settles” slightly into the floor.

Sprites would be another solution and if you are feeling ambitious, maybe you can see if meshes will do anything for you.  Also, if you use a graphic instead of a display circle, the transition will probably look smoother.

[lua]

–hide status background

display.setStatusBar(display.HiddenStatusBar)

–ball

local h=display.contentHeight

local circl = display.newCircle( h*.05,h*.05,h*.06,h*.06)

circl:setFillColor( .1,.8,.5 ) 

circl.anchorX = 0; circl.anchorY = 0

–floor

local rect = display.newRect( 0,h-(h*.05),display.contentWidth,h)

rect:setFillColor( .8,.5,.1 ) 

rect.anchorX = 0; rect.anchorY = 0

– physics

local physics = require(“physics”)

physics.start()

physics.setGravity(0,9.8)

physics.addBody(circl, {bounce = 0.7, radius = h*0.058})

physics.addBody(rect,“static”,{bounce = 0.2})

–physics.setDrawMode( “hybrid” )

local function squish( e )

    local c = e.target

    if (e.phase == “began”) then

        local vx, vy = c:getLinearVelocity()

        print( "squish time " … " "… vy )

        transition.to( c, {yScale = 1 - vy/1000, time = vy/10, onComplete = function()

            transition.to( c, {yScale = 1, time = vy/10} )

        end} )

    end

end

circl:addEventListener( “collision”, squish )

[/lua]

@roaminggamer - thank you for the clarification on the issue

@sharp100 - thank you for trying to make this work - doesn’t seem to for me.

I don’t know if the display will be fast enough, but it seems to me that the only solution is to make athe physics.circle object have an alpha=.001 and use another display.newCircle object that I can resize and change based upon the movement or collisions of the physics body. Not sure I have the time to give it a try, though.

precollision event may be part of the solution.  i.e. start to squish before collision.

In fact, make the body slightly smaller than the shape.

precollision – start to squish

collision  - stop squish

postcollision - start expansion, run past, rebound to normal.

@roamming gamer

Yes!  That’s why I slightly shrunk the radius of the physics circle.  

precollison and postcollision are great ideas too.

Animation would be the best solution (combined with pre and postcollision).

Does anyone know of someone else who has tried this sort of thing?

Animation would always look best, but its not practical for a game with numerous balls that can bounce in various positions, against other objects, and more than one sometimes.

@troylyndon,

A “squish”-able body might be able to be constructed using a LiquidFun.

https://docs.coronalabs.com/api/type/ParticleSystem/createGroup.html

Best regards,

Brent

@Brent - Good idea!

@troylyndon - Have you see this article ?  It’s a  process to unify your liquid fun bodies into a single element visually using snapshots and filters.  It’s super cool and could be a good solution for distorting your physics objects due to collisions.  However, I have found it to be processor-intensive so if you have a lot of other things going on, it might be a lot to ask of the CPU.

Pre-rendering is the way forward here I think… just have an image sheet containing the ball in various stages of squish and switch the animation on when it collides.  You could say have 10 frames (for the squish) and then just reverse the animation to make 20 frames.  If you make the image sheet grey scale you can tint it whatever colour you want.

It is then just a question of timing the switch from static animation (i.e. only showing the first frame) to dynamic animation (for the squish) and back to static again.

That’s a good solution but it doesn’t cover multiple object collisions ; say one ball getting hit on 2 or 3 sides simultaneously which I think was @troylyndon’s reason for not liking animations for the task.

No.  Box2D (which Corona uses) is a rigid body engine.

However, there are physics particles that may deform.  I’m not sure about this though as I have never used them except to toy with.

Note: You can achieve this affect visually, but making the object a animated sprite and playing the right sequence at collision time.

Alternately, you can use scaling to squish the image.  This won’t affect the body shape.

You can’t deform the physics object as, once set, its size and scale remain constant but you can alter the display object.

Here is a quick and dirty “squish” effect.  I added a yScale transition that adjusts to the y-velocity of the circle.  I decreased slightly the radius of the circle’s physics definition so it “settles” slightly into the floor.

Sprites would be another solution and if you are feeling ambitious, maybe you can see if meshes will do anything for you.  Also, if you use a graphic instead of a display circle, the transition will probably look smoother.

[lua]

–hide status background

display.setStatusBar(display.HiddenStatusBar)

–ball

local h=display.contentHeight

local circl = display.newCircle( h*.05,h*.05,h*.06,h*.06)

circl:setFillColor( .1,.8,.5 ) 

circl.anchorX = 0; circl.anchorY = 0

–floor

local rect = display.newRect( 0,h-(h*.05),display.contentWidth,h)

rect:setFillColor( .8,.5,.1 ) 

rect.anchorX = 0; rect.anchorY = 0

– physics

local physics = require(“physics”)

physics.start()

physics.setGravity(0,9.8)

physics.addBody(circl, {bounce = 0.7, radius = h*0.058})

physics.addBody(rect,“static”,{bounce = 0.2})

–physics.setDrawMode( “hybrid” )

local function squish( e )

    local c = e.target

    if (e.phase == “began”) then

        local vx, vy = c:getLinearVelocity()

        print( "squish time " … " "… vy )

        transition.to( c, {yScale = 1 - vy/1000, time = vy/10, onComplete = function()

            transition.to( c, {yScale = 1, time = vy/10} )

        end} )

    end

end

circl:addEventListener( “collision”, squish )

[/lua]

@roaminggamer - thank you for the clarification on the issue

@sharp100 - thank you for trying to make this work - doesn’t seem to for me.

I don’t know if the display will be fast enough, but it seems to me that the only solution is to make athe physics.circle object have an alpha=.001 and use another display.newCircle object that I can resize and change based upon the movement or collisions of the physics body. Not sure I have the time to give it a try, though.

precollision event may be part of the solution.  i.e. start to squish before collision.

In fact, make the body slightly smaller than the shape.

precollision – start to squish

collision  - stop squish

postcollision - start expansion, run past, rebound to normal.