Shooting arrow

Hi, im making a game where you can shot arrows horizontally.

I’m using physics to detect the collition between the arrow and the target. 

I want to make it so wherever you touch, the arrow goes to that point and continues flying until some time when it gets deleted, but im having some problems doing that.

This is what i got:

local arrow = {} local function shoot\_arrow(event) if event.phase == "began" then for i = 1,1 do arrow[i] = display.newImage("arrow.jpg") arrow[i].x = 0; arrow[i].y = 150 physics.addBody(arrow[i],"static",{ friction=0, bounce=0 } ) if event.y \>= 220 then arrow[i]:rotate(15) end if event.y \<= 140 then arrow[i]:rotate(-15) end transition.to(arrow[i],{x=event.x, y=event.y}) end end background:addEventListener("touch",shoot\_arrow)

The problem here is: 

  1. transition.to asigns a default time and if i touch the screen near the spawn area, it goes really slow until that point, and if i press it far from it, its speed is really fast. I tried other ways to replace transition or make the time dynamic but i couldn’t do it.

  2. The arrow goes to event.x and event.y but stops there, tried with some onComplete functions but I couldn’t do it either.

Im not able to achieve this, can i get some help?

Thanks in advance!

If you already use physics, why don’t you do that for the shooting as well?

You could use object:applyForce, object:setLinearVelocity or object:apply linear impulse to do so.

Hi, thanks for the answer.

I just wanted to use physics for the collisions, thats why i’m using static mode on the arrows. 

Those properties like applyForce only work for dynamic if im not wrong, and I dont really know how to make it “natural” like a linear arrow movement, that way.

Ok, forget the physics. I’ll move it using transition.to, but i need some basic mathematical help. Here is what i have:

local function shoot\_arrow(event) if event.phase == "began" then local speed = event.x\*2.5 for i = 1,1 do arrow[i] = display.newImage("arrow.jpg") arrow[i].x = 55; arrow[i].y = 155 transition.to(arrow[i],{time=speed,x=event.x, y=event.y}) end end end background:addEventListener("touch",shoot\_arrow)

But i’m trying to move the arrow outside the view,but using event.x and event.y so the arrow follows the path wherever the player touched the background. 

you need to use <math.atan> to get the angle and then use< math.sin> and< math.cos> and multiply the speed to get the force you have to apply

however  if you must use the transition.to function you have to calculate the time on you own way more complicated but if you insist

divide the y differece between the two objects by the (math.sin * speed(you chosen)) value and that would be the time

I wish I could go further but its really hard to explain on a keyboard :frowning:

p.s

I saw your second question and found out that  you,ve figured the time problem quite easily

all you gotta do is chage the

set the x , y value in

transition.to(arrow[i],{time=speed,x=event.x, y=event.y})

not in to event.x event.y but to

x = math.cos(angle)*(times the distant you want the arrow to travel),

y = math.sin(angle)*(times the distant you want the arrow to travel)

get the angle in a function like

local angle

local atanVal = math.atan(y/x)

if(atanVal >= 0)then
   angle = atanVal
  else
   angle = atanVal + (math.pi)
 end

there maybe an easier way but this one just came to my mind

Hi, thanks for the answer.

I’ve tried to use it but i dont know what should be the values of y/x here? local atanVal = math.atan(y/x 

Also, what if i want to make something more like a magic ball? A proyectile wich doesn’t make a parabola, it just goes to event.x and event.y and then follow the same path to exit the scene?

Thanks

ps: i’m using transition.to because i thought it was the best way to do this, i don’t mind using another funcion at all

the x, y in atanVal is the event.x and event.y

:) glad you asked more , I got some things wrong at the first reply i didn’t know you were shooting horizontally

if youre shooting horizontal it get’s way simple

 if you use applyForce

– first obviously you should make a body for the object 

local physics = require(“physics”)

local magicBullet = display.newImage(“image.png”)

physics.addBody(magicBullet,“dynamic”)

–get the angle in a function like atan or atan2

