Firing a bullet from my turret, and how to make the bullet ricochet

I currently have a tank with a turret, attached via physics joint, and I am trying to figure out how to fire a bullet in the direction my turret is pointing…
My goal is to fire a bullet at the beginning of the touch event ( when the user ‘taps’ the screen) and at the ‘end’ of the touch event.
*Very similar to the TinyTanks game.

Q1. How do I fire a bullet from the tip of my turret’s ‘cannon’ in whatever direction the turret is currently facing?

Q2. How do I code the bullet to ricochet off walls, preferably only once, canceling on the second collision…?

My turret is controlled by the user either touching &or dragging their finger within the display, and my thought was that I could using the ‘angle between’ portion of the code (kudos to Brent Sorrentino ) to calculate the direction the bullet should fire, but I have been experimenting all day trying to find the answer and have had little success.
This is the code I am using to ‘aim’ my turret: [lua]

–adds a rect to act as a base for touch events relating to the turret
local transRect = display.newRect(0,0, 1024, 768)
transRect.isVisible = false
transRect.isHitTestable = true

local math_deg = math.deg --localize ‘math.deg’ for better performance
local math_atan2 = math.atan2 --localize ‘math.atan2’ for better performance

–likewise, this function should reside outside and above the touch function
local function angleBetween( user_turretX, user_turretY, eventX, eventY )
local angle = ( math_deg( math_atan2( eventY-user_turretY, eventX-user_turretX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

local function touchRect( event )

local ang = angleBetween( user_turret.x, user_turret.y, event.x, event.y )
user_turret.rotation = ang --rotate turret on ALL touch/drag conditions
local e = event.phase
if e.phase == “began” or e.phase == “moved” then
print( “BEGAN/MOVED phase touch” )
elseif e.phase == “ended” then
print( “FIRE a bullet now!” )

end

end

transRect:addEventListener( “touch”, touchRect )[/lua]

P.S. Is there a way for me to delete my old forum posts?

Thanks in advance for any replies. :slight_smile:

-Saer [import]uid: 148623 topic_id: 32510 reply_id: 332510[/import]

Hi Saer,
It’s me again. ;).
I guess what you’re asking is, how to get the linear velocity for the bullet, knowing the rotation of the turret? Well, you just need to use the “difference” between your tank and touch coordinates (same as those sent to the angleBetween function) and apply the inverse force to your bullet. The force must be capped at a certain maximum value, but I address this and the entire method here:

https://developer.coronalabs.com/forum/2012/09/24/how-set-maximum-force-applied-object

For the starting point of the bullet, it’s tedious and unnecessary to calculate the “tip location” of the cannon. Is the turret in a separate display layer? If so, put the bullet in the same layer but use the “object:toBack()” call to place it behind the turret. Then just start it at the same central location of the tank… the player won’t notice any difference.

As for a ricochet, you can sense how many times any object has collided with something by just adding a counter to it. When the bullet fires, the counter is 0. On first collision, it goes up to 1. On second collision, it equals 1 and is thus destroyed on impact.

Brent [import]uid: 9747 topic_id: 32510 reply_id: 129311[/import]

Have a look at -

http://developer.coronalabs.com/code/asteroids

You can use the code in their to shoot your missile the same way as the gun is pointing.

To ricochet your missile, do as Brent says above about keeping a count and also add physics walls to the sides of your game, so the missile bounces off.

Take a look at the pool or air hockey demo games.

Dave [import]uid: 117617 topic_id: 32510 reply_id: 129315[/import]

Hi Saer,
It’s me again. ;).
I guess what you’re asking is, how to get the linear velocity for the bullet, knowing the rotation of the turret? Well, you just need to use the “difference” between your tank and touch coordinates (same as those sent to the angleBetween function) and apply the inverse force to your bullet. The force must be capped at a certain maximum value, but I address this and the entire method here:

https://developer.coronalabs.com/forum/2012/09/24/how-set-maximum-force-applied-object

For the starting point of the bullet, it’s tedious and unnecessary to calculate the “tip location” of the cannon. Is the turret in a separate display layer? If so, put the bullet in the same layer but use the “object:toBack()” call to place it behind the turret. Then just start it at the same central location of the tank… the player won’t notice any difference.

As for a ricochet, you can sense how many times any object has collided with something by just adding a counter to it. When the bullet fires, the counter is 0. On first collision, it goes up to 1. On second collision, it equals 1 and is thus destroyed on impact.

Brent [import]uid: 9747 topic_id: 32510 reply_id: 129311[/import]

Have a look at -

http://developer.coronalabs.com/code/asteroids

You can use the code in their to shoot your missile the same way as the gun is pointing.

To ricochet your missile, do as Brent says above about keeping a count and also add physics walls to the sides of your game, so the missile bounces off.

Take a look at the pool or air hockey demo games.

Dave [import]uid: 117617 topic_id: 32510 reply_id: 129315[/import]

@Brent - lol thanks for replying! : D

I understand what you’re saying about how to get the ricochet and I kind of understand how the block of code you suggested puts a max value on the objects’ force, but I’m having trouble wrapping my head around how to format the rest…

I create new bullet:
[lua] local function firePbullet()
Pbullet = display.newImageRect(“gameImages/Bullets/bullet.png”, 30, 30);
Pbullet.x = user_tank.x; Pbullet.y = user_tank.y;
physics.addBody(bullet, “kinematic”, {bounce = 0});

Pbullet.isBullet = true

Pbullet:setLinearVelocity( xVelocity, yVelocity ) [/lua]
beyond this, I’m stuck…
I tried a bunch of different things… I added some transition.to lines, added the angleBetween bit with a few other things I tried, but I couldn’t get it to work.
Any recommended resources for learning the math behind all this? I understand the math, just not how to ‘code’ it… if that makes sense.
P.S. Thanks for the suggestion Dave; I’ll give it a try.

-Saer
[import]uid: 148623 topic_id: 32510 reply_id: 129406[/import]

@Brent - lol thanks for replying! : D

I understand what you’re saying about how to get the ricochet and I kind of understand how the block of code you suggested puts a max value on the objects’ force, but I’m having trouble wrapping my head around how to format the rest…

I create new bullet:
[lua] local function firePbullet()
Pbullet = display.newImageRect(“gameImages/Bullets/bullet.png”, 30, 30);
Pbullet.x = user_tank.x; Pbullet.y = user_tank.y;
physics.addBody(bullet, “kinematic”, {bounce = 0});

Pbullet.isBullet = true

Pbullet:setLinearVelocity( xVelocity, yVelocity ) [/lua]
beyond this, I’m stuck…
I tried a bunch of different things… I added some transition.to lines, added the angleBetween bit with a few other things I tried, but I couldn’t get it to work.
Any recommended resources for learning the math behind all this? I understand the math, just not how to ‘code’ it… if that makes sense.
P.S. Thanks for the suggestion Dave; I’ll give it a try.

-Saer
[import]uid: 148623 topic_id: 32510 reply_id: 129406[/import]

@Dave - I tried doing what you said, but it didn’t work. :\
I wasn’t getting any errors, but nothing was appearing on my screen…? I had the mathlib and everything, but still couldn’t get it to work.

-Saer [import]uid: 148623 topic_id: 32510 reply_id: 130257[/import]

@Dave - I tried doing what you said, but it didn’t work. :\
I wasn’t getting any errors, but nothing was appearing on my screen…? I had the mathlib and everything, but still couldn’t get it to work.

-Saer [import]uid: 148623 topic_id: 32510 reply_id: 130257[/import]

It took me a while to get it working in my game but sorted it in the end. If you have a iOS device check out “Ball Barrage Lite” in the app store and you will see I use the code to get the balls firing out of the gun.

Dave [import]uid: 117617 topic_id: 32510 reply_id: 130274[/import]

It took me a while to get it working in my game but sorted it in the end. If you have a iOS device check out “Ball Barrage Lite” in the app store and you will see I use the code to get the balls firing out of the gun.

Dave [import]uid: 117617 topic_id: 32510 reply_id: 130274[/import]

Well I’ve spent all day trying to get it to work and I’ve alomst got it!:smiley:

This is what I have so far:
[lua]–adds a rect to act as a base for touch events relating to the Ptank
local transRect = display.newRect(0,0, 1024, 768)
transRect.isVisible = false
transRect.isHitTestable = true

local math_deg = math.deg --localize ‘math.deg’ for better performance
local math_atan2 = math.atan2 --localize ‘math.atan2’ for better performance

local function angleBetween( user_tankX, user_tankY, eventX, eventY )
local angle = ( math_deg( math_atan2( eventY-user_tankY, eventX-user_tankX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

function transRect:touch( event )

local ang = angleBetween( user_tank.x, user_tank.y, event.x, event.y )
user_turret.rotation = ang --rotate turret on ALL touch/drag conditions
local e = event.phase

if e.phase == “began” or e.phase == “moved” then
print( “BEGAN/MOVED phase touch” )

elseif e.phase == “ended” then

print( “FIRE a bullet now!” )
shootBullet()

end

end

Runtime:addEventListener( “touch”, user_tank )
transRect:addEventListener( “touch”, transRect )

–===============================================================================================

function shootBullet()
local pt = mathapi.rotateAboutPoint( {x=user_turret.x,y=user_turret.y-60}, user_turret, user_turret.rotation )
local bullet = display.newCircle( pt.x, pt.y, 7 )
physics.addBody( bullet, “dynamic”, { friction=0, bounce=0, density=1, radius=7 } )
bullet.class = “bullet”
bullet.isBullet = true
Ptank:insert( bullet )
bullet:toBack()

bullet:applyForce( pt.x - user_turret.x, pt.y - user_turret.y, user_turret.x, user_turret.y )
– bullet:addEventListener( “collision”, isShot )

– function bullet:doRemove()
– timer.performWithDelay( 1, 1 )
–end
end

function user_tank:touch( event )
if (event.phase == “began”) then

elseif (event.phase == “moved”) then
print(" moved")

elseif (event.phase == “ended”) then
shootBullet()
end
end[/lua]

For some reason when I go and delete the function [lua] user_tank:touch( event ) [/lua] it won’t fire a bullet…? I don’t get any errors, but it no longer fires, even with the call to the " shootBullet() " function on line #28.
Also, when I do fire it, the tank acts as though there is major recoil. I think it’s 'cause the bullet is spawning within the tank and is hitting it, causing it to jerk…?

-Saer [import]uid: 148623 topic_id: 32510 reply_id: 130591[/import]

Well I’ve spent all day trying to get it to work and I’ve alomst got it!:smiley:

This is what I have so far:
[lua]–adds a rect to act as a base for touch events relating to the Ptank
local transRect = display.newRect(0,0, 1024, 768)
transRect.isVisible = false
transRect.isHitTestable = true

local math_deg = math.deg --localize ‘math.deg’ for better performance
local math_atan2 = math.atan2 --localize ‘math.atan2’ for better performance

local function angleBetween( user_tankX, user_tankY, eventX, eventY )
local angle = ( math_deg( math_atan2( eventY-user_tankY, eventX-user_tankX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

function transRect:touch( event )

local ang = angleBetween( user_tank.x, user_tank.y, event.x, event.y )
user_turret.rotation = ang --rotate turret on ALL touch/drag conditions
local e = event.phase

if e.phase == “began” or e.phase == “moved” then
print( “BEGAN/MOVED phase touch” )

elseif e.phase == “ended” then

print( “FIRE a bullet now!” )
shootBullet()

end

end

Runtime:addEventListener( “touch”, user_tank )
transRect:addEventListener( “touch”, transRect )

–===============================================================================================

function shootBullet()
local pt = mathapi.rotateAboutPoint( {x=user_turret.x,y=user_turret.y-60}, user_turret, user_turret.rotation )
local bullet = display.newCircle( pt.x, pt.y, 7 )
physics.addBody( bullet, “dynamic”, { friction=0, bounce=0, density=1, radius=7 } )
bullet.class = “bullet”
bullet.isBullet = true
Ptank:insert( bullet )
bullet:toBack()

bullet:applyForce( pt.x - user_turret.x, pt.y - user_turret.y, user_turret.x, user_turret.y )
– bullet:addEventListener( “collision”, isShot )

– function bullet:doRemove()
– timer.performWithDelay( 1, 1 )
–end
end

function user_tank:touch( event )
if (event.phase == “began”) then

elseif (event.phase == “moved”) then
print(" moved")

elseif (event.phase == “ended”) then
shootBullet()
end
end[/lua]

For some reason when I go and delete the function [lua] user_tank:touch( event ) [/lua] it won’t fire a bullet…? I don’t get any errors, but it no longer fires, even with the call to the " shootBullet() " function on line #28.
Also, when I do fire it, the tank acts as though there is major recoil. I think it’s 'cause the bullet is spawning within the tank and is hitting it, causing it to jerk…?

-Saer [import]uid: 148623 topic_id: 32510 reply_id: 130591[/import]

I got it!:smiley:
Solved the “jerking” problem by making the tank-base a kinematic physics body.

One last question - based on the code below, how do I change the velocity and other various bullet attributes?
[lua]–adds a rect to act as a base for touch events relating to the Ptank
local transRect = display.newRect(0,0, 1024, 768)
transRect.isVisible = false
transRect.isHitTestable = true

local math_deg = math.deg --localize ‘math.deg’ for better performance
local math_atan2 = math.atan2 --localize ‘math.atan2’ for better performance

–This function should reside outside and above the touch function
local function angleBetween( user_tankX, user_tankY, eventX, eventY )
local angle = ( math_deg( math_atan2( eventY-user_tankY, eventX-user_tankX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

function transRect:touch( event )

local ang = angleBetween( user_tank.x, user_tank.y, event.x, event.y )
user_turret.rotation = ang --rotate turret on ALL touch/drag conditions
local e = event.phase

if (event.phase == “began”) then

elseif (event.phase == “moved”) then
print(" moved")

elseif (event.phase == “ended”) then
shootBullet()
end
end
Runtime:addEventListener( “touch”, transRect ) [/lua]

This is the code I use to fire a bullet:

[lua]function shootBullet()
local pt = mathapi.rotateAboutPoint( {x=user_turret.x,y=user_turret.y-60}, user_turret, user_turret.rotation )
local bullet = display.newCircle( pt.x, pt.y, 7 )
physics.addBody( bullet, “dynamic”, { friction=0, bounce=0, density=1, radius=7 } )
bullet.class = “bullet”
bullet.isBullet = true
Ptank:insert( bullet )
bullet:toBack()

bullet:applyForce( pt.x - user_turret.x, pt.y - user_turret.y, user_turret.x, user_turret.y )
– bullet:addEventListener( “collision”, isShot )

–function bullet:doRemove()
– timer.performWithDelay( 1, 1 )
– end
end[/lua]

Thanks guys for your help!:smiley:

-Saer [import]uid: 148623 topic_id: 32510 reply_id: 130636[/import]

I got it!:smiley:
Solved the “jerking” problem by making the tank-base a kinematic physics body.

One last question - based on the code below, how do I change the velocity and other various bullet attributes?
[lua]–adds a rect to act as a base for touch events relating to the Ptank
local transRect = display.newRect(0,0, 1024, 768)
transRect.isVisible = false
transRect.isHitTestable = true

local math_deg = math.deg --localize ‘math.deg’ for better performance
local math_atan2 = math.atan2 --localize ‘math.atan2’ for better performance

–This function should reside outside and above the touch function
local function angleBetween( user_tankX, user_tankY, eventX, eventY )
local angle = ( math_deg( math_atan2( eventY-user_tankY, eventX-user_tankX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

function transRect:touch( event )

local ang = angleBetween( user_tank.x, user_tank.y, event.x, event.y )
user_turret.rotation = ang --rotate turret on ALL touch/drag conditions
local e = event.phase

if (event.phase == “began”) then

elseif (event.phase == “moved”) then
print(" moved")

elseif (event.phase == “ended”) then
shootBullet()
end
end
Runtime:addEventListener( “touch”, transRect ) [/lua]

This is the code I use to fire a bullet:

[lua]function shootBullet()
local pt = mathapi.rotateAboutPoint( {x=user_turret.x,y=user_turret.y-60}, user_turret, user_turret.rotation )
local bullet = display.newCircle( pt.x, pt.y, 7 )
physics.addBody( bullet, “dynamic”, { friction=0, bounce=0, density=1, radius=7 } )
bullet.class = “bullet”
bullet.isBullet = true
Ptank:insert( bullet )
bullet:toBack()

bullet:applyForce( pt.x - user_turret.x, pt.y - user_turret.y, user_turret.x, user_turret.y )
– bullet:addEventListener( “collision”, isShot )

–function bullet:doRemove()
– timer.performWithDelay( 1, 1 )
– end
end[/lua]

Thanks guys for your help!:smiley:

-Saer [import]uid: 148623 topic_id: 32510 reply_id: 130636[/import]

Try playing around with the addBody values (mostly density) and also have a look at -

http://docs.coronalabs.com/api/library/physics/setPositionIterations.html

It’s a matter of playing with the numbers till it feels right for your game.

Dave [import]uid: 117617 topic_id: 32510 reply_id: 130675[/import]

Try playing around with the addBody values (mostly density) and also have a look at -

http://docs.coronalabs.com/api/library/physics/setPositionIterations.html

It’s a matter of playing with the numbers till it feels right for your game.

Dave [import]uid: 117617 topic_id: 32510 reply_id: 130675[/import]

Thanks.
Care to help me again? :slight_smile:

I just hit several ‘snags’ -

  1. I am using an image for my bullet and when I fire it the ‘bullet’ comes out of the turret facing whatever direction the original image is pointing.

  2. I currently have collision detection off so my bullets just bounce around my screen (I’m doing this to get the settings for the bullet the way I want them) and my problem is that whenever one of them ‘hits’ my turret, it starts spinning? I tried to fix this by making the turret a kinematic body, but when I do the tank-base won’t move and I get an error about my pivot joint having to be attached to at least several physics objects…

-Saer [import]uid: 148623 topic_id: 32510 reply_id: 130887[/import]

Thanks.
Care to help me again? :slight_smile:

I just hit several ‘snags’ -

  1. I am using an image for my bullet and when I fire it the ‘bullet’ comes out of the turret facing whatever direction the original image is pointing.

  2. I currently have collision detection off so my bullets just bounce around my screen (I’m doing this to get the settings for the bullet the way I want them) and my problem is that whenever one of them ‘hits’ my turret, it starts spinning? I tried to fix this by making the turret a kinematic body, but when I do the tank-base won’t move and I get an error about my pivot joint having to be attached to at least several physics objects…

-Saer [import]uid: 148623 topic_id: 32510 reply_id: 130887[/import]

You can setup filters, so that only certain object will colide with other objects.

http://developer.coronalabs.com/forum/2010/10/25/collision-filters-helper-chart

Dave

[import]uid: 117617 topic_id: 32510 reply_id: 131100[/import]