My spawn object with tables doesnt work!

can you post your spawnEnemy and scene.hide functions ?

Sure thing!

At the top i have

local enemytable = {} local enemypics = {"images/beetleship.png","images/octopus.png", "images/rocketship.png"} local enemyCnt = 0 local scoreStep = 5

Then i have spawnenemy

function spawnEnemy() enemyCnt = enemyCnt + 1 enemypic = enemypics[math.random(#enemypics)] enemytable[enemyCnt] = display.newImage(scene.view,enemypic) --sceneGroup:insert(enemytable[enemyCnt]) enemytable[enemyCnt]:addEventListener ( "tap", shipSmash ) if math.random(2) == 1 then enemytable[enemyCnt].x = math.random ( -100, -10 ) else enemytable[enemyCnt].x = math.random ( display.contentWidth + 10, display.contentWidth + 100 ) enemytable[enemyCnt].xScale = -1 end enemytable[enemyCnt].y = math.random (display.contentHeight) enemytable[enemyCnt].trans = transition.to ( enemytable[enemyCnt], { x=centerX, y=centerY, time=math.random(2500-speedBump, 4500-speedBump), onComplete=hitPlanet } ) speedBump = speedBump + 50 end local function gameLoop(e) if score == scoreStep then spawnEnemy() scoreStep = scoreStep + 5 end end Runtime:addEventListener("enterFrame", gameLoop)

Scenehide

-- "scene:hide()" function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Called when the scene is on screen (but is about to go off screen). -- Insert code here to "pause" the scene. -- Example: stop timers, stop animation, stop audio, etc. Runtime:removeEventListener( "enterFrame", gameLoop ) for i = enemyCnt, 1, -1 do if enemytable[enemyCnt].trans then transition.cancel(enemytable[enemyCnt].trans) enemytable[enemyCnt].trans = nil end end -- if enemy.trans then -- transition.cancel(enemy.trans) -- enemy.trans = nil -- end elseif ( phase == "did" ) then -- Called immediately after scene goes off screen. display.remove(planet) display.remove(enemytable[enemyCnt]) display.remove(scoreTxt) pauseBtn.alpha=0 end end

Do tell me if you need more information!

if you want to remove all the enemy units, you have to do a loop, just like you did with canceling the transitions in the ‘will’ phase.

As you are using it now, enemyCnt in the ‘did’ phase will only destroy the last enemy object.  

Can you see how enemyCnt value only changes when an enemy is spawned.  So when you use that anywhere in the code it is always going to be a value that equals the number of enemies.  So, as you have it, you are simply removing the last enemy object.

So when you make the loop in the ‘did’ phase, it needs to be a reverse loop, because you will be removing objects from the enemy table.  

When you did the cancel transitions loop in the ‘will’ phase, you could and probably should do the loop in normal order. Although either way works. It just does not need to be a reverse loop.

I know everytime i spawn a unit it becomes enemyCnt + 1 so it becomes +2, +3 etc… But… how do i make a loop for that? With enemyCnt -1? Because im not sure what that count itself do. The spawning is done with spawnEnemy right? What does the enemyCnt do?

enemyCnt just keeps track of the total enemies.  Then, in the spawnEnemy function it is used to ‘index’ which enemy unit in the enemy table you are referring to as you position the enemy object, assign it an event listener and so forth.  

once out of the spawnEnemy function, enemyCnt will be equal to whatever is the total number of enemies.

So, in this example loop, if you have created 15 enemies, enemyCnt will be equal to 15.

In this sample, the loop runs from 1 to 15, and if the enemy has an active transition, it will cancel it.

  for i = 1, enemyCnt do if enemytable[i].trans then transition.cancel(enemytable[i].trans) enemytable[i].trans = nil end   end  

in this sample below, since we are removing display objects (enemy images) and clearing the enemy table, it works best to 

loop backwards…  So the loop goes from 15, to 1.   the -1, tells the loop to subtract 1 each time, so it removes enemy table index #15 first, then 14, then 13 … etc

  for i = enemyCnt, 1, -1 do  display.remove(enemyTable[i]) enemyTable[i] = nil end enemyTable = nil  

I would suggest you can learn a lot of this by checking out some good tutorials and other code other developers have shared. Looking over those tutorials and code and getting to understand them, will really help.  But, you should go over several of them.  Many indie developers have learned this way. It takes a lot of time, but it is a good way to get a feel for this stuff.

Here are just a few you may want to check out.  I have not checked these out, so I am not sure which is the best of them. But you could check each of them out.

http://coronalabs.com/blog/2014/11/04/tutorial-basic-spawning/

http://coronalabs.com/blog/2011/09/14/how-to-spawn-objects-the-right-way/

http://www.christianpeeters.com/complete-app-tutorial/create-a-simple-space-shooter-with-corona-sdk/

http://www.tandgapps.co.uk/resources/tutorial-space-shooter-in-240-lines/

http://www.raywenderlich.com/22064/how-to-make-a-simple-game-with-corona

There are even more then these out there on the internet.  You are likely to find even better ones if you search the internet.

Alright thanks for everything! I will give it a look!

Hey there guys! I still need one little bit of advice and then my app is all done!
I have done various patching and editing and most of the bugs and problems are gone by now!
How do i get the loop back after i removed it? It seems that changing the emptytable = nil to {} Doesnt allow me to spawn my enemies anymore and it stays empty if i reload the scene!

Im using this atm:

for i = enemyCnt, 1, -1 do display.remove(enemytable[i]) enemytable[i] = nil end enemytable = {}

Danny,

Probably need to see your ‘scene.create’ and ‘scene.show’ code.

Somewhere in one of those functions you would need to re-do the enemy table. This all is assuming, that when you leave the scene and return you did not want to save anything. In other words, start everything over each time player exits and returns to the scene. Otherwise, you will have to figure out what things you want to save when a scene is paused or closed.

Edit: I think i know the problem! I am also cancelling the transition so i do recall the table but i just need to recall the transition again! Im going to look up how to do that exactly!

I am trying to recall this line but it gives me an error!

enemytable[enemyCnt].trans = transition.to ( enemytable[enemyCnt], { x=centerX, y=centerY, time=math.random(2500-speedBump, 4500-speedBump), onComplete=hitPlanet } )

for i = 1, enemyCnt do if enemytable[i].trans then transition.cancel(enemytable[i].trans) enemytable[i].trans = nil end end for i = enemyCnt, 1, -1 do -- enemycnt till 1 everytime -1 display.remove(enemytable[i]) enemytable[i] = nil end enemytable = nil

Hi there!

I am trying to set the table back to what it was with the sceneshow… i dont have much there only 2 functions.

The table is set again with enemytable = {}, this should set the table back since the for loop sets it to nil. All i need to do is set it back to {} right?

-- "scene:create()" function scene:create( event ) local sceneGroup = self.view -- Initialize the scene here. -- Example: add display objects to "sceneGroup", add touch listeners, etc. end -- "scene:show()" function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Called when the scene is still off screen (but is about to come on screen). print("Show play scene") elseif ( phase == "did" ) then -- Called when the scene is now on screen. -- Insert code here to make the scene come alive. -- Example: start timers, begin animation, play audio, etc. createPlayScreen(sceneGroup) setUpDisplay(sceneGroup) enemytable = {} end end

Danny,

I imagine that one of 2 functions at the end of the show function, handle the initial spawning of the enemies, but I am just guessing. If so,  I would think you need to move the last line  ‘enemyTable = {}’ up 2 lines, to just above the call to those 2 functions (createPlayScreen) & (setUpDisplay).  You need to make sure the table {} gets assigned to enemyTable, before you call those functions.

The error you mention with regards to the transition call , is likely because of the same issue, where you assign enemyTable after the function calls, and as such the table is nil and those transition calls are using enemyTable which does not exist when that code is ran.  At least that is the best I can tell from the limited bit of code you show here.

I figured it out! I made an function that allows it to reset and now it all works!
Now all i need to do is get the graphics and music done! Thank you~
By the way… have you seen my private message? It would be great if it was possible!

It looks to me like you would want all the code you have in the bottom half of the function inside the

 – for i = 1, 5 do  loop.

You are getting nil, because all the references to ‘i’,  below the ‘for-loop’ see ‘i’ as nil.

Get everything in the loop, except maybe the last line … speedBump = speedBump + 50.  As I am not sure when or how often you want that speedBump incremented. If you put that line inside that ‘for-loop’ then it will increment 5 times each call to spawnEnemy. 

It looks like every time you call the spawnEnemy, you are going to run that loop and create 5 enemy images. Is that your intention? Or were you going to just want to create one enemy image per spawn?  

Hope this helps

Thank you for your reply as i can get it to run now, but my problem is i am spawning too many enemies with this function!
Not even 5 but more like 50!! What do i need to change to make it to spawn only 1? And how do i manually add one later when a certain score has been reached?

Danny,

I kept your code as it was (for the most part).  So, using your code layout I made a few changes. Generally, I would not do it exactly as you have it, but as you have it is okay. There are many ways to do the same thing. So we will stick with how you have it laid out, and just a few changes need to be made.

  1. Took the for loop out of the ‘spawnEnemy’ function

  2. Got rid of the ‘enemies display group’. It is not being used in your code. It is local to the spawnEnemy function and I do not see anywhere that is is actually needed or used… other then inserting the enemy objects into it… it did not seem to me it is needed there.

  3. I moved the enemy table and enemy pics out of the spawnEnemy function. You should put that code at the top of the file.

  4. in the spawnEnemy function, took out the ‘i’ and used enemyCnt, and just increment that at the end of the function each time an enemy is spawned.

  5. Created an ‘enterFrame’ event called gameLoop to check every frame to see if score has reached whatever amount, and spawn and enemy.

good luck.  

  local enemytable = {} local enemypics = {"images/beetleship.png","images/octopus.png", "images/rocketship.png"} local enemyCnt = 1   function spawnEnemy() enemypic = enemypics[math.random(#enemypics)] enemytable[enemyCnt] = display.newImage(enemypic) enemytable[enemyCnt]:addEventListener ( "tap", shipSmash ) if math.random(2) == 1 then enemytable[enemyCnt].x = math.random ( -100, -10 ) else enemytable[enemyCnt].x = math.random ( display.contentWidth + 10, display.contentWidth + 100 ) enemytable[enemyCnt].xScale = -1 end enemytable[enemyCnt].y = math.random (display.contentHeight) enemytable[enemyCnt].trans = transition.to ( enemytable[enemyCnt], { x=centerX, y=centerY, time=math.random(2500-speedBump, 4500-speedBump), onComplete=hitPlanet } ) speedBump = speedBump + 50 enemyCnt = enemyCnt + 1 end   for i = 1, 5 do spawnEnemy() end     local function gameLoop(e) if score == 5000 then spawnEnemy() end end   Runtime:addEventListener("enterFrame", gameLoop)      

Again thank you for answering me so fast.

I have tried to insert your code and i ran into two problems. The first is that if i start the game i get an error which means i can not start the game. If i remove enemytable[enemyCnt]:addEventListener ( “tap”, shipSmash ) then i can start the game but not destroy the ships.
The second is when i start the game it spawns 5 enemies at start without me calling the function yet.
 

EDIT: I removed the for loop and i only get 1 when i press start now! Only need to figure out why the tap shipsmash addeventlistener doesnt work anymore!

Danny,

  1. It spawns 5 enemies without you calling the function, because in the sample I sent, I call the spawning 5 times, with the for loop that I placed just below the function spawnEnemy.  Take that loop and put it in your button event, or whatever mechanism you are using when you want to start spawning.

  2. As to the error that goes away when you remove the line :

enemytable[enemyCnt]:addEventListener ( “tap”, shipSmash )

I am not sure. That was as you had it coded originally, it just ‘indexes’ using enemyCnt instead of i, and as I set the code, that should not have caused an issue. I am not sure if you may have change something else in your code, or accidentally changed something.

Did you delete ‘shipSmash’ function?  Is that function above the ‘spawnEnemy’ function in your code?

You may have to post all (or at least more of your code) for me to see what might be wrong.

You were right! I had to put it above my spawn code now it works halfish. The runtime event of checking for the score(i set it to 5) spawns endlessly instead of 1 time. How do i change this?

There are a lot of ways to do this, depending on what you want to achieve; but here is the quick and simple solution.

This assumes you want to spawn a new enemy every time score increases by 5, see first example below.

If you only want to do it one time, when score is 5, and never again see the second example below.

At the top of your file add something like this:

local scoreStep = 5

local function gameLoop(e) if score == scoreStep then spawnEnemy() scoreStep = scoreStep + 5 end end

second example:

local function gameLoop(e) if score == scoreStep then spawnEnemy() scoreStep = 0 end end

Thank you!! I only have one thing to fix and then its done! I will surely mention you in my credits when my app is done! When i exit the scene to menu the objects do not dissappear and if i re enter the play scene they will crash into my planet and give an error code. My guess is i need to remove all of the enemies before going out of the scene so i tried this.

display.remove(planet) display.remove(enemytable[enemyCnt]) display.remove(scoreTxt)

This is what i have in scene:hide but it doesnt remove the objects from enemies. Do you need more code to know how to do this?