Merge pull request #11788 from pchote/fix-smooth-moves
Make turning-while-moving actors follow curved paths.
This commit is contained in:
@@ -64,6 +64,20 @@ namespace OpenRA
|
|||||||
return new WAngle(Angle - 512).Tan();
|
return new WAngle(Angle - 512).Tan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static WAngle Lerp(WAngle a, WAngle b, int mul, int div)
|
||||||
|
{
|
||||||
|
// Map 1024 <-> 0 wrapping into linear space
|
||||||
|
var aa = a.Angle;
|
||||||
|
var bb = b.Angle;
|
||||||
|
if (aa > bb && aa - bb > 512)
|
||||||
|
aa -= 1024;
|
||||||
|
|
||||||
|
if (bb > aa && bb - aa > 512)
|
||||||
|
bb -= 1024;
|
||||||
|
|
||||||
|
return new WAngle(aa + (bb - aa) * mul / div);
|
||||||
|
}
|
||||||
|
|
||||||
public static WAngle ArcTan(int y, int x) { return ArcTan(y, x, 1); }
|
public static WAngle ArcTan(int y, int x) { return ArcTan(y, x, 1); }
|
||||||
public static WAngle ArcTan(int y, int x, int stride)
|
public static WAngle ArcTan(int y, int x, int stride)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -292,6 +292,12 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
protected readonly Move Move;
|
protected readonly Move Move;
|
||||||
protected readonly WPos From, To;
|
protected readonly WPos From, To;
|
||||||
protected readonly int FromFacing, ToFacing;
|
protected readonly int FromFacing, ToFacing;
|
||||||
|
protected readonly WPos ArcCenter;
|
||||||
|
protected readonly int ArcFromLength;
|
||||||
|
protected readonly WAngle ArcFromAngle;
|
||||||
|
protected readonly int ArcToLength;
|
||||||
|
protected readonly WAngle ArcToAngle;
|
||||||
|
|
||||||
protected readonly int MoveFractionTotal;
|
protected readonly int MoveFractionTotal;
|
||||||
protected int moveFraction;
|
protected int moveFraction;
|
||||||
|
|
||||||
@@ -304,6 +310,24 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
ToFacing = toFacing;
|
ToFacing = toFacing;
|
||||||
moveFraction = startingFraction;
|
moveFraction = startingFraction;
|
||||||
MoveFractionTotal = (to - from).Length;
|
MoveFractionTotal = (to - from).Length;
|
||||||
|
|
||||||
|
// Calculate an elliptical arc that joins from and to
|
||||||
|
if (fromFacing != toFacing)
|
||||||
|
{
|
||||||
|
// The center of rotation is where the normal vectors cross
|
||||||
|
var u = new WVec(1024, 0, 0).Rotate(WRot.FromFacing(fromFacing));
|
||||||
|
var v = new WVec(1024, 0, 0).Rotate(WRot.FromFacing(toFacing));
|
||||||
|
var w = from - to;
|
||||||
|
var s = (v.Y * w.X - v.X * w.Y) * 1024 / (v.X * u.Y - v.Y * u.X);
|
||||||
|
var x = from.X + s * u.X / 1024;
|
||||||
|
var y = from.Y + s * u.Y / 1024;
|
||||||
|
|
||||||
|
ArcCenter = new WPos(x, y, 0);
|
||||||
|
ArcFromLength = (ArcCenter - from).HorizontalLength;
|
||||||
|
ArcFromAngle = (ArcCenter - from).Yaw;
|
||||||
|
ArcToLength = (ArcCenter - to).HorizontalLength;
|
||||||
|
ArcToAngle = (ArcCenter - to).Yaw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Cancel(Actor self)
|
public override void Cancel(Actor self)
|
||||||
@@ -344,9 +368,22 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
|
|
||||||
void UpdateCenterLocation(Actor self, Mobile mobile)
|
void UpdateCenterLocation(Actor self, Mobile mobile)
|
||||||
{
|
{
|
||||||
// avoid division through zero
|
// Avoid division through zero
|
||||||
if (MoveFractionTotal != 0)
|
if (MoveFractionTotal != 0)
|
||||||
mobile.SetVisualPosition(self, WPos.Lerp(From, To, moveFraction, MoveFractionTotal));
|
{
|
||||||
|
WPos pos;
|
||||||
|
if (FromFacing != ToFacing)
|
||||||
|
{
|
||||||
|
var angle = WAngle.Lerp(ArcFromAngle, ArcToAngle, moveFraction, MoveFractionTotal);
|
||||||
|
var length = int2.Lerp(ArcFromLength, ArcToLength, moveFraction, MoveFractionTotal);
|
||||||
|
var height = int2.Lerp(From.Z, To.Z, moveFraction, MoveFractionTotal);
|
||||||
|
pos = ArcCenter + new WVec(0, length, height).Rotate(WRot.FromYaw(angle));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pos = WPos.Lerp(From, To, moveFraction, MoveFractionTotal);
|
||||||
|
|
||||||
|
mobile.SetVisualPosition(self, pos);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
mobile.SetVisualPosition(self, To);
|
mobile.SetVisualPosition(self, To);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user