Fire bullet from rotating object

Hi,

I have an issue and hope you can help.

If we think “asteroids” of which there is a good example in the code share forum.
Now I have an object which will orientate itself to the users touch, no probs.
I have bullets which will spawn and move from objects x.y. position, no probs.

The issue I have is I need the bullets to fire in the direction at which the touch event ended.

I have used a code snippet from code exchange for the rotation.

I figure I have to pass the ended co-ords from the rotation function to the bullet function ?
Or could I use the ended touch event co- ord?

here is some simplified code, plug and play, no need to worry about bullet spawn etc, just need the bullet to orientate its self to object “ended” position.

Thanks for the advice

local physics = require('physics')  
physics.start()  
physics.setGravity(0, 0)  
--physics.setDrawMode( "hybrid")  
  
local ship = display.newRect( 50, 50, 50, 50 )  
ship.x = 200  
ship.y = 200  
local transRect = display.newRect(0,0, 1024, 768)  
transRect.isVisible = false  
transRect.isHitTestable = true  
ship:setReferencePoint(display.CenterReferencePoint)  
   
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( srcX, srcY, dstX, dstY )  
 local angle = ( math\_deg( math\_atan2( dstY-srcY, dstX-srcX ) )+90 ) --; return angle  
 if ( angle \< 0 ) then angle = angle + 360 end ; return angle % 360  
end  
   
   
 local function touchRect ( event )  
  
 local ang = angleBetween( ship.x, ship.y, event.x, event.y )  
 ship.rotation = ang   
  
 if event.phase == "began" or event.phase == "moved" then  
 print ("BEGAN/MOVED " )  
 elseif event.phase == "ended" then   
 bullet()  
  
 end   
end  
  
function bullet()  
local bullet = display.newRect( 10, 10, 10, 80 )  
bullet:setFillColor (255,0,0)  
 bullet.x = ship.x -10  
 bullet.y = ship.y -10  
 bullet.name = 'bullet'  
 physics.addBody(bullet)  
  
end   
  
transRect:addEventListener( "touch", touchRect )   

[import]uid: 127675 topic_id: 32966 reply_id: 332966[/import]

The bullet’s rotation value will need to be the same as the angle between the starting location and target location. Take a look at my asteroids code sample:

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

While I don’t actually rotate the bullets in that code, it would not be difficult to take the angle between the ship and the tap location and apply it to the bullet display object. [import]uid: 8271 topic_id: 32966 reply_id: 130912[/import]

@HB,

I looked at the asteroids code yesterday but while I can see it working I was unable to implement the nessacary actions.

Suppose Iam looking at moving the bullets in the direction the ship has rotated and toward the touch event.
I tried using angleBetween in the bullet function but alas I am still unable to link the rotation with the direction of fire.

Is there an example of linking the ship “ended” phase to the bullet direction of fire?
Driving me nuts!
[import]uid: 127675 topic_id: 32966 reply_id: 130917[/import]

If you like you can send me your code and I’ll take a look, but the pseudo-code would be:

Get position of ship
Get position of touch point (on the event.phase == “ended”)
Call “angleOf” passing in the ship and touch positions
Set bullet.rotation = angle

If you’re not doing that I would say you are over thinking it and maybe need to go back to basics. Maybe try getting that working in a very simple proof of concept first. [import]uid: 8271 topic_id: 32966 reply_id: 130932[/import]

The bullet’s rotation value will need to be the same as the angle between the starting location and target location. Take a look at my asteroids code sample:

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

While I don’t actually rotate the bullets in that code, it would not be difficult to take the angle between the ship and the tap location and apply it to the bullet display object. [import]uid: 8271 topic_id: 32966 reply_id: 130912[/import]

@HB,

I looked at the asteroids code yesterday but while I can see it working I was unable to implement the nessacary actions.

Suppose Iam looking at moving the bullets in the direction the ship has rotated and toward the touch event.
I tried using angleBetween in the bullet function but alas I am still unable to link the rotation with the direction of fire.

Is there an example of linking the ship “ended” phase to the bullet direction of fire?
Driving me nuts!
[import]uid: 127675 topic_id: 32966 reply_id: 130917[/import]

If you like you can send me your code and I’ll take a look, but the pseudo-code would be:

Get position of ship
Get position of touch point (on the event.phase == “ended”)
Call “angleOf” passing in the ship and touch positions
Set bullet.rotation = angle

