HELP! problem with spawn multiple object, action takes effect only on the last enemy spawned

Hello everyone, I’m using corona SDK even as a beginner , and to date I have not had any problems … but now I need help to continue my little project. I have enemies that spawn from one point of the screen and every few second code creates another identical enemy, but these enemies have a health bar which decreases when touched … well, and here lies the problem , because if you build a new enemy suffers the damage only the last … I know it is a problem related to the tables , but I just can not understand how I can fix this… help please.

if it can be useful I can also give the code. Also I apologize for any grammatical errors … this is not my language :slight_smile:

Hello everyone, I’m using coronaa even as a beginner , and to date I have not had any problems … but now I need help to continue. I have enemies that spawn from one point of the screen and every few scondi code creates an identical , these enemies but they have a health bar which decreases when touched … well, and here lies the problem , because if you build a new enemy suffers the damage only the last … I know it is a problem related to the tables , but I just can not understand how I can fix … help please

We will need to see your code to verify the problem, but I’ve seen this a lot in the forums lately where you don’t retain a reference to the spawned object and anything you do only happens to the last one.

Consider:

local badGuy local function hitBadGuy( event )      if event.phase == "ended" then           badGuy.health = badGuy.health - 1      end      return true end local function spawnBadGuy()       badGuy = display.newImageRect( ... )       badGuy.health = 10       badGuy:addEventListener( "touch" , hitBadGuy ) end timer.performWithDelay( 3000, spawnBadGuy, 10) -- create 10 badGuys

The variable “badGuy” will only know about the last one created. There are a couple of solutions. One, use event.target in the touch handler:

local function hitBadGuy( event ) if event.phase == "ended" then event.target.health = event.target.health - 1 end return true end

Or keep track of all of the badGuys by using a table.

