determine which objects collided

Trying to get some basic functionality with a ‘space invaders’ type simulation. I have three questions about my code:

  1. How do I make multiple enemies, and determine which one got hit so the program knows which one to delete? In essence trying to combine the Polylines and Collision Detection tutorials. Make multiple, then when one gets shot, it gets deleted.

  2. In my very simple code, you tap the screen once, it fires a shot, hits the target, and the bullet and target disappear. Then the next shot seems to shoot backwards. It only does this after the target is hit (for example, comment out the target, and it does not do this). The rest of the shots are fine. Why does it do this?

  3. I am normally a PHP/MySQL app developer, games are a new kind of logic to me, and I have about four hours experience with Lua/Corona. Am I working this out correctly? Logically? Code? Any suggestions so far?

[code]
local physics = require( “physics” )
physics.start()
physics.setGravity( 0, 0 )

display.setStatusBar( display.HiddenStatusBar )

local screenW, screenH = display.contentWidth, display.contentHeight

local enemy = {}
enemy[1] = display.newCircle( screenW / 2, screenH * 0.1, 20 )
enemy[1]:setFillColor(0, 255, 0)
physics.addBody( enemy[1], “static”, { density=3.0, friction=0.5, bounce=0.3 } )

local myShip = display.newRect(0,0,40,20)
myShip.x = screenW / 2
myShip.y = screenH - 30
physics.addBody( myShip, “static”, { density=3.0, friction=0.5, bounce=0.3 } )
local tapToShoot = function( event )
if event.phase == “ended” then
print( “Screen tapped, shoot!” )
bullet = display.newCircle( screenW / 2 ,screenH - 30,5)
physics.addBody( bullet, { density=3.0, friction=0.5, bounce=0.05 } )
bullet.isBullet = true
bullet:applyForce( 0, -300, bullet.x, bullet.y )
else
–do nothing
end
return true
end
Runtime:addEventListener( “touch”, tapToShoot )

local function onLocalCollision( self, event )
if ( event.phase == “began” ) then
print( “hit” )
enemy[1]:removeSelf()
bullet:removeSelf()
else
–do nothing
end
end

enemy[1].collision = onLocalCollision
enemy[1]:addEventListener( “collision”, enemy[1] )
[/code] [import]uid: 13726 topic_id: 4942 reply_id: 304942[/import]

this is pretty easy actually ( after I had a little help a while back myself )

In the collision event try using the self and event objects

like self.name or event.other.name

if your expecting to use an array / table this is easy to implement as well.

for each table / array item you create and a ID of the index value like so
enemy[1].id=1; enemy[2].id=2

or in a loop
enemy[x].id=x

this way you can always keep track of the item by the id ( ie index value )

for the collision code you can access this in the following manner

local function onLocalCollision( self, event )  
 if ( event.phase == "began" ) then  
 print( "hit" )  
   
 enemy[self.id]:removeSelf()  
 --bullet:removeSelf() -- not sure on this one but maybe something like  
 local myBullet = event.target;  
 mybullet:removeSelf();  
 else  
 --do nothing   
 end  
end  
  

The above code is not tested and can be prone to errors by me :slight_smile: lol Good luck. [import]uid: 11860 topic_id: 4942 reply_id: 16041[/import]

doubleslash - thank you for your response.

i tried over and over different ways until i did a little troubleshooting. instead of trying to delete various ways of calling the enemies and bullets, i just did a print of what i was trying to call (for example, enemy[self.id] ) - everything printed “nil”. The only thing that printed anything was event.object1. So after borrowing the array of enemies from the Break Out Game, I simplified the ‘delete enemy and bullet’ code. For anyone experiencing the same situation, please see the code below.

BTW - this is 6 hours into trying to code with lua/corona. pretty impressive to me that i can get this far as compared to learning just about any other new syntax/sdk.

[code]
local physics = require( “physics” )
physics.start()
physics.setGravity( 0, 0 )

display.setStatusBar( display.HiddenStatusBar )
gamescreen = display.newGroup()
local screenW, screenH = display.contentWidth, display.contentHeight

enemy = {}
newLevel = function()
– Initial number of enemys (to keep track of when the level is cleared)
enemyCounter = 16

– Set of enemy point values, populated below
enemyValue = {}

– Add all enemys to the screen, looping through rows and columns
for row = 1, 3 do
enemy[row] = {}
enemyValue[row] = {}
for column = 1, 6 do
enemy[row][column] = display.newCircle( 0,0,10 )
gamescreen:insert( enemy[row][column] )
enemy[row][column].x = 20 + (column * 40)
enemy[row][column].y = 50 + (row * 30)

– The point value depends on the row (row 1 = 30, row 2 = 20, row 3 = 10)
enemyValue[row][column] = (4 - row) * 10
enemy[row][column]:setFillColor(0, 255, 0)
physics.addBody( enemy[row][column], “static”, { density=3.0, friction=0.5, bounce=0.3 } )
end
end
end

