I’m trying out some OOP and its killing me, particularly with timers.
I have a simple class object for a snake. I create the snake and when it is touched, it pauses for 2 seconds and then resumes moving. My timer has an id (self.hurtTimer)and check for self.iAlive. My Destroy activity cancels this timer, and sets isAlive to false.
local physics = require('physics') local sounds = require('libs.sounds') local \_M = {} local newPuff = require('classes.puff').newPuff function \_M.newSnake(params) local snake = display.newImageRect(params.g, 'images/ammo/normal.png', 64, 64) snake.x, snake.y = params.x, params.y if params.speed \> 0 then physics.addBody(snake, 'dynamic', {density = 1000, friction = 0, bounce = 1, radius = snake.width \* 0.45}) else physics.addBody(snake, 'static', {density = 1000, friction = 0, bounce = 1, radius = snake.width \* 0.45}) end snake.lives = params.lives print(snake.lives) snake:setFillColor(.9,0.1,0.1,.5) snake.isHungry = true snake.isAlive = true function snake:destroy() self.isHungry = false self.isAlive = false if self.hurtTimer then timer.cancel(self.hurtTimer) end self.hurtTimer = nil self:removeSelf() end --Motion if params.speed \> 0 then local direction = math.random(-180,180)/180\*math.pi snake:setLinearVelocity( math.cos(direction) \* params.speed\*50, math.sin(direction) \*params.speed\*50, snake.x, snake.y ) local vx, vy = snake:getLinearVelocity() snake.bearing = math.atan2(vy, vx) end --touch function snake:touch(event) if event.phase == 'began' and self.isHungry then if self.lives \> 1 then self.lives = self.lives - 1 print("Lives Left: " .. self.lives) self.isHungry = false if params.speed \> 0 then self:setLinearVelocity( 0,0, self.x, self.y ) end self.hurtTimer = timer.performWithDelay( 2000, function() if self.isAlive then local direction = math.random(-180,180)/180\*math.pi self:setLinearVelocity( math.cos(direction) \* params.speed\*50, math.sin(direction) \*params.speed\*50, self.x, self.y ) local vx, vy = self:getLinearVelocity() self.bearing = math.atan2(vy, vx) self.isHungry = true end end ) else sounds.play('bug') newPuff({g = params.g, x = self.x, y = self.y}) self:destroy() end end return true end snake:addEventListener('touch') return snake end return \_M
On my game scene, I have some code in the scene:hide function to cleanup the scene when I exit the stage:
for i = 1, #self.snakes do if self.snakes[i] then self.snakes[i]:destroy() table.remove(self.snakes,i) end end
I am basing this project on the cannon game example, and it is using the intermediate scene.
So according to my logic, destroying the snake should cancel the timer, or at least make sure the timer doesn’t do anything. And yet, when I restart or go to the next level:
snake.lua:67: attempt to call method 'setLinearVelocity' (a nil value)
This happens when I have more than 2+ snakes on the screen, and press on them , then quickly pause and restart the level.
What am I doing wrong? I think there’s something I’m not doing right in regards to scene changing and clearing objects but I am truly stumped. Could someone please help me, or at least point me to some tutorial / example of how one should be doing this?