Function RestoreShip works only when called from game.lua file, but not from a module

Hello guys, I’m having kind of an odd issue. 
I’m basing my project off of the Corona Tutorial for the space shoot 'em up game, which contains the following function in order for the player to gain some invincibility frames upon getting hit, which works without any issues.
It’s contained within the game.lua file and, as such, the ship referenced in the function itself is a local variable.

local function restoreShip() ship.isBodyActive = false ship.x = display.contentCenterX ship.y = display.contentHeight - 100 -- Fade in the ship transition.to( ship, { alpha=1, time=4000, onComplete = function() ship.isBodyActive = true died = false end } ) end

This is my version of said function, contained within a module which I called shipManage.lua

shipManage.restoreShip = function (ship) ship.isBodyActive = false ship.x = display.contentCenterX ship.y = display.contentHeight \* 0.8 -- Fade in the ship transition.to( ship, { alpha = 1, time = 4000, onComplete = function() ship.isBodyActive = true end } ) end

It works well if I put it in my game.lua file (with the only alteration being, in that case, that the ship isn’t passed as a parameter to the function but is instead a local variable). However, if I put it in the shipManage.lua module, and pass the ship as a parameter to the function itself, I start getting the following error:
oVuFGCI.jpg

“property isBodyActive cannot be set cannot be called when the world is locked and in the middle of number crunching, such as during a collision event”

Which doesn’t make sense to me because the function, wether it’s in shipManage.lua or game.lua is called with the same exact delay in milliseconds (and altering it has proven to be useless).

Could somebody help me shed some light into this issue?

Which line is the error happening on? Setting the ship.isBodyActive to false at the beginning of the function or the ship.isBodyActive = true inside the onComplete function?

Where is the code calling shipManage.restoreShip()? Can you share that?

Rob

Which line is the error happening on? Setting the ship.isBodyActive to false at the beginning of the function or the ship.isBodyActive = true inside the onComplete function?

The error is happening at the beginning of the function, where ship.isBodyActive is set to false.

Where is the code calling shipManage.restoreShip()? Can you share that?

 Yeah, sure thing!

local function onCollision(event) -- TODO: Create a file called collisions that returns handles collisions, or at least a collision table local lostLife, newScore, makeSound, remove = level.onCollision(event) -- remove collided objects if ((remove == nil) == false) then for i = #enemyTable, 1, -1 do if (enemyTable[i] == remove[1] or enemyTable[i] == remove[2]) then table.remove(enemyTable, i) break end end end -- Play explosion sound if (makeSound) then audio.play(soundManage.explosionSound) end -- Increase score score = score + newScore updateText() -- update lives or die if ((lostLife == 0) == false) then died = true -- Play explosion sound -- Update lives if (lostLife \> lives) then lives = 0 else lives = lives - lostLife updateText() -- Check on the player's lives if (lives \<= 0) then endGame() else ship.alpha = 0 died = false timer.performWithDelay(1000, shipManage.restoreShip(ship)) end end end end

Thank you in advance!
 

try

timer.performWithDelay(1000, function() shipManage.restoreShip(ship) end)

also use : notation instead of . notation as this will reference your object by default.  i.e.

ship:restoreShip()

You will need to restructure your functions accordingly.  But generally this is the preferred way.  

You then reference self within those functions and that will give you a direct reference to ship.

timer.performWithDelay(1000, function() shipManage.restoreShip(ship) end)

This worked. Is there a particular reason or is it just some quirk?

also use : notation instead of . notation as this will reference your object by default.  i.e.

Could you tell me more about this. So far I’ve built all the modules by putting functions in a table (including a create function when needed) with the dot. What’s the difference?

When you have (param) on a function call (within a timer and other places) it will get executed immediately.  Wrapping it with function() … end turns it into a closure.