If you’re not doing that I would say you are over thinking it and maybe need to go back to basics. Maybe try getting that working in a very simple proof of concept first. [import]uid: 8271 topic_id: 32966 reply_id: 130932[/import]

@Hb,
ok, so I have done as suggested.

I was intially moving the bullet mathmatically, but some one suggested just using applyForce as there would be alot of complex math to achieve my goal.
Ok, so I have taken from the touch function ship and touch references ( i think) and made them accessable by the bullet function.

Problem is the bullet is now reading the “object,ship” orientation and firing the bullet at the same angle.
All I need to do is get the bullet to exit the front of the ship on touch ended whichever way it points, sounds simple I guess.
I need I think to tell the applyForce to pick up the orientation?
here is the updated code.

[code]
local physics = require(‘physics’)
physics.start()
physics.setGravity(0, 0)
–physics.setDrawMode( “hybrid”)

local ship = display.newRect( 50, 50, 20, 100 )
ship.x = 200
ship.y = 200
local transRect = display.newRect(0,0, 1024, 768)
transRect.isVisible = false
transRect.isHitTestable = true
ship:setReferencePoint(display.CenterReferencePoint)

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( srcX, srcY, dstX, dstY )
local angle = ( math_deg( math_atan2( dstY-srcY, dstX-srcX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

local function touchRect ( event )

local ang = angleBetween( ship.x, ship.y, event.x, event.y )
ship.rotation = ang

if event.phase == “began” or event.phase == “moved” then
print ("BEGAN/MOVED " )
elseif event.phase == “ended” then
bullet(ship,event)

end
end

function bullet(ship, target)

local bullet = display.newImage(‘images/bullet.png’)
local ang = angleBetween( ship.x, ship.y, target.x, target.y )
bullet.rotation = ang
bullet.x = ship.x
bullet.y = ship.y

bullet.name = ‘bullet’
physics.addBody(bullet)

bullet:applyForce( 100, 100, bullet.x, bullet.y )

end

transRect:addEventListener( “touch”, touchRect )
[/code] [import]uid: 127675 topic_id: 32966 reply_id: 131041[/import]

I could not get your code to work by just changing it, so I wrote it from scratch. I hope this tells you what you want to know:

main.lua:
[lua]local physics = require(‘physics’)
physics.start()
physics.setGravity(0, 0)
physics.setDrawMode( “hybrid”)
–[[Math Lib: http://developer.coronalabs.com/code/maths-library]]–

– returns the degrees between (0,0) and pt
– note: 0 degrees is ‘east’
function angleOfPoint( pt )
local x, y = pt.x, pt.y
local radian = math.atan2(y,x)
–print('radian: '…radian)
local angle = radian*180/math.pi
–print('angle: '…angle)
if angle < 0 then angle = 360 + angle end
–print('final angle: '…angle)
return angle
end

– returns the degrees between two points
– note: 0 degrees is ‘east’
function angleBetweenPoints( a, b )
local x, y = b.x - a.x, b.y - a.y
return angleOfPoint( { x=x, y=y } )
end

– rotates a point around the (0,0) point by degrees
– returns new point object
function rotateTo( point, degrees )
local x, y = point.x, point.y

local theta = math.rad(degrees)

local pt = {
x = x * math.cos(theta) - y * math.sin(theta),
y = x * math.sin(theta) + y * math.cos(theta)
}

return pt
end

–[[-------------------------------------]]–

function fireBullet(source, angle)
local bullet = display.newRect( 0,0 , 10,2 )
bullet.x, bullet.y, bullet.rotation = source.x, source.y, angle
physics.addBody( bullet )

local direction = rotateTo( {x=10,y=0}, angle )
bullet:applyForce( direction.x, direction.y, bullet.x, bullet.y ) – you might want to shorten the direction values
end

local ship = display.newRect( 50, 50, 20, 100 )
ship.x, ship.y = 200, 200

function touch( e )
local angle = angleBetweenPoints( ship, e )
ship.rotation = angle-90 – because .rotation is not ‘east’
print(‘angle’, angle)

if (e.phase == “began”) then
elseif (e.phase == “moved”) then
else
fireBullet(ship, angle)
end
return true
end
Runtime:addEventListener(“touch”,touch)[/lua] [import]uid: 8271 topic_id: 32966 reply_id: 131052[/import]

@HB,

well what can I say but thank you for your input.
I am not sure how the physics libraries are working but I can see what their outputs are.
Because I can see that, it is so much easier to relate it to the functions calling the maths functions.

The way the “angle” is passed from the “touch.event” and “ship” to the “bullet” makes sense.
Nice, clean and self explaining code, again, thanks, your an asset to Corona.
You would belong in the “essential assets” folder if they had one :slight_smile:

"3 cheers for HB, he rocks 1 "
[import]uid: 127675 topic_id: 32966 reply_id: 131067[/import]

@Hb,
ok, so I have done as suggested.

I was intially moving the bullet mathmatically, but some one suggested just using applyForce as there would be alot of complex math to achieve my goal.
Ok, so I have taken from the touch function ship and touch references ( i think) and made them accessable by the bullet function.

Problem is the bullet is now reading the “object,ship” orientation and firing the bullet at the same angle.
All I need to do is get the bullet to exit the front of the ship on touch ended whichever way it points, sounds simple I guess.
I need I think to tell the applyForce to pick up the orientation?
here is the updated code.

[code]
local physics = require(‘physics’)
physics.start()
physics.setGravity(0, 0)
–physics.setDrawMode( “hybrid”)

local ship = display.newRect( 50, 50, 20, 100 )
ship.x = 200
ship.y = 200
local transRect = display.newRect(0,0, 1024, 768)
transRect.isVisible = false
transRect.isHitTestable = true
ship:setReferencePoint(display.CenterReferencePoint)

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( srcX, srcY, dstX, dstY )
local angle = ( math_deg( math_atan2( dstY-srcY, dstX-srcX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

local function touchRect ( event )

local ang = angleBetween( ship.x, ship.y, event.x, event.y )
ship.rotation = ang

if event.phase == “began” or event.phase == “moved” then
print ("BEGAN/MOVED " )
elseif event.phase == “ended” then
bullet(ship,event)

end
end

function bullet(ship, target)

local bullet = display.newImage(‘images/bullet.png’)
local ang = angleBetween( ship.x, ship.y, target.x, target.y )
bullet.rotation = ang
bullet.x = ship.x
bullet.y = ship.y

bullet.name = ‘bullet’
physics.addBody(bullet)

bullet:applyForce( 100, 100, bullet.x, bullet.y )

end

transRect:addEventListener( “touch”, touchRect )
[/code] [import]uid: 127675 topic_id: 32966 reply_id: 131041[/import]

I could not get your code to work by just changing it, so I wrote it from scratch. I hope this tells you what you want to know:

main.lua:
[lua]local physics = require(‘physics’)
physics.start()
physics.setGravity(0, 0)
physics.setDrawMode( “hybrid”)
–[[Math Lib: http://developer.coronalabs.com/code/maths-library]]–

– returns the degrees between (0,0) and pt
– note: 0 degrees is ‘east’
function angleOfPoint( pt )
local x, y = pt.x, pt.y
local radian = math.atan2(y,x)
–print('radian: '…radian)
local angle = radian*180/math.pi
–print('angle: '…angle)
if angle < 0 then angle = 360 + angle end
–print('final angle: '…angle)
return angle
end

– returns the degrees between two points
– note: 0 degrees is ‘east’
function angleBetweenPoints( a, b )
local x, y = b.x - a.x, b.y - a.y
return angleOfPoint( { x=x, y=y } )
end

– rotates a point around the (0,0) point by degrees
– returns new point object
function rotateTo( point, degrees )
local x, y = point.x, point.y

local theta = math.rad(degrees)

local pt = {
x = x * math.cos(theta) - y * math.sin(theta),
y = x * math.sin(theta) + y * math.cos(theta)
}

return pt
end

–[[-------------------------------------]]–

function fireBullet(source, angle)
local bullet = display.newRect( 0,0 , 10,2 )
bullet.x, bullet.y, bullet.rotation = source.x, source.y, angle
physics.addBody( bullet )

local direction = rotateTo( {x=10,y=0}, angle )
bullet:applyForce( direction.x, direction.y, bullet.x, bullet.y ) – you might want to shorten the direction values
end

local ship = display.newRect( 50, 50, 20, 100 )
ship.x, ship.y = 200, 200

function touch( e )
local angle = angleBetweenPoints( ship, e )
ship.rotation = angle-90 – because .rotation is not ‘east’
print(‘angle’, angle)

if (e.phase == “began”) then
elseif (e.phase == “moved”) then
else
fireBullet(ship, angle)
end
return true
end
Runtime:addEventListener(“touch”,touch)[/lua] [import]uid: 8271 topic_id: 32966 reply_id: 131052[/import]

@HB,

well what can I say but thank you for your input.
I am not sure how the physics libraries are working but I can see what their outputs are.
Because I can see that, it is so much easier to relate it to the functions calling the maths functions.

The way the “angle” is passed from the “touch.event” and “ship” to the “bullet” makes sense.
Nice, clean and self explaining code, again, thanks, your an asset to Corona.
You would belong in the “essential assets” folder if they had one :slight_smile:

"3 cheers for HB, he rocks 1 "
[import]uid: 127675 topic_id: 32966 reply_id: 131067[/import]

At some point between the time Horace posted his code and now, the formatting got lost.

For people who are looking for this kind of help, a reformatted version is here:

local physics = require('physics') physics.start() physics.setGravity(0, 0) physics.setDrawMode( "normal") --[[Math Lib: http://developer.coronalabs.com/code/maths-library]]-- -- returns the degrees between (0,0) and pt -- note: 0 degrees is 'east' function angleOfPoint( pt ) local x, y = pt.x, pt.y local radian = math.atan2(y,x) --print('radian: '..radian) local angle = radian\*180/math.pi --print('angle: '..angle) if angle \< 0 then angle = 360 + angle end --print('final angle: '..angle) return angle end -- returns the degrees between two points -- note: 0 degrees is 'east' function angleBetweenPoints( a, b ) local x, y = b.x - a.x, b.y - a.y return angleOfPoint( { x=x, y=y } ) end -- rotates a point around the (0,0) point by degrees -- returns new point object function rotateTo( point, degrees ) local x, y = point.x, point.y local theta = math.rad(degrees) local pt = { x = x \* math.cos(theta) - y \* math.sin(theta), y = x \* math.sin(theta) + y \* math.cos(theta) } return pt end --[[-------------------------------------]]-- function fireBullet(source, angle) local bullet = display.newRect( 0,0 , 10,2 ) bullet.x, bullet.y, bullet.rotation = source.x, source.y, angle physics.addBody( bullet ) local direction = rotateTo( {x=10,y=0}, angle ) bullet:applyForce( direction.x, direction.y, bullet.x, bullet.y ) -- you might want to shorten the direction values end local ship = display.newRect( 50, 50, 20, 100 ) ship.x, ship.y = 200, 200 function touch( e ) local angle = angleBetweenPoints( ship, e ) ship.rotation = angle-90 -- because .rotation is not 'east' print('angle', angle) if (e.phase == "began") then elseif (e.phase == "moved") then else fireBullet(ship, angle) end return true end Runtime:addEventListener("touch",touch)

At some point between the time Horace posted his code and now, the formatting got lost.

For people who are looking for this kind of help, a reformatted version is here:

local physics = require('physics') physics.start() physics.setGravity(0, 0) physics.setDrawMode( "normal") --[[Math Lib: http://developer.coronalabs.com/code/maths-library]]-- -- returns the degrees between (0,0) and pt -- note: 0 degrees is 'east' function angleOfPoint( pt ) local x, y = pt.x, pt.y local radian = math.atan2(y,x) --print('radian: '..radian) local angle = radian\*180/math.pi --print('angle: '..angle) if angle \< 0 then angle = 360 + angle end --print('final angle: '..angle) return angle end -- returns the degrees between two points -- note: 0 degrees is 'east' function angleBetweenPoints( a, b ) local x, y = b.x - a.x, b.y - a.y return angleOfPoint( { x=x, y=y } ) end -- rotates a point around the (0,0) point by degrees -- returns new point object function rotateTo( point, degrees ) local x, y = point.x, point.y local theta = math.rad(degrees) local pt = { x = x \* math.cos(theta) - y \* math.sin(theta), y = x \* math.sin(theta) + y \* math.cos(theta) } return pt end --[[-------------------------------------]]-- function fireBullet(source, angle) local bullet = display.newRect( 0,0 , 10,2 ) bullet.x, bullet.y, bullet.rotation = source.x, source.y, angle physics.addBody( bullet ) local direction = rotateTo( {x=10,y=0}, angle ) bullet:applyForce( direction.x, direction.y, bullet.x, bullet.y ) -- you might want to shorten the direction values end local ship = display.newRect( 50, 50, 20, 100 ) ship.x, ship.y = 200, 200 function touch( e ) local angle = angleBetweenPoints( ship, e ) ship.rotation = angle-90 -- because .rotation is not 'east' print('angle', angle) if (e.phase == "began") then elseif (e.phase == "moved") then else fireBullet(ship, angle) end return true end Runtime:addEventListener("touch",touch)