bullets not removing on collision

I have a ship, it fires 4 bullets.
The bullets hit an enemy sprite, the enemy sprite is destroyed, an explosion sprite is played and then removed.

My issue is that the bullets still remain on screen and continue to react with other enemies.
What I need help with is I need the bullets to remove themselves once the enemy is hit.

I thought it was simple but its to be; I have some code below:

local bulletGroup = display.newGroup()  
local update = {}  
local fireButton = display.newCircle(410,260,24)  
fireButton:setFillColor (0,0,0,50)  
  
function fireButton:touch(event)  
  
 if event.phase == "began" then  
 display.getCurrentStage():setFocus( self ,event.id )  
  
 local bullet = display.newImage('images/bullet.png')  
 bullet.x = ship.x -10  
 bullet.y = ship.y -10  
 bullet.name = 'bullet'  
 physics.addBody(bullet)  
 bulletGroup:insert (bullet)  
  
 local bullet2 = display.newImage('images/bullet.png')  
 bullet2.x = ship.x -20  
 bullet2.y = ship.y -20  
 bullet2.name = 'bullet'  
 physics.addBody(bullet2)  
 bulletGroup:insert(bullet2)  
  
 local bullet3 = display.newImage('images/bullet.png')  
 bullet3.x = ship.x +20  
 bullet3.y = ship.y -20  
 bullet3.name = 'bullet'  
 physics.addBody(bullet3)  
 bulletGroup:insert(bullet3)  
  
 local bullet4 = display.newImage('images/bullet.png')  
 bullet4.x = ship.x +10  
 bullet4.y = ship.y -12  
 bullet4.name = 'bullet'  
 physics.addBody(bullet4)  
 bulletGroup:insert(bullet4)  
  
 bulletGroup:addEventListener("collision", bulletGroup)  
  
 elseif event.phase == "cancelled" or event.phase == "ended" then  
  
 display.getCurrentStage():setFocus( self ,nil )  
 end  
end  
  
fireButton:addEventListener('touch',fireButton)  
  
function update(event)  
  
 for i = bulletGroup.numChildren,1,-1 do  
 local weapon = bulletGroup[i]  
 if weapon ~= nil and weapon.y ~= nil then  
 weapon:translate(0, -10);  
  
 end  
 end  
  
end  
Runtime:addEventListener('enterFrame', update)  
  

I wrote a simple collision function that would hopefully remove the group on collision but it just didnt work, infact I spent a fair while messing around with it.
I probably shouldnt be putting the bullets in the fire button function either.
I am also using a modular approach to this project.
Any help would be great.

[import]uid: 127675 topic_id: 32321 reply_id: 332321[/import]

@bubblebobble,

I modified your code a bit, but the essence of the changes are:

  1. Used a table of tables to create bullets with offsets (easy to add more now).
  2. Added collision function to individual bullets.
  3. Gave four sample snippets you can use to remove the bullet or bullets
   
function fireButton:touch(event)  
   
 if event.phase == "began" then  
 display.getCurrentStage():setFocus( self ,event.id )  
  
 local bulletOffsets = { {-10,-10}, {-20,-20}, {20,-20}, {10,-12} }  
  
 for i = 1, #bulletOffset do  
  
 local offset = #bulletOffset[i]  
   
 local bullet = display.newImage('images/bullet.png')  
 bullet.x = ship.x + offset[1]  
 bullet.y = ship.y + offset[2]  
 bullet.name = 'bullet'  
 physics.addBody(bullet)  
 bulletGroup:insert (bullet)  
  
 bullet.collision = function( self, event )  
 local target = event.target -- The bullet  
 local other = event.other -- Object bullet just hit  
  
 -- Note: self is also the bullet in this case, but I'll use target in the sample  
 -- code below.  
  
 --[[ In here, do whatever you want, but there should be two parts:  
  
 1. Code operating on 'other' - Do something to the object you hit.  
 2. Code operating on 'target' - Delete the bullet (as you said you want to)  
  
 -- Remove the bullet from bulletGroup  
 bulletGroup:remove(target)   
  
 --Alternate #1, Remove the bullet itself w/ removeSelf()  
 bullet:removeSelf()  
  
 -- Alternate #2, if you want to remove all of the bullets, you could do this:  
 -- Not really suggested as creating groups is not cheap  
 bulletGroup:removeSelf()   
 bulletGroup = display.newGroup()  
  
 -- Alternately #3, if you want to remove all of the bullets, you could do this:  
 while bulletGroup.numChildren \> 0 do  
 bulletGroup:remove(1)  
 end  
  
 --]]  
  
 end  
  
 bullet:addEventListener("collision", bullet)  
  
 elseif event.phase == "cancelled" or event.phase == "ended" then  
  
 display.getCurrentStage():setFocus( self ,nil )  
  
 end  