local myShip = display.newRect(0,0,40,20)
myShip.x = screenW / 2.2
myShip.y = screenH - 30
physics.addBody( myShip, “static”, { density=3.0, friction=0.5, bounce=0.3 } )
myShip.myName = myShip
local tapToShoot = function( event )
if event.phase == “ended” then
print( “Screen tapped, shoot!” )
bullet = display.newCircle( screenW / 2.2 ,screenH - 50,5)
physics.addBody( bullet, { density=3.0, friction=0.5, bounce=0.05 } )
bullet.isBullet = true
bullet:applyForce( 0, -300, bullet.x, bullet.y )
else
–do nothing
end
return true
end
Runtime:addEventListener( “touch”, tapToShoot )

local function onLocalCollision( self, event )
if ( event.phase == “began” ) then
event.object1:removeSelf()
event.object2:removeSelf()
else
–do nothing
end
end

enemy.collision = onLocalCollision
Runtime:addEventListener( “collision”, enemy )

newLevel()
[/code] [import]uid: 13726 topic_id: 4942 reply_id: 16125[/import]

OK, now I have got a moving and shooting “ship”, that will take out the enemies above one by one. Trying to animate the enemies, but I can’t find exactly what I’m looking for in the animation section.

The problem is the functions right() and left() inside the newLevel() function, it animates once, then only the last one animates because it was the last one that was created by the for loop. Makes sense, but how do I move the left and right functions out of the newLevel() function, and still animate them?

Is it possible to call up and animate every object created by that for loop in the enemies{} table?

I’m posting the full code, so if you want to throw it in your simulator you can see what I mean.
Here’s my code:

local physics = require( "physics" )  
physics.start()  
physics.setGravity( 0, 0 )  
  
display.setStatusBar( display.HiddenStatusBar )  
gamescreen = display.newGroup()  
local screenW, screenH = display.contentWidth, display.contentHeight  
  
enemy = {}  
newLevel = function()  
 -- Initial number of enemys (to keep track of when the level is cleared)  
 enemyCounter = 16  
  
 -- Set of enemy point values, populated below  
 enemyValue = {}  
  
 -- Add all enemys to the screen, looping through rows and columns  
 for row = 1, 3 do  
 enemy[row] = {}  
 enemyValue[row] = {}  
 for column = 1, 6 do  
 enemy[row][column] = display.newCircle( 0,0,10 )  
 gamescreen:insert( enemy[row][column] )  
 enemy[row][column].x = -20 + (column \* 40)  
 enemy[row][column].y = 50 + (row \* 30)  
  
 -- The point value depends on the row (row 1 = 30, row 2 = 20, row 3 = 10)  
 enemyValue[row][column] = (4 - row) \* 10  
 enemy[row][column]:setFillColor(0, 255, 0)  
 physics.addBody( enemy[row][column], "kinematic", { density=3.0, friction=0.5, bounce=0.3 } )  
  
 function right()  
 transition.to( enemy[row][column], {time=3000, x=(enemy[row][column].x+80), onComplete=left })  
 end  
 function left()  
 transition.to( enemy[row][column], {time=3000, x=(enemy[row][column].x-80), onComplete=right })  
 end  
  
 right()  
  
 end  
 end  
end  
  
local myShip = display.newRect(0,0,40,20)  
myShip.x = screenW / 2.2  
myShip.y = screenH - 30  
physics.addBody( myShip, "static", { density=3.0, friction=0.5, bounce=0.3 } )  
myShip.myName = myShip  
  
local function startDrag( event )  
 local t = event.target  
   
 local phase = event.phase  
  
 if "began" == phase then  
 display.getCurrentStage():setFocus( t )  
 t.isFocus = true  
   
 -- Store initial position  
 t.x0 = event.x - t.x  
 t.y0 = event.y - t.y  
  
 -- Make body type temporarily "kinematic" (to avoid gravitional forces)  
 event.target.bodyType = "kinematic"  
  
 -- Stop current motion, if any  
 event.target:setLinearVelocity( 0, 0 )  
 event.target.angularVelocity = 0  
   
 elseif t.isFocus then  
 if "moved" == phase then  
 t.x = event.x - t.x0  
 --t.y = event.y - t.y0  
   
 elseif "ended" == phase or "cancelled" == phase then  
 display.getCurrentStage():setFocus( nil )  
 t.isFocus = false  
  
 -- Switch body type back to "dynamic", unless we've marked this sprite as a platform  
 if ( not event.target.isPlatform ) then  
 event.target.bodyType = "kinematic"  
 end  
   
 end  
 end  
   
 -- Stop further propagation of touch event!  
 return true  
end  
  
myShip:addEventListener( "touch", startDrag )  
  
local tapToShoot = function( event )  
 if event.phase == "ended" then  
 print( "Screen tapped, shoot!" )  
 bullet = display.newCircle(myShip.x, myShip.y - 30, 5)   
 physics.addBody( bullet, { density=3.0, friction=0.5, bounce=0.05 } )  
 bullet.isBullet = true  
 bullet:applyForce( 0, -300, bullet.x, bullet.y )   
 else   
 --do nothing  
 end  
 return true  
end  
Runtime:addEventListener( "touch", tapToShoot )  
   
local function onLocalCollision( self, event )  
 if ( event.phase == "began" ) then  
 event.object1:removeSelf()  
 event.object2:removeSelf()  
 else  
 --do nothing   
 end  
end  
  
enemy.collision = onLocalCollision  
Runtime:addEventListener( "collision", enemy )  
  
newLevel()  

Thanks!
Josh [import]uid: 13726 topic_id: 4942 reply_id: 16138[/import]