– use atan2 to get the whole 360angle but you should use “,” not “/”

– use atan to get only 90~negative90 angle and shoot from left to right, you should use “/” not “,”

local atanVal = math.atan2(event.y,event.x)

–or

local atanVal = math.atan(event.y/event.x) 

–  you can just use atanVal directly  as the angle in either cases if your shooting left to right  

– and in the atan2 case you can use atanVal directly nomatter which direction you shoot

– set the x,y Force

local xForce,yForce = cos(atanVal)*(speed) , sin(atanVal)*(–same speed should be applied)

– At last you do

physics.applyForce(xForce,yForce,magicBullet.x,magicBullet.y)

– this will apply the force in the x,y direction of magicBullet

I prefer applyForce since you can pause all the bullets by just calling physics.pause() it really comes handy when making a pause function for the game by the way I guess you would know but to use physics you need to trigger physics.start() don’t forget

you have to keep in mind to remove the object manualy even after it can’t be seen or the bullet will travel forever, same for the transition.to as it will just remain in the destination

Also it will never hurt to learn about the basic notions of math functions like arctangent tangent sin cosin etc, it is quite fun :slight_smile:

Dssi thanks for the answer.

I’ve applied those lines to my app (just in case somebody wants to use it too, its math.cos, math.sin on the local xForce,yForce and magicBullet:applyForce) but whenever i press, the arrow goes always a little bit to the bottom of the screen, and when I press in the upper section of the screen ( the arrow is initialized in the middle), the arrow goes to the middle, cant get past it. I know it might be something about a negative value but i don’t know what to change to do it. 

Tell me if you understand what i just said, if not i can make a simple graphic.

Thanks again

 I was in a rush so I may have left some more things out

above all I was foolish I didn’t ask where you will be initializing the arrow haha…

there are two things I missed

first you should turn Off gravity after you call physics.start()

by typing

physics.setGravity(0,0)

and I forgot to tell you how to set the initial location

so this is a script I tested and I gaurantee it  works

local physics = require(“physics”)

physics.start()
physics.setGravity(0,0)

local bulletGroup = display.newGroup()
 

local function touched(event)
if event.phase ==“began” then
local magicBullet = display.newImage(“image.png”)

local startX = 123 – startlocaations

local startY = 123

physics.addBody(magicBullet,“dynamic”)

**magicBullet.x = startX
magicBullet.y = startY
local atanVal = math.atan2(event.y - startX,event.x - startY)
local xForce,yForce = math.cos(atanVal)*(speed), math.sin(atanVal)*( speed )

magicBullet:applyForce(xForce,yForce,magicBullet.x,magicBullet.y)**

bulletGroup:insert(magicBullet)  – i reccomend you do this so you’ll be able to delete
end
end

Runtime:addEventListener(“touch”,touched)

I just started answering questions so my replies are pretty lame …sorry haha… :D  :D 

Thanks a lot! added it inside a for loop and it worked!

Only thing i’ve noticed is that if you want to use a different position where startX =/ startY you have to use 

local atanVal = math.atan2(event.y - startX,event.x - startY)

instead of 

local atanVal = math.atan2(event.y - startY,event.x - startX)

Thanks for all the help, i’ll totally need to re-read all those math books haha…

I would recommend:

http://www.amazon.com/Mathematics-Game-Developers-Development/dp/159200038X

or

http://www.amazon.com/Beginning-Math-Physics-Game-Programmers/dp/0735713901/ref=pd_sim_b_1

I tested this chunk of code for my self and it was very nice

One thing I would like to implement is that the arrow follows the sinus curve so it looks more natural

so it kinda points down when it false to the ground

and I´m also one of those coders who says “I wish I didn´t sleep through the math lessons at school”

I started with:

physics.setGravity(0,4) --so it falls down after a while

local speed = -20 --this could be calculated on the length between self and target

magicBullet.isFixedRotation = false  --but after this I got lost

hmm, that’s strange it may have something to do with the view My scripts are based on vertical so , anyway gladit works

