Targeting reticle with fire button functionality

Hi folks,

I’m new to Corona and Lua and I’m setting up a pretty simple ‘shooter’ game where a series of objects (actually flying zombie heads) travel across the screen and need to be ‘shot’ by moving a targeting reticle on top of them and pressing the fire button.

Most things are working and the game is almost playable but I’m stuck on getting the collision between the targeting reticle and the zombie head to actually register and play the ‘death’ function (which is obviously pretty key).

The targeting reticle works in that it can be moved by dragging the finger anywhere on the screen, and the fire button works in that it plays the animation of the gun firing, so I feel like I’m close and just can’t quite tie it all together.

Anyway, here’s some snippets of what I have:

[code]–Set Gun
local spriteSheet = sprite.newSpriteSheet(“pistol.png”, 256, 256)
local pistolSet = sprite.newSpriteSet(spriteSheet, 1, 8)

sprite.add(pistolSet, “shoot”, 1, 8, 200, 1)

local pistol = sprite.newSprite(pistolSet)
pistol.x = 440; pistol.y = 225

displayReticle:insert(pistol)

–Fire button
fireBtn = display.newImage( “fire.png” )
fireBtn.x = 50
fireBtn.y = 270

displayGUI:insert(fireBtn)

function fireBtn:tap( event )
pistol:prepare(“shoot”)
pistol:play(“shoot”)
if event.phase == “began” then --Here I’m trying to create a boolean for the fireBtn state to call later when checking to see if the button is presssed
fireBtnDown = true
elseif event.phase == “ended” then
fireBtnDown = false
end
end

fireBtn:addEventListener( “tap”, fireBtn)

–Targeting Reticle
reticle = display.newImage( “Reticle.png” )
physics.addBody( reticle, { isSensor = true } )
reticle.bodyType = “kinematic”
reticle.isAwake = true;
reticle.name = “reticle”

displayReticle:insert(reticle)

–function makes it so that the reticle is moved around the screen by dragging a finger anywhere on the background
local function onTouch( event )
if “began” == event.phase then
reticle.isFocus = true

reticle.x0 = event.x - reticle.x
reticle.y0 = event.y - reticle.y
elseif reticle.isFocus then
if “moved” == event.phase then
reticle.x = event.x - reticle.x0
reticle.y = event.y - reticle.y0
–coerceOnScreen( reticle )
elseif “ended” == phase or “cancelled” == phase then
reticle.isFocus = false
end
end

return true
end

– Only the background receives touches.
background:addEventListener( “touch”, onTouch)

–This below function doesn’t seem to do anything, but I was strying to get it to check if both the target was over the head and the button was pressed
function fireCheck( event )
if ( event.phase == “began” ) then
if fireBtnDown == true then
killHead()
end
end
end

reticle.collision = fireCheck
reticle:addEventListener( “collison”, fireCheck )

–Destroy Head Function
function killHead( event )
zombie1:removeSelf()
display.newImage(“Zombie01dead.png”, zombie1.x - 50, zombie1.y - 50)
end

–Create head as physics object
function randomZombieHead()
zombie1 = display.newImage( “Zombie01.png”)
zombie1.x = math.random (30, 450); zombie1.y = 350
zombie1.myName = “Zombie Head”
displayHeads:insert(zombie1)

physics.addBody( zombie1, { density = 1.0, friction = 0.3, bounce = 0.2, radius = 25 } )
– Apply random force to zombie heads
zombie1:applyForce( math.random (-250, 250), math.random (-900, -800), zombie1.x, zombie1.y )

end[/code]

Sorry for the super noob code guys but I figured the best way to learn (after doing a few tutorials) is to try and get my own thing going.

I know that I have another issue where I need to call the random zombie heads into a table so that they can each register a hit if more than one are on the screen at the same time, but I’ll be happy if I can figure out how to make one ‘killed’ properly at this point.

Thanks! [import]uid: 36682 topic_id: 27604 reply_id: 327604[/import]

