0
votes

I'm pretty new to lua as you can probably tell by the code, i'm trying to remove an object that says "Stop!" when the time runs out by using an event listener on a button object that's also created when the time runs out. This returns the error attempt to index global 'stopit' (a nil value). I declared it as a local var in the class that adds it to the screen so i'm not sure whats going on. I have organized and tried this several different ways and I can't get it to loop continually without randomly crashing either immediately or after one or two rounds of the game.

Here is the code:

display.setStatusBar(display.HiddenStatusBar)

local centerX = display.contentCenterX
local centerY = display.contentCenterY
local score = 0
local dextime;
local stopit;
local button3;

function newTarget(event)
timer.performWithDelay(100, function() display.remove(target) end)
transition.to(target, {time=99, xScale=.4, yScale=.4})
timer.performWithDelay(101, dexit)
score = score + 10
scoreTxt.text = ("Score:" .. score)
end



function dexit()
stopit = display.newImage("stop.png")
stopit.x = 300
stopit.y = 600
stopit.isVisible = false
button3 = display.newImage("button3.png")
button3:addEventListener("tap", removeitems)
button3.x = centerX
button3.y = centerY
button3.isVisible = false
target = display.newImage("target.png")
target.xScale = .25
target.yScale = .25
target.x  = math.random(50, 550)
target.y = math.random(50, 750)
target:addEventListener("tap", newTarget)   
 local function removeitems(event)
stopit:removeSelf()
button3:removeSelf()
scoreTxt:removeSelf()
timerTxt:removeSelf()
timer.performWithDelay(500, setup)
dextime = 15
score = 0
end
timer.performWithDelay(15000, function() display.remove(target) end)
timer.performWithDelay( 15000, function() button3.isVisible = true end)
timer.performWithDelay(15000, function() stopit.isVisible = true end)
end

local function dexgo()
timer.performWithDelay(1000, function() dextime = dextime - 1 end, 15)
timer.performWithDelay(1001, function() timerTxt.text = ("Time:" .. dextime) end, 15)
dexit()
end

local function one2()
local one = display.newImage("1.png")
    one.x = centerX
    one.y = centerY
    one.alpha = 0
    transition.to(one, {time=1000, alpha =1, onComplete=dexgo})
    timer.performWithDelay( 1000, function() 
    display.remove(one)
end, 1)

end

local function two2()

    local two = display.newImage("2.png")
    two.x = centerX
    two.y = centerY
    two.alpha = 0
    transition.to(two, {time=1000, alpha =1, onComplete=one2})
    timer.performWithDelay( 1000, function() 
    display.remove(two)
end, 1)

end

local function dexMode()
local three = display.newImage("3.png")
    three.x = centerX
    three.y = centerY
    three.alpha = 0
    timerTxt = display.newText("Time:" .. dextime,-1, centerX - 440,      "Helvetica", 40)
    scoreTxt = display.newText( "Score:" .. score, 440, -140, "Helvetica", 40)
    display.remove(mode1)
    display.remove(mode2)
    display.remove(title)
    transition.to(three, {time=1000, alpha =1, onComplete=two2})
    timer.performWithDelay( 1000, function() 
    display.remove(three)
end, 1) 
    bg = nil
    title = nil
    mode1 = nil
    mode2 = nil
end
function listener(event) 
   simpleMode() 
end 

function listener2(event) 
dexMode() 
end 




function startGame()
transition.to( title, { time=2000, y=0, alpha=.9, onComplete=showTitle})
transition.to(bg, { time=2000, y=centerY, alpha=1})
transition.to(mode1, { time=2000, x=centerX, alpha=.9})
transition.to(mode2, { time=2000, x=centerX, alpha=.9})


end

function setup()
dextime = 15;
bg = display.newImage("background.png")
bg.yScale = 1.4
bg.alpha = 0
title = display.newImage("title.png")
title.x = centerX
title.y = -200
title.alpha = 0
mode1 = display.newImage("button1.png")
mode1.xScale = 1.23
mode1.yScale = 1.23
mode1.x = 800
mode1.y = 500
mode1.alpha = 0
mode2 = display.newImage("button2.png")
mode2.xScale = 1.23
mode2.yScale = 1.23
mode2.x = -200
mode2.y = 625
mode2.alpha = 0
mode1:addEventListener( "touch", listener )
mode2:addEventListener( "touch", listener2 )
startGame()
end

setup()
3

3 Answers

1
votes

The usage of in stopit button3, scoreTxt and timerTxt in function removeitems(event) are globally scoped. When removeitems gets called in dexit it cannot see the local variables you declared in dexit.

The easiest solution is to make removeitems a closure by moving it into dexit:

function dexit()
  local stopit = display.newImage("stop.png")
  local button3 = display.newImage("button3.png")

  local function removeitems(event)
    stopit:removeSelf()
    button3:removeSelf()
    scoreTxt:removeSelf()
    timerTxt:removeSelf()
    timer.performWithDelay(500, setup)
  end

  -- ...
end
0
votes

Try this:

if(stopit~=nil)then
    stopit:removeSelf()
end
0
votes

You are getting this error due to timer and transition. When you are removing an object without canceling timer or transition, it's calling in loop and getting nil value after removing once. First of all you need to store all the timer and transition in array and release array while stoping game or changing scene. Then Reinitialize array again.

Ex: local timerId = {}

local TransitionID = {}

timerId[#timerId+1] = timer.performWithDelay(15000, function() display.remove(target) end)

TransitionID[#TransitionID+1] = transition.to(two, {time=1000, alpha =1, onComplete=one2})

When removing all the object remove timer and transition first.

for i = 1, #timerId do

        timer.cancel(timerId[i])
        timerId[i] = nil
        timerId = {} //Initializing array
end

for j = 1, #transitionID do

 transition.cancel(transitionID[j])
 transitionID[j] = nil
  transitionID = {}

end