Using : means your functions will automatically have a reference to self and keeps everything clean. (more info https://www.lua.org/pil/16.html).  

ship = {} function ship:restore() //reset ship self.x = 0 self.y = 0 end return ship

So using : notation means (with a slight mod) your original code would of worked

timer.performWithDelay(1000, ship:restoreShip)

I know this is going off-topic, but I don’t fully understand how I’d change my code to use the : notation as you described.
For instance, this is how I currently create the ship

local shipManage = {} shipManage.create = function() local ship = {} ship = display.newSprite(mainGroup, sprites.spriteSheet, sprites.sequences\_Ship) -- constants.sizingTable["ship"][1], constants.sizingTable["ship"][2] \_TODO\_ -- 4 is the frame number (declared in order earlier from the image sheet) physics.addBody(ship, {radius = display.contentWidth / 12, isSensor = true}) -- Defines 'physical box' of object and is set as object that can sense collisions but not bounce off ship.myName = "ship" -- Property used for collisions ship:scale( constants.sizingTable["ship"][1] / ship.contentWidth, constants.sizingTable["ship"][2] / ship.contentHeight ) return ship end

How would I change this portion of the code to accomodate the changes you’ve suggested making?

. notation would be fine for create() as that creates the instance of ship.  You would then use : notation for anything else in the ship class (like moving, etc.)

Which line is the error happening on? Setting the ship.isBodyActive to false at the beginning of the function or the ship.isBodyActive = true inside the onComplete function?

Where is the code calling shipManage.restoreShip()? Can you share that?

Rob

Which line is the error happening on? Setting the ship.isBodyActive to false at the beginning of the function or the ship.isBodyActive = true inside the onComplete function?

The error is happening at the beginning of the function, where ship.isBodyActive is set to false.

Where is the code calling shipManage.restoreShip()? Can you share that?

 Yeah, sure thing!

local function onCollision(event) -- TODO: Create a file called collisions that returns handles collisions, or at least a collision table local lostLife, newScore, makeSound, remove = level.onCollision(event) -- remove collided objects if ((remove == nil) == false) then for i = #enemyTable, 1, -1 do if (enemyTable[i] == remove[1] or enemyTable[i] == remove[2]) then table.remove(enemyTable, i) break end end end -- Play explosion sound if (makeSound) then audio.play(soundManage.explosionSound) end -- Increase score score = score + newScore updateText() -- update lives or die if ((lostLife == 0) == false) then died = true -- Play explosion sound -- Update lives if (lostLife \> lives) then lives = 0 else lives = lives - lostLife updateText() -- Check on the player's lives if (lives \<= 0) then endGame() else ship.alpha = 0 died = false timer.performWithDelay(1000, shipManage.restoreShip(ship)) end end end end

Thank you in advance!
 

try

timer.performWithDelay(1000, function() shipManage.restoreShip(ship) end)

also use : notation instead of . notation as this will reference your object by default.  i.e.

ship:restoreShip()

You will need to restructure your functions accordingly.  But generally this is the preferred way.  

You then reference self within those functions and that will give you a direct reference to ship.

timer.performWithDelay(1000, function() shipManage.restoreShip(ship) end)

This worked. Is there a particular reason or is it just some quirk?

also use : notation instead of . notation as this will reference your object by default.  i.e.

Could you tell me more about this. So far I’ve built all the modules by putting functions in a table (including a create function when needed) with the dot. What’s the difference?

When you have (param) on a function call (within a timer and other places) it will get executed immediately.  Wrapping it with function() … end turns it into a closure.

Using : means your functions will automatically have a reference to self and keeps everything clean. (more info https://www.lua.org/pil/16.html).  

ship = {} function ship:restore() //reset ship self.x = 0 self.y = 0 end return ship

So using : notation means (with a slight mod) your original code would of worked

timer.performWithDelay(1000, ship:restoreShip)

I know this is going off-topic, but I don’t fully understand how I’d change my code to use the : notation as you described.
For instance, this is how I currently create the ship

local shipManage = {} shipManage.create = function() local ship = {} ship = display.newSprite(mainGroup, sprites.spriteSheet, sprites.sequences\_Ship) -- constants.sizingTable["ship"][1], constants.sizingTable["ship"][2] \_TODO\_ -- 4 is the frame number (declared in order earlier from the image sheet) physics.addBody(ship, {radius = display.contentWidth / 12, isSensor = true}) -- Defines 'physical box' of object and is set as object that can sense collisions but not bounce off ship.myName = "ship" -- Property used for collisions ship:scale( constants.sizingTable["ship"][1] / ship.contentWidth, constants.sizingTable["ship"][2] / ship.contentHeight ) return ship end

How would I change this portion of the code to accomodate the changes you’ve suggested making?

. notation would be fine for create() as that creates the instance of ship.  You would then use : notation for anything else in the ship class (like moving, etc.)