Lerp turning-while-moving mobile actors along an arc.

This commit is contained in:
Paul Chote
2016-08-07 19:29:03 +01:00
parent 1f2824e614
commit 03e2fa5d55

View File

@@ -292,6 +292,12 @@ namespace OpenRA.Mods.Common.Activities
protected readonly Move Move;
protected readonly WPos From, To;
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 int moveFraction;
@@ -304,6 +310,24 @@ namespace OpenRA.Mods.Common.Activities
ToFacing = toFacing;
moveFraction = startingFraction;
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)
@@ -344,9 +368,22 @@ namespace OpenRA.Mods.Common.Activities
void UpdateCenterLocation(Actor self, Mobile mobile)
{
// avoid division through zero
// Avoid division through zero
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
mobile.SetVisualPosition(self, To);