setLinearVelocity (a nil value) problem

Error setLinearVelocity (a nil value) when the enemy collided with the player and call the spawnEnemy function 

 local physics = require "physics" physics.start() physics.setDrawMode("hybrid") physics.setGravity(0,0) local \_W, \_H = display.contentWidth, display.contentHeight local enemy local player = display.newRect(\_W/2,\_H/2,50,50) physics.addBody(player,"dynamic") local function spawnEnemy() enemy = display.newRect(\_W/2,10,20,20) physics.addBody(enemy,"kinematic") enemy:setLinearVelocity(0,40) end local function onCollision(e) enemy:removeSelf() enemy = nil spawnEnemy() end spawnEnemy() Runtime:addEventListener("collision",onCollision)
  • Try to use locals instead of globals whenever possible,
  • Consider using a table listener instead,
  • Remember to use phases in collision, touch, and other listeners.  In this case only delete/spawn on ‘began’ phase,
  • It is safer to use 'display.remove( obj ) ’ instead of ‘obj:removeSelf()’.  The later will crash if obj is already removed.
  • Thanks for posting in a code block <>. You rock!

Try this instead, 

local physics = require "physics" physics.start() physics.setDrawMode("hybrid") physics.setGravity(0,0) local \_W, \_H = display.contentWidth, display.contentHeight -- Forward declare spawn function -- local spawnEnemy local player = display.newRect(\_W/2,\_H/2,50,50) physics.addBody(player,"dynamic") local function enemyCollision( self, event ) if( event.phase == "began" ) then self:removeEventListener( "collision" ) display.remove(self) spawnEnemy() end return true end spawnEnemy = function() local enemy = display.newRect(\_W/2,10,20,20) physics.addBody(enemy,"kinematic") enemy:setLinearVelocity(0,40) enemy.collision = enemyCollision enemy:addEventListener( "collision" ) return enemy end spawnEnemy()

Post #2 to answer question.  Please read Post #1 above also.

Here is an alternate solution, where the player has the collision listener instead:

local physics = require "physics" physics.start() physics.setDrawMode("hybrid") physics.setGravity(0,0) local \_W, \_H = display.contentWidth, display.contentHeight -- Forward declare spawn function -- local spawnEnemy local function playerCollision( self, event ) local other = event.other if( event.phase == "began" ) then if( other.isEnemy ) then other:removeEventListener( "collision" ) display.remove( other ) spawnEnemy() end end return true end local player = display.newRect(\_W/2,\_H/2,50,50) physics.addBody(player,"dynamic") player.collision = playerCollision player:addEventListener( "collision" ) spawnEnemy = function() local enemy = display.newRect(\_W/2,10,20,20) physics.addBody(enemy,"kinematic") enemy:setLinearVelocity(0,40) enemy.isEnemy = true return enemy end spawnEnemy()
  • Try to use locals instead of globals whenever possible,
  • Consider using a table listener instead,
  • Remember to use phases in collision, touch, and other listeners.  In this case only delete/spawn on ‘began’ phase,
  • It is safer to use 'display.remove( obj ) ’ instead of ‘obj:removeSelf()’.  The later will crash if obj is already removed.
  • Thanks for posting in a code block <>. You rock!

Try this instead, 

local physics = require "physics" physics.start() physics.setDrawMode("hybrid") physics.setGravity(0,0) local \_W, \_H = display.contentWidth, display.contentHeight -- Forward declare spawn function -- local spawnEnemy local player = display.newRect(\_W/2,\_H/2,50,50) physics.addBody(player,"dynamic") local function enemyCollision( self, event ) if( event.phase == "began" ) then self:removeEventListener( "collision" ) display.remove(self) spawnEnemy() end return true end spawnEnemy = function() local enemy = display.newRect(\_W/2,10,20,20) physics.addBody(enemy,"kinematic") enemy:setLinearVelocity(0,40) enemy.collision = enemyCollision enemy:addEventListener( "collision" ) return enemy end spawnEnemy()

Post #2 to answer question.  Please read Post #1 above also.

Here is an alternate solution, where the player has the collision listener instead:

local physics = require "physics" physics.start() physics.setDrawMode("hybrid") physics.setGravity(0,0) local \_W, \_H = display.contentWidth, display.contentHeight -- Forward declare spawn function -- local spawnEnemy local function playerCollision( self, event ) local other = event.other if( event.phase == "began" ) then if( other.isEnemy ) then other:removeEventListener( "collision" ) display.remove( other ) spawnEnemy() end end return true end local player = display.newRect(\_W/2,\_H/2,50,50) physics.addBody(player,"dynamic") player.collision = playerCollision player:addEventListener( "collision" ) spawnEnemy = function() local enemy = display.newRect(\_W/2,10,20,20) physics.addBody(enemy,"kinematic") enemy:setLinearVelocity(0,40) enemy.isEnemy = true return enemy end spawnEnemy()