Attempt to index global variable issue

Hi all,

Im relatively new to coding but have been enjoying it greatly. So far I have been able to work out most issues looking on the forums/guides etc but I can’t seem to get my head around the variable and function scope issue, specifically when it comes to calling and removing objects from inside a function. As such I was wondering whether someone could just give some pointers. 

I have some code below which works when I only use one fireball. The fireball shoots and transitions correctly and I can Selfremove it after it reaches a certain point (y=400). However the problem I always seem to encounter in this example and others is when I try to put and incremental for loop in to create 3 fireballs. In the example below I need 3 fireballs to be shot at random locations and when they reach y=400 they all need to be destroyed.

However I always seem to get an error stating "attempt to index field (a nil value). I assume this is something to do with upvalues & table scope and me trying to call something outside of the loop & function but whatever I try to do I get the same value.

Would really appreciate any help.

PS I know the code is rough and I could probably cut some out but hopefully I’ll do that later.

Example one

local fire ={} local idx = 0 function shootFire() for ball = 1, 3 do idx = 0 fireball=display.newSprite( monsterSheetFireball, sequenceData) fireball:setSequence("walk") fireball:play() fireball.x = math.random(40,160) fireball.y = 40 transition.to(fireball, {time = 4000, y = 200, onComplete = removeFireball}) fire[idx] = fireball fire[idx].idx = idx end timer.performWithDelay ( 1000, goBack, 1 ) end function removeFireball() fire[1]:removeSelf() fire[1] = nil fire[2]:removeSelf() fire[2] = nil fire[3]:removeSelf() fire[3] = nil end

Example 2:

In this example I tried to increment through creating monsters (changing monster1 for monster[i] but I run into the same problem (not to do with removeself but again an index global error. To get around it I have 5 copies of the below for each monster which I know is not ideal.

local monster1=display.newSprite( monsterSheet, sequenceData) monster1:setSequence("walk") monster1:play() monster1.speed = math.random(2,4) monster1.x = math.random ( 20, 30 ) monster1.y = -400 monster1.initX = monster1.x monster1.amp = math.random(20,50) monster1.angle = math.random(30,200) function moveMonster1(event) local posValue = math.random(10, 700) local negValue = posValue \* - 1 if monster1.y \> 480 then monster1.y = negValue monster1.speed = math.random(2,4) monster1.x = math.random ( 20, 320 ) monster1.initX = monster1.x monster1.amp = math.random(20,100) monster1.angle = math.random(40,100) else monster1.y = monster1.y + monster1.speed monster1.angle = monster1.angle + .1 monster1.x = monster1.amp \* math.sin(monster1.angle)+monster1.initX end end Runtime:addEventListener ( "enterFrame", moveMonster1 )

Think this may be an issue with returning a a table value (upvalue)? Still cannot work it out. Works fine if outside of a function but I need to call the function

In example 1, is “idx” ever not 0?

You seem to be setting fire[0] on each iteration, which is just replacing the previous reference. And then you’re trying to destroy fire[1], fire[2], and fire[3] in removeFireball (fire[1], fire[2], fire[3] don’t exist). The other problem is each time a single fireball completes a transition, you’re attempting to destroy all 3 fireballs, rather than just destroying the one fireball that completed the transition.

Perhaps you should be setting “fire[ball] = fireball” in the loop (as ball goes from 1 to 3), rather than idx, and pass the index to the removeFireball function so that only the fireball that has completed the transition is removed.

Think this may be an issue with returning a a table value (upvalue)? Still cannot work it out. Works fine if outside of a function but I need to call the function

In example 1, is “idx” ever not 0?

You seem to be setting fire[0] on each iteration, which is just replacing the previous reference. And then you’re trying to destroy fire[1], fire[2], and fire[3] in removeFireball (fire[1], fire[2], fire[3] don’t exist). The other problem is each time a single fireball completes a transition, you’re attempting to destroy all 3 fireballs, rather than just destroying the one fireball that completed the transition.

Perhaps you should be setting “fire[ball] = fireball” in the loop (as ball goes from 1 to 3), rather than idx, and pass the index to the removeFireball function so that only the fireball that has completed the transition is removed.