Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1]
  Print  
Author Topic: Caclulate facing angle  (Read 1273 times)
Canning
Community Member
*
Posts: 592


« on: September 24, 2011, 05:42:07 AM »

Is this the correct code to calculate a facing angle in 2d:

Code:
Ship.msngFacing = System.Math.Atan2(Ship.Target.x - Ship.msngX, Ship.Target.y - Ship.msngY)

Where Ship.msngFacing is the facing angle, Ship.Target.x and Ship.Target.y the desired target, and Ship.msngX and Ship.msngY the position of the source.

I'm sure it is correct, but it aint working.

In my 3d game, I use a vector normalize technique. Is there such a thing for 2d vectors?

Canning
« Last Edit: September 24, 2011, 05:44:11 AM by Canning » Logged

I am using 2010 VB.NET and TV 6.5 with Windows 7
Mithrandir
Community Member
*
Posts: 325


« Reply #1 on: September 24, 2011, 08:27:19 AM »

I believe there is Direction2Ang that does that.

To normalize a 2D vector use TVVec2Normalize
Logged
Canning
Community Member
*
Posts: 592


« Reply #2 on: September 24, 2011, 09:10:19 PM »

Figured it out.

Code:
Ship.msngFacing = System.Math.Atan2(Ship.Target.y - Ship.msngY, Ship.Target.x - Ship.msngX) + PI / 2

Canning
« Last Edit: September 24, 2011, 11:57:33 PM by Canning » Logged

I am using 2010 VB.NET and TV 6.5 with Windows 7
asia
Customers
Community Member
*****
Posts: 183


« Reply #3 on: September 30, 2011, 03:47:31 AM »

The PI/2 comes from your choice of what is forward...Z is an alternative to X...
Logged

Fabio Musmeci
ENEA
CR Casaccia
Via Anguillarese 301
00060 Rome
Italy
musmeci@enea.it
+39 3333934898
Learning to live better on a smaller footprint..
Canning
Community Member
*
Posts: 592


« Reply #4 on: October 02, 2011, 09:55:52 PM »

OK, next problem... I am wanting to turn my ship from its current angle to a destination angle.

This is my current code:

Code:
        If Ship.turning = True Then

            a = System.Math.Sin(Ship.msngHeading + PI)
            b = System.Math.Cos(Ship.msngHeading + PI)
            c = System.Math.Sin(Ship.msngFacing)
            d = System.Math.Cos(Ship.msngFacing)

            det = a * d - b * c

            If det > 0 Then
                Ship.msngFacing = Ship.msngFacing + Ship.ROTATION_RATE * PI / 180
                If Ship.msngFacing > Ship.DestAngle Then
                    Ship.msngFacing = Ship.DestAngle
                    Ship.turning = False
                    'Ship.stopping = True
                End If
            Else
                Ship.msngFacing = Ship.msngFacing - Ship.ROTATION_RATE * PI / 180
                If Ship.msngFacing < Ship.DestAngle Then
                    Ship.msngFacing = Ship.DestAngle
                    Ship.turning = False
                    'Ship.stopping = True
                End If
            End If
        End If

Sometimes it turns nicely, other times it 'jumps' to the destination angle. I think this has something to do with the sign changing when rotating.
Logged

I am using 2010 VB.NET and TV 6.5 with Windows 7
Mithrandir
Community Member
*
Posts: 325


« Reply #5 on: October 03, 2011, 06:54:15 PM »

It seems to me that "det" is just sine of angle between the ship's direction and direction towards the target (This comes nicely from cross product of the two vectors by the way).

So to get a nice rotation just get ASin(det) and keep adding/subtracting the "Ship.ROTATION_RATE" to/from the current ship angle until ASin(det) equals to 0. Which you are doing anyway.

The check you are performing afterwards:
Code:
If Ship.msngFacing > Ship.DestAngle Then
is probably messing stuff up. You then set the angle when you think you have reached the desired direction. You should only set:
Code:
Ship.msngFacing = Ship.DestAngle
when abs(ASin(det)) < Ship.ROTATION_RATE * PI / 180
Logged
Canning
Community Member
*
Posts: 592


« Reply #6 on: October 04, 2011, 04:46:43 AM »

Sorry, I didn't explain what Ship.DestAngle is. It is the destination angle that I am wanting to reach.

When I want to start rotating I call this code:

Code:
            Ship.DestAngle = System.Math.Atan2(Ship.Target.y - Ship.msngY, Ship.Target.x - Ship.msngX) + PI / 2
            Ship.turning = True

As i said, sometimes it turns nicely, other times it doesn't. I'm pretty sure many people will use similar functions in their games, so I thought I should ask.
« Last Edit: October 04, 2011, 05:42:19 AM by Canning » Logged

I am using 2010 VB.NET and TV 6.5 with Windows 7
Canning
Community Member
*
Posts: 592


« Reply #7 on: October 04, 2011, 06:24:33 AM »

I believe the correct way to do this is to measure the angle to turn through both clockwise and anticlockwise. Then choose whichever has smaller magnitude and rotate in that direction.

Is there a simple formula to do this?
Logged

I am using 2010 VB.NET and TV 6.5 with Windows 7
Mithrandir
Community Member
*
Posts: 325


« Reply #8 on: October 04, 2011, 02:52:56 PM »

I believe the correct way to do this is to measure the angle to turn through both clockwise and anticlockwise. Then choose whichever has smaller magnitude and rotate in that direction.

Is there a simple formula to do this?

Your "dot" is the sine of that angle.

I like to relate this to cross product. From wikipedia you have:

Where the magnitude (length) of the purple vector pointing up is given by:
So if "a" and "b" are unit vectors the magnitude of "axb" is the sine of the angle between them.
The magnitude is given by .
This then corresponds to your code where:
Quote
d=bx
c=by
b=cx
a=cy
dot = d * a - c * b
Notice that vectors [bx,by] and [cx,cy] are unit vectors since you calculate them using sine and cosine of an angle which by definition gives you coordinates on a unit circle.

The problem with the previous approach is that you probably get something like:
Code:
Ship.DestAngle = 10
Ship.msngFacing = 360
This means:
Code:
det > 0
and
Ship.msngFacing > Ship.DestAngle
Which executes:
Code:
Ship.msngFacing = Ship.DestAngle
This is where the ship jumps from 360 (which is 0) to 10 (DestAngle).
The easiest way to remedy this is to check for:
Code:
det<0

instead of:
Code:
Ship.msngFacing > Ship.DestAngle
within the inner condition.
Logged
Canning
Community Member
*
Posts: 592


« Reply #9 on: October 05, 2011, 05:09:24 AM »

So something like this:

Code:
        If Ship.turning = True Then

            a = System.Math.Sin(Ship.msngHeading + PI)
            b = System.Math.Cos(Ship.msngHeading + PI)
            c = System.Math.Sin(Ship.msngFacing)
            d = System.Math.Cos(Ship.msngFacing)

            det = a * d - b * c

            If det > 0 Then
                Ship.msngFacing = Ship.msngFacing + Ship.ROTATION_RATE * PI / 180
                If det < 0 Then
                    Ship.turning = False
                End If
            Else
                Ship.msngFacing = Ship.msngFacing - Ship.ROTATION_RATE * PI / 180
                If det > 0 Then
                    Ship.turning = False
                End If
            End If
        End If

Don't I need some statement checking to see if the facing angle reaches the destination angle (ship.DestAngle)? Currently, it just rotates south, then gets stuck.
Logged

I am using 2010 VB.NET and TV 6.5 with Windows 7
Mithrandir
Community Member
*
Posts: 325


« Reply #10 on: October 05, 2011, 05:49:16 PM »

Sure, you still need "Ship.msngFacing = Ship.DestAngle", otherwise you may overshoot the angle.

All you needed to change was the inner condition.

What it should be doing is decreasing the angle in every step until you overshoot (det<0). When it overshoots the angle difference between facing angle and destination angle is smaller than Ship.ROTATION_RATE so you basically just want to rotate the last bit which you do (or should be doing) by directly setting the angle.
Logged
Canning
Community Member
*
Posts: 592


« Reply #11 on: October 05, 2011, 10:22:33 PM »

Awesome, thanks. Smiley

Canning
Logged

I am using 2010 VB.NET and TV 6.5 with Windows 7
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.3 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks