firing arc

BlitzMax Forums/BlitzMax Programming/firing arc

Cruis.In(Posted 2013) [#1]
Hey guys,

I want to figure out how to set a firing arc for directly ahead of a ship object, where the firing arc = 60 degrees.

      /  
     /  <-- arc
    /  
   O <---- ship

where the angle between there is the firing arc.

I been learning 2d maths, trig, equations, py theory. Bit difficult for 40 yr old who majored more in arts than sciences :)

Been reading math sites on math sites for days, looking at how to calculate distance, bearings, angles of vectors.

Been testing what I've learned or thought I learned.



my ship is always centered in the middle of the screen.

I therefore want to calculate the angle of enemy ships from my ship, and then of course I will test if they fall within my specified arc, before firing is allowed.

My ship is obviously going to be turning, it's angle will be changing, and it should only be able to fire ahead of it.

So I have the X,Y of the enemy ship/s and the angle my ships is facing. I am guessing this means I have two vectors.

What would be the formula for calculating the angle of that enemy from my ship? I used this formula

http://www.jtaylor1142001.net/calcjat/Solutions/VDotProduct/VDPTheta2D.htm

It produced weird result (yes fixed), even though I checked and double checked calculations.

The other issue I can think of is even if I had the right formula for the calculation, that would give me the angle of the enemy ship from my ship, but that wouldn't change based on me rotating my ship. So let's say I maneuvered the enemy to be at a 60 degree angle from my ship, I could be facing away from him and still fire, which ruins the idea of being only able to fire from the front of my ship.

I guess what I have to determine is, is my ship facing the enemy?

Kind of stumped, any aids in the right direction would be useful. thanks

Last edited 2013

Last edited 2013