I was thinking like this:

http://snag.gy/TB2xj.jpg

If you already use physics, why don’t you do that for the shooting as well?

You could use object:applyForce, object:setLinearVelocity or object:apply linear impulse to do so.

Hi, thanks for the answer.

I just wanted to use physics for the collisions, thats why i’m using static mode on the arrows. 

Those properties like applyForce only work for dynamic if im not wrong, and I dont really know how to make it “natural” like a linear arrow movement, that way.

Ok, forget the physics. I’ll move it using transition.to, but i need some basic mathematical help. Here is what i have:

local function shoot\_arrow(event) if event.phase == "began" then local speed = event.x\*2.5 for i = 1,1 do arrow[i] = display.newImage("arrow.jpg") arrow[i].x = 55; arrow[i].y = 155 transition.to(arrow[i],{time=speed,x=event.x, y=event.y}) end end end background:addEventListener("touch",shoot\_arrow)

But i’m trying to move the arrow outside the view,but using event.x and event.y so the arrow follows the path wherever the player touched the background. 

you need to use <math.atan> to get the angle and then use< math.sin> and< math.cos> and multiply the speed to get the force you have to apply

however  if you must use the transition.to function you have to calculate the time on you own way more complicated but if you insist

divide the y differece between the two objects by the (math.sin * speed(you chosen)) value and that would be the time

I wish I could go further but its really hard to explain on a keyboard :frowning:

p.s

I saw your second question and found out that  you,ve figured the time problem quite easily

all you gotta do is chage the

set the x , y value in

transition.to(arrow[i],{time=speed,x=event.x, y=event.y})

not in to event.x event.y but to

x = math.cos(angle)*(times the distant you want the arrow to travel),

y = math.sin(angle)*(times the distant you want the arrow to travel)

get the angle in a function like

local angle

local atanVal = math.atan(y/x)

if(atanVal >= 0)then
   angle = atanVal
  else
   angle = atanVal + (math.pi)
 end

there maybe an easier way but this one just came to my mind

Hi, thanks for the answer.

I’ve tried to use it but i dont know what should be the values of y/x here? local atanVal = math.atan(y/x 

Also, what if i want to make something more like a magic ball? A proyectile wich doesn’t make a parabola, it just goes to event.x and event.y and then follow the same path to exit the scene?

Thanks

ps: i’m using transition.to because i thought it was the best way to do this, i don’t mind using another funcion at all

the x, y in atanVal is the event.x and event.y

:) glad you asked more , I got some things wrong at the first reply i didn’t know you were shooting horizontally

if youre shooting horizontal it get’s way simple

 if you use applyForce

– first obviously you should make a body for the object 

local physics = require(“physics”)

local magicBullet = display.newImage(“image.png”)

physics.addBody(magicBullet,“dynamic”)

–get the angle in a function like atan or atan2

– use atan2 to get the whole 360angle but you should use “,” not “/”

– use atan to get only 90~negative90 angle and shoot from left to right, you should use “/” not “,”

local atanVal = math.atan2(event.y,event.x)

–or

local atanVal = math.atan(event.y/event.x) 

–  you can just use atanVal directly  as the angle in either cases if your shooting left to right  

– and in the atan2 case you can use atanVal directly nomatter which direction you shoot

– set the x,y Force

local xForce,yForce = cos(atanVal)*(speed) , sin(atanVal)*(–same speed should be applied)

– At last you do

physics.applyForce(xForce,yForce,magicBullet.x,magicBullet.y)

– this will apply the force in the x,y direction of magicBullet

I prefer applyForce since you can pause all the bullets by just calling physics.pause() it really comes handy when making a pause function for the game by the way I guess you would know but to use physics you need to trigger physics.start() don’t forget

you have to keep in mind to remove the object manualy even after it can’t be seen or the bullet will travel forever, same for the transition.to as it will just remain in the destination

Also it will never hurt to learn about the basic notions of math functions like arctangent tangent sin cosin etc, it is quite fun :slight_smile: