Removing Object Rotation Issue

I am having a problem with a rotating twinkling star in my game. I rotate the star using code that runs on a timer.  I cancel the timer on the function that terminates the game, but it still gives me the error: Corona Simulator[192]: Runtime error /classic1.lua:2118: attempt to perform arithmetic on field ‘rotation’ (a nil value). Even though I remove the timer, it still tries to rotate the star. 

This is the code where I create the twinkling star:

[lua]

local function spawnTStar() 

local tstar = display.newImage(“TStar1-1.png”)

tstar.x = math.random(0,300)

tstar.y = math.random(0,300)

local function tstarAnimation()

local function GlowAlpha()

tstarGlowing = transition.to(tstar,{time=1500, alpha=0.3, onComplete=starsAnimation})

end

tstarGlowing = transition.to(tstar,{time=1500, alpha=1.0, onComplete=GlowAlpha})

end

tstarGlowing = transition.to(tstar,{time=1500, alpha=0, onComplete=starsAnimation})

local function rotateTStar()

if (tstar ~= nil) then

tstar.rotation = tstar.rotation + 1

end

end

rttmr = timer.performWithDelay(1,rotateTStar,-1)

local function eraseTStar()

display.remove(tstar)

tstar = nil

timer.cancel(rttmr)

end

ettmr = timer.performWithDelay(2200,eraseTStar,1)

local function addScoreTStar(xLoc,yLoc)

local xLoc = xLoc

local yLoc = yLoc

local function displayScoreText(textLine, theX, theY)

local string = textLine

local theX = theX

local theY = theY

local scoreText = display.newText(string, 0, 0, “Apple Casual”, 20)

scoreText:setTextColor( 1, 1, 1, 1 )

scoreText.alpha = 1.0

scoreText.xOrigin = theX

scoreText.yOrigin = theY

localGroup:insert(scoreText)

local function destroyText()

display.remove(scoreText)

scoreText = nil

end

local newY = theY - 30

textAnim = transition.to( scoreText, {time=1200, alpha=0, y=newY, onComplete=destroyText} )

end

score = score + 2

scoreDisplayText.text = score

tstarScore = tstarScore + 1

saveValue(“tstarScore.data”,tstarScore)

print(tstarScore, “: tstarScore”)

displayScoreText( “+2”, xLoc, yLoc)

end

local function addScore(event)

if (event.phase == “ended”) then

addScoreTStar(tstar.x,tstar.y)

display.remove(tstar)

tstar = nil

timer.cancel(rttmr)

end

end

tstar:addEventListener(“touch”, addScore)

return tstar

end

ststmr = timer.performWithDelay(4000, spawnTStar, -1)

[/lua] 

This is the function where the game is terminated and I cancel the timer: 

[lua]

local function loseGame()

if (spaceshipLives == 2) then

display.remove(spaceship3)

spaceship3 = nil

end

if (spaceshipLives == 1) then

display.remove(spaceship2)

spaceship2 = nil

end

if (spaceshipLives == 0) then

display.remove(spaceship1)

spaceship1 = nil

display.remove(redspaceship)

redspaceship = nil

Runtime:removeEventListener(“enterFrame”, spawnRedSpaceships)

Runtime:removeEventListener(“enterFrame”, loseGame)

timer.cancel(rttmr)

saveValue(“score1.data”, score)

timer.cancel(ststmr)

cstmr = timer.performWithDelay(1000, director:changeScene(“levelslosescreen”, “fade”), 1)

if score > highScore then

highScore = score

saveValue(“highscore1.data”, highScore2)

print(“High Score Received!”)

end

end

end

Runtime:addEventListener(“enterFrame”, loseGame)

highScore = tonumber(loadValue(“highscore1.data”))

[/lua]

If someone can tell me why this error is occurring, that would be great! Thanks a lot.

It would help if the code didn’t lose the indenting :slight_smile: (any chance of this being fixed Corona ?)

It looks to me like you have several levels of local functions here, and that you are creating an encapsulated object. I am wondering if when you create your local functions after the initial tstar = display.newImage() call, then the local functions are creating a closure, so the value is then stuck at whatever tstar is , e.g. a pointer to the display object, so when you nil it later on, it doesn’t nil the one in the closure which still has the value tstar had at the start e.g. it is a reference to the now deleted image.

Then when you do your rotate code, the tstar image, still pointing to the now delete object, passes the nil test (because it’s the closure value)  and tries to rotate something which of course no longer has a rotation value, because it’s been removed already.

I’m not quite sure how best to fix this ; I’d write it as an object and lose all the local functions, personally. I always think closures are a bad idea and try to avoid them wherever possible unless I actually want that functionality.

So when the rotation code is executed, it passes the nil test because of the closure value, which is basically the tstar in the closure function? I know that the error is occurring at the function where I try to cancel the timers because that’s when it fails to rotate the tstar. How come it doesn’t fail to rotate the tstar elsewhere, and only when the game ends? And one more note: the error only appears at the end of the game when the tstar is rotating at the same time. 

Is there another approach to tackling this problem? I can’t think of another way besides a spawning closure function, but it seems that it’s not going to work in this case. 

Thanks so much for continuing to help me on this! 

Because, I think, the error comes after you have called remove() on your image - the table still exists, but the objects don’t.

I’ll give the other approach some thought ; what exactly are you trying to do, it’s unfortunate that your code has been made hard to read because of the indentation being removed.

I’m basically trying to create the effect of a twinkling star. It appears every 4 seconds, visible and rotating for 2.2 seconds.  If it is tapped when it is visible and rotating, the user earns two points. It spawns infinitely throughout the whole game until of course, the game ends. My approach as shown in the code above is using a spawn function and closure functions to set a rotation timer and a touch listener. In addition, the timer (ststmr in this case) determines how often it spawns. 

I have looked at it and tried some fixes, but I can’t find a way to remove both the closure object and actual object when the game ends. That would be great if a more efficient solution to this code exists. Thanks so much!

It would help if the code didn’t lose the indenting :slight_smile: (any chance of this being fixed Corona ?)

It looks to me like you have several levels of local functions here, and that you are creating an encapsulated object. I am wondering if when you create your local functions after the initial tstar = display.newImage() call, then the local functions are creating a closure, so the value is then stuck at whatever tstar is , e.g. a pointer to the display object, so when you nil it later on, it doesn’t nil the one in the closure which still has the value tstar had at the start e.g. it is a reference to the now deleted image.

Then when you do your rotate code, the tstar image, still pointing to the now delete object, passes the nil test (because it’s the closure value)  and tries to rotate something which of course no longer has a rotation value, because it’s been removed already.

I’m not quite sure how best to fix this ; I’d write it as an object and lose all the local functions, personally. I always think closures are a bad idea and try to avoid them wherever possible unless I actually want that functionality.

So when the rotation code is executed, it passes the nil test because of the closure value, which is basically the tstar in the closure function? I know that the error is occurring at the function where I try to cancel the timers because that’s when it fails to rotate the tstar. How come it doesn’t fail to rotate the tstar elsewhere, and only when the game ends? And one more note: the error only appears at the end of the game when the tstar is rotating at the same time. 

Is there another approach to tackling this problem? I can’t think of another way besides a spawning closure function, but it seems that it’s not going to work in this case. 

Thanks so much for continuing to help me on this! 

Because, I think, the error comes after you have called remove() on your image - the table still exists, but the objects don’t.

I’ll give the other approach some thought ; what exactly are you trying to do, it’s unfortunate that your code has been made hard to read because of the indentation being removed.

I’m basically trying to create the effect of a twinkling star. It appears every 4 seconds, visible and rotating for 2.2 seconds.  If it is tapped when it is visible and rotating, the user earns two points. It spawns infinitely throughout the whole game until of course, the game ends. My approach as shown in the code above is using a spawn function and closure functions to set a rotation timer and a touch listener. In addition, the timer (ststmr in this case) determines how often it spawns. 

I have looked at it and tried some fixes, but I can’t find a way to remove both the closure object and actual object when the game ends. That would be great if a more efficient solution to this code exists. Thanks so much!