From 03e2fa5d554204b26ba68b7761cf75fa6ed9d601 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Aug 2016 19:29:03 +0100 Subject: [PATCH] Lerp turning-while-moving mobile actors along an arc. --- OpenRA.Mods.Common/Activities/Move/Move.cs | 41 ++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/OpenRA.Mods.Common/Activities/Move/Move.cs b/OpenRA.Mods.Common/Activities/Move/Move.cs index d0f637506c..2b01a2c169 100644 --- a/OpenRA.Mods.Common/Activities/Move/Move.cs +++ b/OpenRA.Mods.Common/Activities/Move/Move.cs @@ -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);