end  
   
fireButton:addEventListener('touch',fireButton)  
  • Ed [import]uid: 110228 topic_id: 32321 reply_id: 128645[/import]

@Ed,

thankyou very much for taking the time to review my code, also the explanations are just what I like, it helps me understand the code.

Ed, I have a problem though,
I noticed an error in in

local bulletOffsets = { {-10,-10}, {-20,-20}, {20,-20}, {10,-12} }  

I removed the “s”.
I am afraid I cant get it to work, I can see the spawned bullet at x=1,y=1, I keep getting an error relating to the

bullet.x = ship.x + offset[1]  

attempt to index local ‘offset’ a numerical value.

Is this something to do with the table? It is I think not getting the offset values and applying them in relation to the ship.

Thanks [import]uid: 127675 topic_id: 32321 reply_id: 128748[/import]

@bubblebobble,

I modified your code a bit, but the essence of the changes are:

  1. Used a table of tables to create bullets with offsets (easy to add more now).
  2. Added collision function to individual bullets.
  3. Gave four sample snippets you can use to remove the bullet or bullets
   
function fireButton:touch(event)  
   
 if event.phase == "began" then  
 display.getCurrentStage():setFocus( self ,event.id )  
  
 local bulletOffsets = { {-10,-10}, {-20,-20}, {20,-20}, {10,-12} }  
  
 for i = 1, #bulletOffset do  
  
 local offset = #bulletOffset[i]  
   
 local bullet = display.newImage('images/bullet.png')  
 bullet.x = ship.x + offset[1]  
 bullet.y = ship.y + offset[2]  
 bullet.name = 'bullet'  
 physics.addBody(bullet)  
 bulletGroup:insert (bullet)  
  
 bullet.collision = function( self, event )  
 local target = event.target -- The bullet  
 local other = event.other -- Object bullet just hit  
  
 -- Note: self is also the bullet in this case, but I'll use target in the sample  
 -- code below.  
  
 --[[ In here, do whatever you want, but there should be two parts:  
  
 1. Code operating on 'other' - Do something to the object you hit.  
 2. Code operating on 'target' - Delete the bullet (as you said you want to)  
  
 -- Remove the bullet from bulletGroup  
 bulletGroup:remove(target)   
  
 --Alternate #1, Remove the bullet itself w/ removeSelf()  
 bullet:removeSelf()  
  
 -- Alternate #2, if you want to remove all of the bullets, you could do this:  
 -- Not really suggested as creating groups is not cheap  
 bulletGroup:removeSelf()   
 bulletGroup = display.newGroup()  
  
 -- Alternately #3, if you want to remove all of the bullets, you could do this:  
 while bulletGroup.numChildren \> 0 do  
 bulletGroup:remove(1)  
 end  
  
 --]]  
  
 end  
  
 bullet:addEventListener("collision", bullet)  
  
 elseif event.phase == "cancelled" or event.phase == "ended" then  
  
 display.getCurrentStage():setFocus( self ,nil )  
  
 end  
end  
   
fireButton:addEventListener('touch',fireButton)  
  • Ed [import]uid: 110228 topic_id: 32321 reply_id: 128645[/import]

@bubblebobble,

Hi. I forgot to mention that there could be typos. I normally run my example code before giving it out, but I typed up the entire batch untested this time. :frowning:

That said, I think you can find any problems in the offset code by changing the top of the code to look like this (see lines/sections with my initials EFM):

 local bulletOffsets = { {-10,-10}, {-20,-20}, {20,-20}, {10,-12} } --EFM  
 for i = 1, #bulletOffsets do -- EFM  
 local offset = bulletOffsets[i] -- EFM  
  
 if(offset) then -- EFM verify the offset is picked up  
 print("Current offset ", i, offset, offset[1], offset[2])   
 else  
 print("Offset is nil: ", i )  
 end  
  
 if(ship) then -- EFM verify the offset is picked up  
 print("Ship position ", ship.x, ship.y)   
 else  
 print("No ship? Is the ship handle in scope?" )  
 end  
   
 local bullet = display.newImage('images/bullet.png')  
  
 if(not bullet) then EFM  
 print("Bullet not created?")  
 end  

I think what may be happening is either a problem with the code that gets the offset or your ship handle is not in scope (not visible to the code trying to access it).
[import]uid: 110228 topic_id: 32321 reply_id: 128759[/import]

@bubblebobble,

Hi again. I see the problem now.

Originally, I wrote something like this:

 local offset = #bulletOffsets[i] --EFM (always returns 2, i.e. 2 elements in subtable)  

It should have been like this:

 local offset = bulletOffsets[i] --EFM (returns the sub-table like it should)  

[import]uid: 110228 topic_id: 32321 reply_id: 128760[/import]

@Ed,

thankyou very much for taking the time to review my code, also the explanations are just what I like, it helps me understand the code.

Ed, I have a problem though,
I noticed an error in in

local bulletOffsets = { {-10,-10}, {-20,-20}, {20,-20}, {10,-12} }  

I removed the “s”.
I am afraid I cant get it to work, I can see the spawned bullet at x=1,y=1, I keep getting an error relating to the

bullet.x = ship.x + offset[1]  

attempt to index local ‘offset’ a numerical value.

Is this something to do with the table? It is I think not getting the offset values and applying them in relation to the ship.

Thanks [import]uid: 127675 topic_id: 32321 reply_id: 128748[/import]

@bubblebobble,

Hi. I forgot to mention that there could be typos. I normally run my example code before giving it out, but I typed up the entire batch untested this time. :frowning:

That said, I think you can find any problems in the offset code by changing the top of the code to look like this (see lines/sections with my initials EFM):

 local bulletOffsets = { {-10,-10}, {-20,-20}, {20,-20}, {10,-12} } --EFM  
 for i = 1, #bulletOffsets do -- EFM  
 local offset = bulletOffsets[i] -- EFM  
  
 if(offset) then -- EFM verify the offset is picked up  
 print("Current offset ", i, offset, offset[1], offset[2])   
 else  
 print("Offset is nil: ", i )  
 end  
  
 if(ship) then -- EFM verify the offset is picked up  
 print("Ship position ", ship.x, ship.y)   
 else  
 print("No ship? Is the ship handle in scope?" )  
 end  
   
 local bullet = display.newImage('images/bullet.png')  
  
 if(not bullet) then EFM  
 print("Bullet not created?")  
 end  

I think what may be happening is either a problem with the code that gets the offset or your ship handle is not in scope (not visible to the code trying to access it).
[import]uid: 110228 topic_id: 32321 reply_id: 128759[/import]

@bubblebobble,

Hi again. I see the problem now.

Originally, I wrote something like this:

 local offset = #bulletOffsets[i] --EFM (always returns 2, i.e. 2 elements in subtable)  

It should have been like this:

 local offset = bulletOffsets[i] --EFM (returns the sub-table like it should)  

[import]uid: 110228 topic_id: 32321 reply_id: 128760[/import]