You’d likely compare the reticle x and y with the zombie head x and y then kill if they were the within X pixels of each other.

If you can figure that with one zombie head you can then use a for loop to check the coords when you have multiple heads in a table.

I notice your current set up is done to use the reticle as a sensor, try switching it to static body type then using a print statement to ensure collision event is firing. (Assuming you wish to continue using the physics approach rather than coord check - which is perfectly acceptable as well.)

Peach :slight_smile: [import]uid: 52491 topic_id: 27604 reply_id: 112166[/import]

Hi Peach,

Thanks for that! Actually, it’s fuunny that you mention the co-ordinate check system because that’s exactly what I initially planned to do but then using a physics sensor seemed easier once I got going (which obviously wasn’t the case since I still can’t get it working :).

I’ll definitely try what you suggest.

Queston though:

What syntax would I use to compare if the two were close to each other within a certain number of pixels? I know == and ~= but is there an equivalent where a range can be established?

Thanks again!

–Glenn [import]uid: 36682 topic_id: 27604 reply_id: 112170[/import]

Hey again Glenn - this is really basic but try running it. (Plug and play, iPhone in mind.)

[lua]–reticle
local reticle = display.newCircle(160, 240, 25)
reticle.alpha=0.5

–drag reticle around
local function moveRet(event)
reticle.x, reticle.y = event.x, event.y
end
reticle:addEventListener(“touch”, moveRet)

–zombie
local zombie = display.newRect( 100, 20, 40, 40 )

–check coords
local function checkCoords(event)
zx, zy = zombie.x, zombie.y
rx, ry = reticle.x, reticle.y
if zx < rx+20 and zx > rx-20 then
if zy < ry+20 and zy > ry-20 then
print “in range”
else
print “Out of range”
end
end
end
Runtime:addEventListener(“enterFrame”, checkCoords)[/lua]

Let me know how that goes :slight_smile: [import]uid: 52491 topic_id: 27604 reply_id: 112262[/import]

Wow, Peach, thanks!! That bit of code definitely clears things up and will come in handy for sure.

I actually ended up solving the problem in a slightly different way (I knew I was close and it was driving me insane so I had to pursue the current path to success or death haha).

Anyway, in case it can help anyone else, here’s what I did:

function onCollision( event )  
 if ( event.phase == "began" ) then  
 isCollision = true;  
 currentHead = event.object2; -- this was the key, adding a currentHead variable  
 elseif ( event.phase == "ended" ) then  
 isCollision = false;  
 end  
end  

And then changed the ‘death’ function to

function killHead()  
 currentHead:removeSelf()  
 zombie1Dead = display.newImage("Zombie01dead.png", currentHead.x - 50, currentHead.y - 50)  
 isCollision = false  
  
end  

Then I call isCollison from the fireBtn function which was tweaked slightly to this:

function fireBtn:tap( event )  
 pistol:prepare("shoot")  
 pistol:play("shoot")  
 if (isCollision) then  
 killHead();  
 end  
end  
  
fireBtn:addEventListener( "tap", fireBtn)  

And it works! :slight_smile:

I can’t take full credit for this solution. A (non-Lua) programmer friend helped me pinpoint where I was probably going wrong with the logic and it’s one of those situations where it’s obvious once it slaps you in the forehead.

Thanks for your help though, Peach! Your co-ordinate compare system solves another problem I hadn’t even asked yet so you’re ahead of the game :slight_smile:

–Glenn [import]uid: 36682 topic_id: 27604 reply_id: 112430[/import]

Hey Glenn,

Thanks so much for posting your solution, it is always great when devs do that as it really helps others out.

You’re welcome RE my code, I hope it does help you or others even if not with your original problem. (It’s good you are using your own code, even with a friends help, you get that feeling of “Yay me!” ;))

Peach :slight_smile: [import]uid: 52491 topic_id: 27604 reply_id: 112479[/import]