I have given up!

My goal is to create an Enemy class for my game (Enemy.lua). Then during game play i want to be spawning new enemies every second or so.

Each enemy is required to have a function that is to be called every 60 milliseconds or may be called at enterFrame, this function is used for their behavior and AI.

When the enemy is shot, it has to die by calling its :delete function which does all the usual removeSelf() and nilling values.

When the game is over, i need to delete any remaining enemies that havent been shot.

BUT MY PROBLEM IS THAT I CAN NEVER SUCCESFULLY REMOVE ALL THE REMAINING ENEMIES.

Can someone please help me? I need guidance , if you have a stripped down source code i can look at it would be nice.

  • Ive tried everything in the books

  • ive read tons of tutorials

  • i’ve done eveyrhing i can it’s so frustrating. I keep getting “error… attempt to delete nil value” or “error attempt to compare nil value”

  • I’ve been dealing with this BS since Febuary so im getting fed up.

any help will be appreciated.

I haven’t given this much thought but wouldn’t something like this work:

So I’ll assume you are spawning new enemies in a table, let’s call it ‘myEnemies’. How many enemies can be at the screen at any point in time, the max? Let’s say 20 for now

Since this is after they leave the level and not during, you might be able to try something like this?

for i = (#myEnemies - 20), #myEnemies do if myEnemy[i] ~= nil then myEnemy[i]:removeSelf() myEnemy[i] = nil else return true end end

This is assuming that some of the enemies that never get killed get removed automatically after being alive for x seconds.

In case you don’t and if you might still have an enemy #2 who got lucky to survive for the longest time and you’re at enemy #150 then maybe you can just add a loading screen and do, at least for a quick fix

for i = 1, #myEnemy do   end

Something more advanced that I can think of on the spot and always wanted to try but never had a game like this to test it out is something like this:
 

enemyNr = {} eNum = 1 -- everytime you create an enemy also add another value to them, for example myEnemy.num = 1 for the first one created, for enemy #150 it'd be myEnemy.num = 150, also add enemyNr[eNum] = 'whatever number enemy this is' and eNum = eNum + 1, you can also use #enemyNr if it isnt confusing. --next up when you remove enemies is the tricky part, in the function where you remove your enemies, i'll assume you use something like event.object1 or event.object2? local deadEnem = event.object1.num local remEnem = table.indexOf( enemyNr, deadEnem ) -- this will look up the number of the dead enemy in the table. so if it finds enemy #150 in the 5th slot this will return 5, then with the next command we are removing the 5th slot from the table, this table will have a list of all the enemies alive table.remove( enemyNr, remEnem ) eNum = eNum - 1 --since the table will have all the enemies alive at the end you can do something like this for i = 1, eNum do -- you should also be able to use for i = 1, #enemyNr do if you'd like myEnemy[enemyNr[i]]:removeSelf() myEnemy[enemyNr[i]] = nil eNum = eNum - 1 end

Meh the viewer kinda sucks

Since each enemy is controlling their own AI, etc, use a global flag to tell them when the game is over and have them each commit suicide.
[lua]
function controlEnemy()
if gameOver then
display.removeSelf(me)
else
other code here…
end
end
[/lua]

Something like that.

Jay

@hatethinkingofnames. Thanks for your input, i’ve tried the for loop but i keep getting “error, removeSelf() a nil value” maybe what i’ll do is to separate the dead enemies from the alive ones.

@J.A. Whye. Thats the perfect idea that i had, yet when ever they all commit suicide, i get an error “attempt to compare nil value” on their A.I. function. It’s like their timer is still running after they have died. I explicitly cancel their timer when they commit suicide, yet their timer is still calling their A.I function. WTF?

Has anyone of you used Unity 3D SDK? In Unity, you create a script (C# or Java) and attach it to your enemy, in the script, Unity has a built in function called onUpdate(). that function is automatically called on every frame, so thats where you get to code your enemies AI. When the enemy dies, all his functions, variables and timers die with him.

That is what i am trying to duplicate here in Corona SDK. But for some reason .timer.performWithDelay is giving me nightmares.

Has anyone of you used Unity 3D SDK? In Unity, you create a script
(C# or Java) and attach it to your enemy, in the script, Unity has a
built in function called onUpdate(). that function is automatically
called on every frame, so thats where you get to code your enemies AI.
When the enemy dies, all his functions, variables and timers die with
him.

That is what i am trying to duplicate here in Corona SDK. But for some reason timer.performWithDelay is giving me nightmares.

any help is welcomed

If you send the complete code to otterstudios@hotmail.co.uk I’d be happy to take a look.

Nick

Did you skip my third post cuz the viewer made the code look weird?

I did it for you, just copy paste this code in a brand new lua file and it should do what you want it too. Thanks for the interesting problem =)

----------------------------------------------------------------------------------------- -- -- main.lua -- ----------------------------------------------------------------------------------------- -- Your code here display.setStatusBar( display.HiddenStatusBar ) myEnemies = {} enemyNr = {} eNum = 1 function killEveryone(event)     if event.phase == "ended" then     timer.cancel( SpawnTimer )         for i = 1, #enemyNr do         myEnemies[enemyNr[i]]:removeSelf()         myEnemies[enemyNr[i]] = nil         end              end end killBut = display.newRect( 110, 0, 100, 40 ) killBut:addEventListener( "touch", killEveryone ) function killGuys(event)     if event.phase == "began" then         local target = event.target         local deadEnemy = event.target.num         local remEnem = table.indexOf( enemyNr, deadEnemy )         table.remove( enemyNr, remEnem )         target:removeSelf()         target = nil     end end function spawnGuys() myEnemies[#myEnemies + 1] = display.newCircle( math.random( 20, 300), math.random( 40, 460 ), 20 ) myEnemies[#myEnemies].num = #myEnemies enemyNr[#enemyNr + 1] = #myEnemies myEnemies[#myEnemies]:addEventListener( "touch", killGuys ) end SpawnTimer = timer.performWithDelay( 500, spawnGuys, -1 )

@hatethinkingofgames, thanks, i’ll give this a try asap. when i get back to the office.

@nick_sherman, as soon as i return i can zip up the project for you

finally got back to my computer… busy week. ill keep you updated

no errors thus far

I haven’t given this much thought but wouldn’t something like this work:

So I’ll assume you are spawning new enemies in a table, let’s call it ‘myEnemies’. How many enemies can be at the screen at any point in time, the max? Let’s say 20 for now

Since this is after they leave the level and not during, you might be able to try something like this?

for i = (#myEnemies - 20), #myEnemies do if myEnemy[i] ~= nil then myEnemy[i]:removeSelf() myEnemy[i] = nil else return true end end

This is assuming that some of the enemies that never get killed get removed automatically after being alive for x seconds.

In case you don’t and if you might still have an enemy #2 who got lucky to survive for the longest time and you’re at enemy #150 then maybe you can just add a loading screen and do, at least for a quick fix

for i = 1, #myEnemy do   end

Something more advanced that I can think of on the spot and always wanted to try but never had a game like this to test it out is something like this:
 

enemyNr = {} eNum = 1 -- everytime you create an enemy also add another value to them, for example myEnemy.num = 1 for the first one created, for enemy #150 it'd be myEnemy.num = 150, also add enemyNr[eNum] = 'whatever number enemy this is' and eNum = eNum + 1, you can also use #enemyNr if it isnt confusing. --next up when you remove enemies is the tricky part, in the function where you remove your enemies, i'll assume you use something like event.object1 or event.object2? local deadEnem = event.object1.num local remEnem = table.indexOf( enemyNr, deadEnem ) -- this will look up the number of the dead enemy in the table. so if it finds enemy #150 in the 5th slot this will return 5, then with the next command we are removing the 5th slot from the table, this table will have a list of all the enemies alive table.remove( enemyNr, remEnem ) eNum = eNum - 1 --since the table will have all the enemies alive at the end you can do something like this for i = 1, eNum do -- you should also be able to use for i = 1, #enemyNr do if you'd like myEnemy[enemyNr[i]]:removeSelf() myEnemy[enemyNr[i]] = nil eNum = eNum - 1 end

Meh the viewer kinda sucks

Since each enemy is controlling their own AI, etc, use a global flag to tell them when the game is over and have them each commit suicide.
[lua]
function controlEnemy()
if gameOver then
display.removeSelf(me)
else
other code here…
end
end
[/lua]

Something like that.

Jay

@hatethinkingofnames. Thanks for your input, i’ve tried the for loop but i keep getting “error, removeSelf() a nil value” maybe what i’ll do is to separate the dead enemies from the alive ones.

@J.A. Whye. Thats the perfect idea that i had, yet when ever they all commit suicide, i get an error “attempt to compare nil value” on their A.I. function. It’s like their timer is still running after they have died. I explicitly cancel their timer when they commit suicide, yet their timer is still calling their A.I function. WTF?

Has anyone of you used Unity 3D SDK? In Unity, you create a script (C# or Java) and attach it to your enemy, in the script, Unity has a built in function called onUpdate(). that function is automatically called on every frame, so thats where you get to code your enemies AI. When the enemy dies, all his functions, variables and timers die with him.

That is what i am trying to duplicate here in Corona SDK. But for some reason .timer.performWithDelay is giving me nightmares.

Has anyone of you used Unity 3D SDK? In Unity, you create a script
(C# or Java) and attach it to your enemy, in the script, Unity has a
built in function called onUpdate(). that function is automatically
called on every frame, so thats where you get to code your enemies AI.
When the enemy dies, all his functions, variables and timers die with
him.

That is what i am trying to duplicate here in Corona SDK. But for some reason timer.performWithDelay is giving me nightmares.

any help is welcomed