Can you change physics body size after resizing an image?

Pretty simple question:  Can you change physics body size after resizing an image?  I have a game where items will be touching it, if it does, then the item gets bigger (and the physics size should as well).  Anyone know how to accomplish this? I can’t seem to get it to work. 

No, I’m pretty sure you need to remove the old body and add a new one.

Alternately, you can might be able to have multiple bodies with just one enabled

Have a look at the guide and see if anything pops out at you: https://docs.coronalabs.com/guide/physics/physicsBodies/index.html

Also, don’t forget to peruse the API:

https://docs.coronalabs.com/api/library/physics/index.html

https://docs.coronalabs.com/api/type/Body/index.html

Another couple of alternatives:

  1. If you’re not using physics for anything except collision detection, then do the math yourself.

  2. If you’re physics for physics based movement, consider converting the colliders to sensors and calculating the collisions yourself.

Circle vs circle collisions are usually good enough an drop-dead simple.  They break down to a simple distance calculation.

So I tried the whole, removebody / add new one… and I get this error.  I guess this is out of the question during a collision event.  

ERROR: E:\Users\Documents\Corona Projects\Pixel\_Pop\gameLevel.lua:66: physics.addBody() cannot be called when the world is locked and in the middle of number crunching, such as during a collision event

As for the below comments, I am using physics for collision detection and moving objects via the setLinearVelocity. I have changed them all to sensors.  Do you think you could provide me with an example of what you mean by calculating myself.  

I am using moving squares and a stationary rectangle. 

Right.  You have to wait one frame to remove/modify the body.  Just as the error says, you can’t make physics changes in the middle of a collision.

Waiting is as simple as this:

local function collision( self, event ) if(event.phase == "began" ) then timer.performWithDelay( 1, -- wait 1ms (essentially next frame) function() -- deferred work here end ) ...

I get the same error using this.  

 

local whiteCellScaleBy = 50 local whiteCellSize = screenW/whiteCellScaleBy local whiteCell local function createWhiteCell()     whiteCell = display.newRect( mainGroup, centerX, centerY, whiteCellSize, whiteCellSize )     physics.addBody( whiteCell, "static")     whiteCell.isSensor = true     whiteCell.myName = "whiteCell" end local function onCollision( event )     local obj1 = event.object1     local obj2 = event.object2              if ( event.phase == "began" ) then         if ( ( obj1.myName == "pixel" and obj2.myName == "whiteCell" ) or              ( obj1.myName == "whiteCell" and obj2.myName == "pixel" ) )         then             -- Remove both the pixel and whiteCell             display.remove( obj1 )             display.remove( obj2 )             whiteCellScaleBy = whiteCellScaleBy - 2.5             timer.performWithDelay( 1, createWhiteCell(), 1)             print("Grow")             for i = #pixelsTable, 1, -1 do                 if ( pixelsTable[i] == obj1 or pixelsTable[i] == obj2 ) then                     table.remove( pixelsTable, i )                     break                 end             end         end     end end
timer.performWithDelay( 1, createWhiteCell, 1)

This worked like a charm.   Would you be willing to explain why to call a function without the () made such a difference?

No, but I’ll help you figure it out.

First, read the entire page here: 

https://docs.coronalabs.com/api/library/timer/performWithDelay.html

Second, create a new main.lua file and put this in it:

local function run() print("Ran at ", system.getTimer() ) end run() timer.performWithDelay( 1000, run() ) timer.performWithDelay( 2000, run )

Now, tell me what you see in the console and why you see it.

Well, I notice that when using the run() during the delay, it doesn’t actually delay anything.  It is instantly ran regardless of the 1000 delay stated.  However, when using the run it does delay based on the set delay. After reading the page mentioned, I was still unsure as to why.  Thus, I googled it.  From what I gather, when you use the parenthesis, it runs the function(in this case instantly instead of after the 1 second), however, when you don’t use the parenthesis, it instead passes a reference to the function and that function is called later after the delay when it it becomes the focus. 

Does this sound right? 

That is right.
 
The first call to timer.performWithDelay()

timer.performWithDelay( 1000, run() )