GfK(Posted 2013) [#2]
To get the angle just use this:
angle = Atan2(enemyY-playerY, enemyX-playerX)

You can subtract the player's rotation angle from the result and work within a tolerance of, say +/-10 degrees for a 20 degree FOV.


GfK(Posted 2013) [#3]
Ha, code tags are broken!


Cruis.In(Posted 2013) [#4]
so am I correct in saying that atan2 just calculates the angle between the two tangents?


Cruis.In(Posted 2013) [#5]
of course in this instance, atan2 is returning the top half of the circle as positive values and bottom half as negetive




E <--- enemyship



anywhere above, from the left straight OVER the top of E to the right returns 0-180 value.

Anywhere below is -1 to -179

still leaves the issue, of determining if the enemy is in my firing arc.


Midimaster(Posted 2013) [#6]
well, with ATAN2 you now have the absolut direction of a vektor from ship to enemy (relativ to the world). And you know the orientation of your ship (relativ to the world), you can calculate the relativ direction of the enemy seen from the ship. It is simply the difference. And now you can check whether it is bigger or smaller than 30°.

The problems with negativ results you can eliminate by

Arc=(Arc+360) mod 360

The problems with vektors and orientation around 0° you can eliminate by doing two checks:


Spaceship: 10°
Enemy: 350°

ARC=abs(10-350)=340°
If ARC>180 then a second check is necessary:
ARC=Abs(10+360-350)=20°


Cruis.In(Posted 2013) [#7]
ok so atan2 gives me the angle of the enemy from me. I know the orientation of my ship which is variable ship.angle.

next part was "you can calculate the relative direction of the enemy seen from the ship, it is simply the difference"

not sure I understand this part.

would that be arc = ship.angle - ( atan2(eship.x - ship.x, eship.y - eship.x) )


Cruis.In(Posted 2013) [#8]
ok the attempt at drawing it above using symbols doesn't come out right.

http://imageshack.us/photo/my-images/593/arcx.png/

your view is fixed on the ship at the centre of the screen, while you rotate and move about the world.

I need to know the constant value of that 'arc' or angle there ahead of the ship. That value needs to be obtained, told to the program and remain constant.

then I will check if the 'target' falls within that value.


Midimaster(Posted 2013) [#9]
Now it depends on how you coded the orientation of the world....

If you store all objects in world coordinates, my formula is working like this:

[bbcode]Graphics 800,600

Global E_X#,E_Y#, S_X#=400,S_Y#=300,S_Orient#

Global WorldAngle#, ShipAngle#, Arc#
Global Timer%
Global i%=100
Repeat

' only for simulate a rotation:
i=i+1
E_X=400+Sin(i%)*200
E_Y=300+Cos(I)*200
WorldAngle=(360+ATan2( S_X-E_X , S_Y-E_Y ))Mod 360

If Timer<MilliSecs()
Timer=MilliSecs()+2000
ShipAngle=(ShipAngle+20) Mod 360
EndIf

Cls

Arc=Abs(ShipAngle-WorldAngle)
If Arc>180 Then
Arc=360-arc
EndIf

SetRotation 0
SetOrigin 0,0
If Arc<31
SetColor 255,0,0
Else
SetColor 255,255,255
EndIf
DrawOval E_X,E_Y,10,10
DrawText " Enemy's World Angle = " + Int(WorldAngle), 40,40
DrawText "Ship Orientation Angle = " + Int(ShipAngle), 40,60
DrawText " Difference = " + Int(Arc) , 40,80
SetOrigin S_X,S_Y
SetRotation -ShipAngle


DrawRect -5,0,10,40
DrawRect -1,0,2,-140
SetColor 255,0,0
DrawOval -3,-3,6,6
Flip 1
Until KeyHit(KEY_ESCAPE)


[/bbcode]

Last edited 2013


Kryzon(Posted 2013) [#10]
Once you have this angle in degrees (which is the angle of the line that goes from your centered ship to your enemy, target or whatever), you can compare it with the known angle limits of your arc (which are nothing more than numerical values).

More of the same, but from a different school:



Derron(Posted 2013) [#11]
Just to note:
	WorldAngle = ATan2( S_X-E_X , S_Y-E_Y )
	if WorldAngle  < 0 then WorldAngle:+360

is a bit faster than using the modulo operator in all cases.

The code just uses the modulo to convert the range from "-180 to 180" to "0 to 360" degrees.

Without that modulo:

everything above the line: __|___ -> is >90 or <-90

Think of it as an "eye of sight". You could then limit the view by limiting the degrees range eg to smaller values.
The "more" positive degrees, the more it is moving "left ways" away from your looking-at point. Same for the right side (except it is negative).

Without the modulo you are able to easily know in which direction you should rotate...

But there are plenty ways to achieve the desired result.


PS: before I forget the most important fact: modulo truncates floats. So you end up getting integers - this may lead to unwanted results in case of more precision needed.

bye
Ron


Cruis.In(Posted 2013) [#12]
hi kyrzon thanks for the code. Unfortunately I do not think applying it as is works.

I don't think that it takes into account the present player ship's facing. Meaning that, ok as I fly around the enemy ship, his angle from me changes, so put him in a firing arc and fire. Problem with that is if I rotate my ship so that the aft is facing the enemy, the enemy ship's angle to me remains the same. So let's say I maneuver the enmyship to be at an angle from me of 60 degrees value. Then rotate my ship and face away, he's still at 60 degrees and I can still fire. But obviously that isn't the desired effect since I want the arc on the front.


Cruis.In(Posted 2013) [#13]
this code here



this is derived from this formula

atan2(px*cosA - py*sinA , py*cosA + px*sinA)

where PX = (mouseX - graphicswidth()/2)
where py = (-mousY - graphicsheight()/2)
where A = playerships Angle

what this does is check the angle of my mouseX & mouseY relative to my ship.

I've stored the value of the mouse pointer in variable ARC, using that formula above. Whenever my mouse pointer is in front of my ship (no matter what direction my ship is facing) it has a low value. So the forward firing arc of my ship is like between -30 and 30

so when I check if the enemyship is between -30 and 30, basically a 60 degree firing arc.

So this way I have to be FACING the enemy with the NOSE (front of my ship) & I have to have the mouse pointer within that -30, 30 arc as well.

Because I am using the mouse pointer as the aimer, the projectile fires toward the mouse pointer. So basically I am checking the angle of my mouse pointer from my ship, and included in that check the value of the angle is being supplemented by my ships current rotation.

So if my ship is facing, but my mouse pointer is behind my ship, the ARC value will be off, it won't be within a -30, 30 range, it always works out based on the formula above that I have to be facing the enemy ship with my ship, then once the pointer from my ship is within the specified arc -30, 30 im allowed to shoot.

I want to experiment taking out the mouse pointer as the shooter. So instead of checking the mouseX and MouseY, I substituted the enemyX and enemyY in the above formula where mouseX and Y is, and kept everything else the same. Hoping that when the enemy is in front my ship, it would be within the firing arc, based on my ships rotation just like before.

Only thing now its checking, the enemy ship location to me, and my ships rotation. So once I press a button on the keyboard for example (if my ships is facing the enemy) hence within forward arc, it'll fire.

removing the need for the mouse to be used as the aimer, if I wanted.

Am I making sense?


Kryzon(Posted 2013) [#14]
But obviously that isn't the desired effect since I want the arc on the front.

I think I get what you're after. You want the screen to be independent of the player ship's orientation. In other words, the screen isn't "attached" to the ship, and the ship can rotate independently.

In that case, you need to assume a "starting" orientation for your ship - it's the orientation you start the game with - say it's the default one of pointing up, at -90 degrees.
While the game is running, you offset your arc's angle limits with the ship's rotation, so your arc is always oriented according to wherever your ship is pointing.
It's as simple as that, adding your ship's rotation (as an angle value) to the angle values that represent the limits of your shooting arc.


Cruis.In(Posted 2013) [#15]
ok i tried it again...using exactly the code I typed above. I swear I did it before.

I have narrowed down the area that is always in front of my ship to always be a particular value. No matter how I rotate or where I or the enemy is.

Now that this value is constant, I can set a firing arc based on it.

The angle directly ahead of my ship is always 180, if i drew a straight line. this means a good firing arc of 160 and 200 is good. Anything between 160 and 200.

Last edited 2013


Cruis.In(Posted 2013) [#16]
ok i tired it again...using exactly the code I typed above. I swear I did it before.

I have narrowed down the area that is always in front of my ship to always be a particular value. No matter how I rotate or where I or the enemy is.

Now that this value is constant, I can set a firing arc based on it.

The angle directly ahead of my ship is always 180, if i drew a straight line. this means a good firing arc of 160 and 200 is good. Anything between 160 and 200


by saying " you offset your arc's angle limits with the ship's rotation, so your arc is always oriented according to wherever your ship is pointing."


You meant the angle of enemy ship from my ship right? And not meaning how wide I want my actual frontal firing arc to be. I assumed that is what you meant and thats why I did the code as I did for it to now work. Since really all I need is the to have the area in front of my ship = a constant value (which it does now) so i can check if said value falls within stipulated firing arc.


It's as simple as that, adding your ship's rotation (as an angle value) to the angle values that represent the limits of your shooting arc.


again i assumed you meant the angle of my ship to the enemy.

Last edited 2013


Kryzon(Posted 2013) [#17]
There's no way to comment without your exact code - if you can share it, please do.

From what you posted at #15, your ATan2() has a wrong order of arguments: it should be delta Y as first argument then delta X as second.

Also, the ship's rotation angle may have some weird sign and you'll need to take that into consideration (remember pointing up in screen coordinates means -90 degrees), so make sure you're not cancelling values by adding things with different signs.


Cruis.In(Posted 2013) [#18]
sorry the code i did to get it 'hacked' heh is



I found that strange, that my ship is pointing up on start, as thats how the image is in the image file and the angle still reports 0. Probably because i've offset that by having If angle#<0.0 Then angle#=360.0
If angle#>360.0 Then angle#= 0.00

so it never goes to negative values.

Last edited 2013


Cruis.In(Posted 2013) [#19]
so atan2 should be this?

ATan2(enemyship.y - ship.x, enemyship.y - ship.x)

that sends it off again, the value doesn't work out.

Last edited 2013


Kryzon(Posted 2013) [#20]
No, "delta Y" means you only deal with Y components: enemyship.y - ship.y

For the delta X: enemyship.x - ship.x

Then you order them like so: ATan2(deltaY, deltaX) (specifically with Y before X)

(Since you're interested in the maths, under the hood you are calculating a line's slope value.)

Last edited 2013


Jesse(Posted 2013) [#21]
its like this:

ATan2(enemyShip.y-ship.y,enemyShip.x - ship.x)

that will give you the angle from ship to enemyShip.


Derron(Posted 2013) [#22]
Jesse: this "formula" was presented multiple times in this thread. If the OP is not able to use them I would not care any longer.

Atan2 is used to calculate the angle between two points in a 2d-System (the normal X/Y-Carthesian we know).
yes... POINTS... to get a "viewing arc" you just have to check the angle of the object to the global world.
Why? If the world "rotates" the x,y of the 2 objects will change too, their angle will then change according to the new x,y.
That is why you have to know: Angle of the "shooting" ship according to the world, Angle of between the two ships... afterwards it is just Addition and Subtraction.


bye
Ron


Cruis.In(Posted 2013) [#23]
no need to get fiesty, the repetition of atan2 is not an issue.

I have been merely trying to understand it and understand how stuff works, which is the reason for the length of the thread etc.

I do not merely wish to come and receive a formula and then retreat back into the shadows.

But to understand it's implementation how it works, why it works, so I can understand the results.

thanks for all your helps, sorry to waste your times.


Derron(Posted 2013) [#24]
But to know what atan2 does, there are better ways:
https://en.wikipedia.org/wiki/Atan2

For game implementation thoughts I do not see enough related posts in this thread.

If you are unsure what does what and why:
take a sheet of paper and a pencil.
a) Draw a rect: your "screen" (the hardware device -> realXY)
b) Draw a somehow rotated "screen" (your world-screen or camera view viewXY)
c and d) Draw 2 somehow rotated small rects (your ships -> object or localXY)

Call the x and y axis of each rect like aX aY, bX, bY, ...

Now you can reach each point of interest and use the formulas of above.

If you do not trust atan2 (it is an algorithm) you can easily make custom (but heavier) calculations.
Why?
2 Points in a carthesian coordinate system can built up an triangle with one 90 dregree angle.
And knowing that... pythagoras and friends will help with classical sin/tan and cosinus usage.

The most important thing is overview: know what coordinates build up a line.


bye
Ron