Proper traveling Positions of Bullet

Hi. I got this code from the documentation, then i tried to make it rectangular.

		local physics = require("physics")
		physics.setDrawMode("hybrid")
		physics.start()

		local bullet = display.newRect( 0, display.contentCenterY, 100, 20)
		physics.addBody( bullet, "dynamic" )
		bullet.gravityScale = 0

		-- Make the object a "bullet" type object
		bullet.isBullet = true

		bullet:setLinearVelocity( 800, 0 )

I understand that I may repeatedly produce this through timer.performWithDelay, or “enterframe” listener, or through transition.to instead of Linear Velocity, particle system, ray casting and etc.

As a training and practice for me as a rookie, I will make a shooting object. But I don’t know how to start because of thinking-when the gun aims to shoot vertically, the bullet may travel in horizontal position, and more bad is when the gun randomly shoot slantingly.

How can I make the rectangular objects travels correspondingly to it’s rotation position, or travel accordingly where it’s rotation is pointing?

Please, I really need help from you. And a sample code or project will be indeed an elevation for me, its really a BIG help. thank you so much.

This comes down to trigonometry. You use the sine and cosine functions to get the vertical and horizontal components of the angle. For example, a measurement of one unit at a 30 degree angle corresponds to moving .866 units on the x-axis and .5 units on the y-axis. These are the figures that the cosine and sine functions will give you. If you multiply them by the distance you want to move, it will give you horizontal and vertical distances required to make that move in the given direction. Hope I’m not explaining it too badly. Anyway, maybe these examples will help:

-- with an enterFrame listener
local bullet = display.newRect(display.contentCenterX, display.contentCenterY, 20, 10)
bullet.rotation = math.random(0, 360)
local rotationInRadians = bullet.rotation*math.pi/180
local movementPerFrame = 1
local xMovement = math.cos(rotationInRadians)*movementPerFrame
local yMovement = math.sin(rotationInRadians)*movementPerFrame

local function update()
	bullet.x = bullet.x + xMovement
	bullet.y = bullet.y + yMovement
end

Runtime:addEventListener("enterFrame", update)





-- with transition.to
local bullet = display.newRect(display.contentCenterX, display.contentCenterY, 20, 10)
bullet.rotation = math.random(0, 360)
local rotationInRadians = bullet.rotation*math.pi/180
local travelDist = 200
local xDist = math.cos(rotationInRadians)*travelDist
local yDist = math.sin(rotationInRadians)*travelDist
local xDestination, yDestination = bullet.x + xDist, bullet.y + yDist
transition.to(bullet, {x = xDestination, y = yDestination, time = 2000})

You could do it with timer.performWithDelay also, but… I wouldn’t.

1 Like

This is very helpful. Thank you very much, hasty.

Hello! :slightly_smiling_face:
I hope this code helps you in some way! Maybe you can take something Good from it. It is a gun which shoots in the direction of a tap on the screen! Both the gun and bullet rotate in the direction of the tap/target. And bullet is sent in the direction of the tap.

local math = math
local physics = require("physics")

local background, gun
local bullets = {}

local function shootGun(event)

	local bullet = display.newRect( 0, display.contentCenterY, 100, 20)
	bullet.width, bullet.height = gun.width*0.2, gun.height*0.2
	bullet.x, bullet.y = gun.x, gun.y
    bullet:setFillColor(1, 0, 0)
    gun:toFront()
	
	physics.addBody( bullet, "dynamic" )
	bullet.gravityScale = 0

	-- Make the object a "bullet" type object
	bullet.isBullet = true
	
	local direction = {}
	direction.x = event.x - gun.x
	direction.y = event.y - gun.y
	
	local axis = {}
	axis.x = 0
	axis.y = direction.y
	
	local directionLength = math.sqrt(direction.x*direction.x + direction.y*direction.y)
	local axisLength = math.sqrt(axis.y*axis.y)
	
	local cosA = axisLength/directionLength
	local angleInRad = math.acos(cosA)
	local angleInDegrees = math.deg(angleInRad)
	
	local finalAngle = 0
	
	if direction.y <= 0 then
		finalAngle = angleInDegrees
	else
		finalAngle = 90 + (90 - angleInDegrees)
	end
	
	if direction.x < 0 then finalAngle = -finalAngle end
	
	gun.rotation, bullet.rotation = finalAngle, finalAngle
	
	bullet:setLinearVelocity( direction.x, direction.y )

end

physics.start()

background = display.newRect( display.contentCenterX, display.contentCenterY, display.actualContentWidth, display.actualContentHeight)

gun = display.newRect( 0, display.contentCenterY, 20, 100)
gun:setFillColor(0, 0, 0)

Runtime:addEventListener("tap", shootGun)

1 Like

Hi again guys, thank you very much for your help.

I have innovated hasty’s code a very little bit.

	local function Berserk ()
		local bullet = display.newRect(display.contentCenterX, display.contentCenterY, 40, 20)
		bullet.rotation = math.random(0, 360)
		local rotationInRadians = bullet.rotation*math.pi/180
		local travelDist = display.screenOriginY
		local xDist = math.cos(rotationInRadians)*travelDist
		local yDist = math.sin(rotationInRadians)*travelDist
		local xDestination, yDestination = bullet.x + xDist, bullet.y + yDist
		transition.to(bullet, {x = xDestination, y = yDestination, time = 200, onComplete = function() display.remove(bullet) end})
	end

	timer.performWithDelay(250, Berserk, 0)

I have notice a problem that when the app crashes, the timer.performWithDelay() will still execute it’s function, which result in many many more bullets.

this can be intentionally done when you hold down the minimize button or the close button.


I’m now thinking that maybe firing repeated bullets is much better using the enterFrame listener.

can I have an example of shooting bullets in enterFrame listener? please. Or how can the timer.performWithDelay() also solve this problem if possible? I really need help from you, thank you very much.

I don’t know why it behaves this way when you hold the minimize or close buttons. I did a windows build and saw what you were talking about. I have no idea what the cause of this is. I would suggest starting a new thread about it if no-one chimes in here in the next few days.

By the way, travelDist is the distance for the bullet to travel. If you set it to display.screenOriginY you will get varying results, depending on device. On some devices it’s 0, so the bullets won’t move at all!

2 Likes