runs the function immediately and anything returned from it is passed to timer.performWithDelay()
 
It is equivalent to this (in this scenario):

local retVal = run() timer.performWithDelay( 1000, retVal ) -- retVal is nil in this case

The main thing to remember is you have to pass a reference to a function to timer.performWithDelay().

This is a reference: run

This is you calling the function: run()

No, I’m pretty sure you need to remove the old body and add a new one.

Alternately, you can might be able to have multiple bodies with just one enabled

Have a look at the guide and see if anything pops out at you: https://docs.coronalabs.com/guide/physics/physicsBodies/index.html

Also, don’t forget to peruse the API:

https://docs.coronalabs.com/api/library/physics/index.html

https://docs.coronalabs.com/api/type/Body/index.html

Another couple of alternatives:

  1. If you’re not using physics for anything except collision detection, then do the math yourself.

  2. If you’re physics for physics based movement, consider converting the colliders to sensors and calculating the collisions yourself.

Circle vs circle collisions are usually good enough an drop-dead simple.  They break down to a simple distance calculation.

So I tried the whole, removebody / add new one… and I get this error.  I guess this is out of the question during a collision event.  

ERROR: E:\Users\Documents\Corona Projects\Pixel\_Pop\gameLevel.lua:66: physics.addBody() cannot be called when the world is locked and in the middle of number crunching, such as during a collision event

As for the below comments, I am using physics for collision detection and moving objects via the setLinearVelocity. I have changed them all to sensors.  Do you think you could provide me with an example of what you mean by calculating myself.  

I am using moving squares and a stationary rectangle. 

Right.  You have to wait one frame to remove/modify the body.  Just as the error says, you can’t make physics changes in the middle of a collision.

Waiting is as simple as this:

local function collision( self, event ) if(event.phase == "began" ) then timer.performWithDelay( 1, -- wait 1ms (essentially next frame) function() -- deferred work here end ) ...

I get the same error using this.  

 

local whiteCellScaleBy = 50 local whiteCellSize = screenW/whiteCellScaleBy local whiteCell local function createWhiteCell()     whiteCell = display.newRect( mainGroup, centerX, centerY, whiteCellSize, whiteCellSize )     physics.addBody( whiteCell, "static")     whiteCell.isSensor = true     whiteCell.myName = "whiteCell" end local function onCollision( event )     local obj1 = event.object1     local obj2 = event.object2              if ( event.phase == "began" ) then         if ( ( obj1.myName == "pixel" and obj2.myName == "whiteCell" ) or              ( obj1.myName == "whiteCell" and obj2.myName == "pixel" ) )         then             -- Remove both the pixel and whiteCell             display.remove( obj1 )             display.remove( obj2 )             whiteCellScaleBy = whiteCellScaleBy - 2.5             timer.performWithDelay( 1, createWhiteCell(), 1)             print("Grow")             for i = #pixelsTable, 1, -1 do                 if ( pixelsTable[i] == obj1 or pixelsTable[i] == obj2 ) then                     table.remove( pixelsTable, i )                     break                 end             end         end     end end
timer.performWithDelay( 1, createWhiteCell, 1)

This worked like a charm.   Would you be willing to explain why to call a function without the () made such a difference?

No, but I’ll help you figure it out.

First, read the entire page here: 

https://docs.coronalabs.com/api/library/timer/performWithDelay.html

Second, create a new main.lua file and put this in it:

local function run() print("Ran at ", system.getTimer() ) end run() timer.performWithDelay( 1000, run() ) timer.performWithDelay( 2000, run )

Now, tell me what you see in the console and why you see it.

Well, I notice that when using the run() during the delay, it doesn’t actually delay anything.  It is instantly ran regardless of the 1000 delay stated.  However, when using the run it does delay based on the set delay. After reading the page mentioned, I was still unsure as to why.  Thus, I googled it.  From what I gather, when you use the parenthesis, it runs the function(in this case instantly instead of after the 1 second), however, when you don’t use the parenthesis, it instead passes a reference to the function and that function is called later after the delay when it it becomes the focus. 

Does this sound right?