local badGuy = {} -- make it a table/array local function hitBadGuy( event ) if event.phase == "ended" then event.target.health = event.target.health - 1 end return true end local function spawnBadGuy() badGuy[#badGuy + 1] = display.newImageRect( ... ) badGuy[#badGuy].health = 10 badGuy[#badGuy]:addEventListener( "touch" , hitBadGuy ) end timer.performWithDelay( 3000, spawnBadGuy, 10) -- create 10 badGuys

Now with them in a table, you can still reference each one later. For instance you might want to every second give them a health point back. Now you can with another timer running every second calling a function that would loop over the badGuy table and increase their health:

local function restoreHealth() &nbsp;&nbsp;&nbsp;&nbsp; for i = 1, #badGuy do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if badGuy[i].health \< 10 then &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; badGuy[i].health = badGuy[i].health + 1 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp; end end timer.performWithDelay( 1000, restoreHealth, 1)

By keeping that reference to each object handy it’s easier to do something with them later.

Rob

hello and thanks for the quick reply , however, I am attaching the code so you understand where I’m wrong

local spawnTimer local spawnedObjects = {} local spawnParams = { xMin = 1455, xMax = 1455, yMin = 220, yMax = 230, spawnTime = 5000, spawnOnTimer = 0.1, spawnInitial = 0 } local function nemico1spawn(bounds) local baseline = 280 golemnemici = display.newGroup() golemnemici.x = math.random( bounds.xMin, bounds.xMax ) golemnemici.y = math.random( bounds.yMin, bounds.yMax ) scroll:insert(golemnemici) local nemico = graphics.newImageSheet( "img/livello/mostro1.png", { width=350, height=350, numFrames=57 } ) local sequenceData = { { name="mostrocammina", start=46, count=11, time=600 }, { name="mostrocorre", start=46, count=11, time=600 }, { name="mostromuore", start=46, count=11, time=600 }, { name="mostroattacca", start=1, count=16, time=1200 } } local instance3 = display.newSprite( nemico, sequenceData ) instance3:setSequence("mostrocammina") instance3.xScale = .3--ridimenziona il personaggio instance3.yScale = .3 instance3:play()-- esegue l'animazione golemnemici:insert(instance3) maxHealth = 50 currentHealth = 50 -- create green health bar barravita = display.newRoundedRect(0, -30, maxHealth ,10,5) barravita:setFillColor( 000/255, 255/255, 0/255 ) barravita.strokeWidth = 1 barravita:setStrokeColor( 255, 255, 255, .5 ) golemnemici:insert(barravita) damageBar = display.newRoundedRect(0,-30 , 0 ,10,0) damageBar:setFillColor( 255/255, 0/255, 0/255 ) golemnemici:insert(damageBar) -- update the damage bar function updateDamageBar() damageBar.x = currentHealth / 2 damageBar.width = maxHealth - currentHealth end -- lower the character's currentHealth function damageCharacter(damageTaken) currentHealth = currentHealth - damageTaken updateDamageBar() end --- funzione tocca il danno piri local function dannotocco(event) if(event.target.currentHealth \> 0) then event.target.damageCharacter(5) end end golemnemici:addEventListener("touch",dannotocco) local function attacco () instance3:setSequence("mostroattacca") instance3:play() end -- add item to spawnedObjects table for tracking purposes spawnedObjects[#spawnedObjects+1] = golemnemici transition.to( golemnemici, {x=80, time = 16000,onComplete = attacco} ) end local function spawnController( action, params ) -- cancel timer on "start" or "stop", if it exists if ( spawnTimer and ( action == "start" or action == "stop" ) ) then timer.cancel( spawnTimer ) end -- Start spawning if ( action == "start" ) then -- gather/set spawning bounds local spawnBounds = {} spawnBounds.xMin = params.xMin or 0 spawnBounds.xMax = params.xMax or display.contentWidth spawnBounds.yMin = params.yMin or 0 spawnBounds.yMax = params.yMax or display.contentHeight -- gather/set other spawning params local spawnTime = params.spawnTime local spawnOnTimer = params.spawnOnTimer or 50 local spawnInitial = params.spawnInitial -- if spawnInitial \> 0, spawn n item(s) instantly if ( spawnInitial \> 0 ) then for n = 1,spawnInitial do nemico1spawn( spawnBounds ) end end -- start repeating timer to spawn items if ( spawnOnTimer \> 0 ) then spawnTimer = timer.performWithDelay( spawnTime, function() nemico1spawn( spawnBounds ); end, spawnOnTimer ) end -- Pause spawning elseif ( action == "pause" ) then timer.pause( spawnTimer ) -- Resume spawning elseif ( action == "resume" ) then timer.resume( spawnTimer ) end end spawnController( "start", spawnParams )

We will need to see your code to verify the problem, but I’ve seen this a lot in the forums lately where you don’t retain a reference to the spawned object and anything you do only happens to the last one.

Consider:

local badGuy local function hitBadGuy( event ) &nbsp;&nbsp;&nbsp;&nbsp; if event.phase == "ended" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; badGuy.health = badGuy.health - 1 &nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp; return true end local function spawnBadGuy() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; badGuy = display.newImageRect( ... ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; badGuy.health = 10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; badGuy:addEventListener( "touch" , hitBadGuy ) end timer.performWithDelay( 3000, spawnBadGuy, 10) -- create 10 badGuys

The variable “badGuy” will only know about the last one created. There are a couple of solutions. One, use event.target in the touch handler:

local function hitBadGuy( event ) if event.phase == "ended" then event.target.health = event.target.health - 1 end return true end

Or keep track of all of the badGuys by using a table.

local badGuy = {} -- make it a table/array local function hitBadGuy( event ) if event.phase == "ended" then event.target.health = event.target.health - 1 end return true end local function spawnBadGuy() badGuy[#badGuy + 1] = display.newImageRect( ... ) badGuy[#badGuy].health = 10 badGuy[#badGuy]:addEventListener( "touch" , hitBadGuy ) end timer.performWithDelay( 3000, spawnBadGuy, 10) -- create 10 badGuys

Now with them in a table, you can still reference each one later. For instance you might want to every second give them a health point back. Now you can with another timer running every second calling a function that would loop over the badGuy table and increase their health:

local function restoreHealth() &nbsp;&nbsp;&nbsp;&nbsp; for i = 1, #badGuy do &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if badGuy[i].health \< 10 then &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; badGuy[i].health = badGuy[i].health + 1 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp; end end timer.performWithDelay( 1000, restoreHealth, 1)

By keeping that reference to each object handy it’s easier to do something with them later.

Rob

hello and thanks for the quick reply , however, I am attaching the code so you understand where I’m wrong

local spawnTimer local spawnedObjects = {} local spawnParams = { xMin = 1455, xMax = 1455, yMin = 220, yMax = 230, spawnTime = 5000, spawnOnTimer = 0.1, spawnInitial = 0 } local function nemico1spawn(bounds) local baseline = 280 golemnemici = display.newGroup() golemnemici.x = math.random( bounds.xMin, bounds.xMax ) golemnemici.y = math.random( bounds.yMin, bounds.yMax ) scroll:insert(golemnemici) local nemico = graphics.newImageSheet( "img/livello/mostro1.png", { width=350, height=350, numFrames=57 } ) local sequenceData = { { name="mostrocammina", start=46, count=11, time=600 }, { name="mostrocorre", start=46, count=11, time=600 }, { name="mostromuore", start=46, count=11, time=600 }, { name="mostroattacca", start=1, count=16, time=1200 } } local instance3 = display.newSprite( nemico, sequenceData ) instance3:setSequence("mostrocammina") instance3.xScale = .3--ridimenziona il personaggio instance3.yScale = .3 instance3:play()-- esegue l'animazione golemnemici:insert(instance3) maxHealth = 50 currentHealth = 50 -- create green health bar barravita = display.newRoundedRect(0, -30, maxHealth ,10,5) barravita:setFillColor( 000/255, 255/255, 0/255 ) barravita.strokeWidth = 1 barravita:setStrokeColor( 255, 255, 255, .5 ) golemnemici:insert(barravita) damageBar = display.newRoundedRect(0,-30 , 0 ,10,0) damageBar:setFillColor( 255/255, 0/255, 0/255 ) golemnemici:insert(damageBar) -- update the damage bar function updateDamageBar() damageBar.x = currentHealth / 2 damageBar.width = maxHealth - currentHealth end -- lower the character's currentHealth function damageCharacter(damageTaken) currentHealth = currentHealth - damageTaken updateDamageBar() end --- funzione tocca il danno piri local function dannotocco(event) if(event.target.currentHealth \> 0) then event.target.damageCharacter(5) end end golemnemici:addEventListener("touch",dannotocco) local function attacco () instance3:setSequence("mostroattacca") instance3:play() end -- add item to spawnedObjects table for tracking purposes spawnedObjects[#spawnedObjects+1] = golemnemici transition.to( golemnemici, {x=80, time = 16000,onComplete = attacco} ) end local function spawnController( action, params ) -- cancel timer on "start" or "stop", if it exists if ( spawnTimer and ( action == "start" or action == "stop" ) ) then timer.cancel( spawnTimer ) end -- Start spawning if ( action == "start" ) then -- gather/set spawning bounds local spawnBounds = {} spawnBounds.xMin = params.xMin or 0 spawnBounds.xMax = params.xMax or display.contentWidth spawnBounds.yMin = params.yMin or 0 spawnBounds.yMax = params.yMax or display.contentHeight -- gather/set other spawning params local spawnTime = params.spawnTime local spawnOnTimer = params.spawnOnTimer or 50 local spawnInitial = params.spawnInitial -- if spawnInitial \> 0, spawn n item(s) instantly if ( spawnInitial \> 0 ) then for n = 1,spawnInitial do nemico1spawn( spawnBounds ) end end -- start repeating timer to spawn items if ( spawnOnTimer \> 0 ) then spawnTimer = timer.performWithDelay( spawnTime, function() nemico1spawn( spawnBounds ); end, spawnOnTimer ) end -- Pause spawning elseif ( action == "pause" ) then timer.pause( spawnTimer ) -- Resume spawning elseif ( action == "resume" ) then timer.resume( spawnTimer ) end end spawnController( "start", spawnParams )