Alternatives for DeltaYaw?

Blitz3D Forums/Blitz3D Programming/Alternatives for DeltaYaw?

Cubed Inc.(Posted 2012) [#1]
If was wondering if there was anyway to "tighten up" the turning of this arrow.



Sounds kinda weird right? Let me explain.
Notice how when the arrow turns, it sort of has this acceleration in it where is turns slower as it is more pointed towards the assigned direction.
I want to get rid of that acceleration in it's turning so that the arrow will always turn with the same speed and stops immediatley when is pointing the proper direction.

If your still having trouble picturing it, I don't blame you. I suck at explaining things.

If you watch this video...
http://www.youtube.com/watch?v=SVZbl9u0P8w
You'll notice how mario's turning does not have that acceleration stop look when he turns.
(videos laggy so it's more noticable)

Anyone have any ideas on how to pull this off?
Any help is appreciated.

Last edited 2012

Last edited 2012

Last edited 2012

Last edited 2012

Last edited 2012

Last edited 2012


Yasha(Posted 2012) [#2]
Well the cause of this is simple: you're turning by a proportion of the current DeltaYaw each frame, but the turn is itself changing the delta and thus changing the rate at which you turn (stating the obvious).

Easy solution: call DeltaYaw once, store the result in... something... and then access that stored figure for OriginalDeltaYaw to multiply by 0.02 instead. That way the rate of movement won't change. This introduces a touch more complexity since you'll need to differentiate between "starting a turn" and "currently on the way from an original position", but it's nothing a state flag can't handle.

Last edited 2012


Kryzon(Posted 2012) [#3]
First let's understand why it's doing what it's doing.
The arrow is pointing in any direction, then you call DeltaYaw(). It'll hold a big value, multiplied by that 0.2 to bring it down so the arrow doesn't snap to the target.

Next time you call DeltaYaw(), it'll hold a smaller value and so on and so forth, so every time the arrow draws closer to the target, it turns slower.

The way to keep it constant is by ignoring the amount by which the arrow has to turn, and only worry about its sign. You retrieve the sign of a number using Blitz3D's Sgn() function.
It'll return -1 for negative numbers, 0 for zero, and 1 for positive numbers.

Const turnSpeed# = 0.1

Local tempYaw#

[...]

tempYaw = DeltaYaw(arrow,pivot)
tempYaw = tempYaw * (Abs(tempYaw) > 0.01) ;Expression to snap values smaller than '0.01' to 'zero'.

TurnEntity arrow, 0, Sgn(tempYaw) * turnSpeed, 0

EDIT: Ninja'd by Yasha :D

Last edited 2012


Matty(Posted 2012) [#4]
So two methods depending upon what you require:


Constant turning rate:

DeltaYaw = 60 degrees for example.
Turning by 5 degrees (an example 'turning speed') each frame would take 12 frames to turn through 60 degrees. If the delta yaw was larger, say 90 degrees then it wuold require 18 frames to turn through at a rate of 5 degrees per frame.

Alternative method

Constant turning time:
DeltaYaw = 60 degrees for example.
Turning time = 10 frames, therefore turning rate would be 6 degrees per frame in this case (60/10 = 6).
For a different delta yaw (say 90 degrees) with the same turning time would require a turning rate of 9 degrees per frame.


So there are another two methods:

1 - a fixed turning rate - taking longer to turn a larger angle, but turning at the same rate.
2 - a fixed turning time - taking the same time to turn a larger angle, but turning at a different rate.

Some thoughts for you.


Cubed Inc.(Posted 2012) [#5]
Kryzon
I don't quite understand whats going on in your explaination, mainly becuase i'm not familiar with the sgn function. Hell, I didn't even know it existed until you mentioned it.
I'm pretty confused right now.
Can you explain some more please?
I really want to figure out how to get around this turning issue of mine.


Stevie G(Posted 2012) [#6]
Const TurnRate# = 5.0

DY# = Deltayaw( arrow, pivot )
If abs( DY ) > TurnRate DY = sgn( DY ) * TurnRate
TurnEntity arrow,0, DY,0


Adjust turnrate as appropriate.

Stevie

Last edited 2012


Kryzon(Posted 2012) [#7]
Hi TaGames. What's happening in my sample is this:

- Check how much the arrow has to turn to target.
- If this amount to turn by is lower than '0.01' (a very low amount), then consider it the same as 'zero'.
- Use the direction of the turn (left, right or still) to modulate the constant speed. It'll either move left by the fixed amount, move right by the fixed amount or simply stand still.

Blitz3D treats boolean expressions as numerical values. This is a very useful feature, such that we can use them in may places in our code without having to resort to IFs.
We can use this to include them in numerical expressions:
tempYaw = DeltaYaw(arrow,pivot)
tempYaw = tempYaw * (Abs(tempYaw) > 0.01) ;Expression to snap values smaller than '0.01' to 'zero'.
The expression "(Abs(tempYaw) > 0.01)" will always return either '1' (True) if the amount left for the arrow to turn is bigger than '0.01', or 'zero' (False) if the amount left to turn is smaller than that.

This means "if the arrow has to turn very little to face the target such that it won't be noticeable, then no need to turn at all". It's not really necessary, but this level of control makes me feel warmer inside...
Anyway, we multiply this expression by tempYaw (the actual amount to turn by). If that boolean expression results in '1', tempYaw will remain as it is, unchanged. If it's 'zero', tempYaw will also become zero (hence the snapping to zero in case it's smaller than that small value).

This is how the computer looks at this:
(when > 0.01) tempYaw * 1 = tempYaw
(when smaller than 0.01) tempYaw * 0 = 0

Now for the transformation:
TurnEntity arrow, 0, Sgn(tempYaw) * turnSpeed, 0
At this point in the program, tempYaw will hold 'zero' if it's too small, or an actual positive or negative degree value.
Sgn() will extract the sign of the value (positive, negative or null). It returns -1, 0 or 1 at any time.
I'm considering this returned value as the direction the arrow has to turn to (only the direction, not the amount. Read below).

Multiplying the result of Sgn() by the fixed speed makes the arrow turn toward the direction needed to face the target, but by the amount described by 'turnSpeed'. So it'll turn by the fixed speed you want - whatever value 'turnSpeed' represents.

EDIT: Added the Abs() after looking at Stevie G's.

Last edited 2012


Cubed Inc.(Posted 2012) [#8]
Kryzon
Okay, I think I get it now.
While using Deltayaw, the yaw value of the arrow speeds up depending on how close it is to pointing at it's destination.

So the closer it gets, the slower it turns and vice versa.

While using Stevie G's and your code, the yaw value of the arrow is rounded to the nearest full speed (in this case, 5.0)

Just a question though. Does the turnspeed value have to go via the square root of 5? Any other values seem to lead to violent shaking of the arrow.


Kryzon(Posted 2012) [#9]
Use any value you want. Try different ones.

The code he posted is a bit leaner, so you should use that. The speed value is very big though (5.0 units is very fast), so try 0.1.


Cubed Inc.(Posted 2012) [#10]
Works perfectly!
Thanks a bunch everyone!