diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a450a7..7e4db6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,15 @@ Jump to version: ## 5.1.0 (Unreleased) ### MLEM +Additions +- Added RotateBy to Direction2Helper + Fixes - Set default values for InputHandler held and pressed keys to avoid an exception if buttons are held in the very first frame Improvements - Improved NinePatch memory performance +- Moved sound-related classes into Sound namespace ### MLEM.Ui Fixes diff --git a/MLEM/Misc/Direction2.cs b/MLEM/Misc/Direction2.cs index 4a52861..c95dabe 100644 --- a/MLEM/Misc/Direction2.cs +++ b/MLEM/Misc/Direction2.cs @@ -85,6 +85,9 @@ namespace MLEM.Misc { /// public static readonly Direction2[] AllExceptNone = All.Where(dir => dir != Direction2.None).ToArray(); + private static readonly Direction2[] Clockwise = {Direction2.Up, Direction2.UpRight, Direction2.Right, Direction2.DownRight, Direction2.Down, Direction2.DownLeft, Direction2.Left, Direction2.UpLeft}; + private static readonly Dictionary ClockwiseLookup = Clockwise.Select((d, i) => (d, i)).ToDictionary(kv => kv.d, kv => kv.i); + /// /// Returns if the given direction is considered an "adjacent" direction. /// An adjacent direction is one that is not a diagonal. @@ -190,26 +193,7 @@ namespace MLEM.Misc { /// Whether to rotate by 45 degrees. If this is false, the rotation is 90 degrees instead. /// The rotated direction public static Direction2 RotateCw(this Direction2 dir, bool fortyFiveDegrees = false) { - switch (dir) { - case Direction2.Up: - return fortyFiveDegrees ? Direction2.UpRight : Direction2.Right; - case Direction2.Right: - return fortyFiveDegrees ? Direction2.DownRight : Direction2.Down; - case Direction2.Down: - return fortyFiveDegrees ? Direction2.DownLeft : Direction2.Left; - case Direction2.Left: - return fortyFiveDegrees ? Direction2.UpLeft : Direction2.Up; - case Direction2.UpRight: - return fortyFiveDegrees ? Direction2.Right : Direction2.DownRight; - case Direction2.DownRight: - return fortyFiveDegrees ? Direction2.Down : Direction2.DownLeft; - case Direction2.DownLeft: - return fortyFiveDegrees ? Direction2.Left : Direction2.UpLeft; - case Direction2.UpLeft: - return fortyFiveDegrees ? Direction2.Up : Direction2.UpRight; - default: - return Direction2.None; - } + return Clockwise[(ClockwiseLookup[dir] + (fortyFiveDegrees ? 1 : 2)) % Clockwise.Length]; } /// @@ -219,26 +203,10 @@ namespace MLEM.Misc { /// Whether to rotate by 45 degrees. If this is false, the rotation is 90 degrees instead. /// The rotated direction public static Direction2 RotateCcw(this Direction2 dir, bool fortyFiveDegrees = false) { - switch (dir) { - case Direction2.Up: - return fortyFiveDegrees ? Direction2.UpLeft : Direction2.Left; - case Direction2.Right: - return fortyFiveDegrees ? Direction2.UpRight : Direction2.Up; - case Direction2.Down: - return fortyFiveDegrees ? Direction2.DownRight : Direction2.Right; - case Direction2.Left: - return fortyFiveDegrees ? Direction2.DownLeft : Direction2.Down; - case Direction2.UpRight: - return fortyFiveDegrees ? Direction2.Up : Direction2.UpLeft; - case Direction2.DownRight: - return fortyFiveDegrees ? Direction2.Right : Direction2.UpRight; - case Direction2.DownLeft: - return fortyFiveDegrees ? Direction2.Down : Direction2.DownRight; - case Direction2.UpLeft: - return fortyFiveDegrees ? Direction2.Left : Direction2.DownLeft; - default: - return Direction2.None; - } + var index = ClockwiseLookup[dir] - (fortyFiveDegrees ? 1 : 2); + if (index < 0) + index += Clockwise.Length; + return Clockwise[index % Clockwise.Length]; } /// @@ -269,5 +237,19 @@ namespace MLEM.Misc { return offset.Y > 0 ? Direction2.Down : Direction2.Up; } + /// + /// Rotates the given direction by a given reference direction + /// + /// The direction to rotate + /// The direction to rotate by + /// The direction to use as the default direction + /// The direction, rotated by the reference direction + public static Direction2 RotateBy(this Direction2 dir, Direction2 reference, Direction2 start = Direction2.Up) { + var diff = ClockwiseLookup[reference] - ClockwiseLookup[start]; + if (diff < 0) + diff += Clockwise.Length; + return Clockwise[(ClockwiseLookup[dir] + diff) % Clockwise.Length]; + } + } } \ No newline at end of file diff --git a/Tests/DirectionTests.cs b/Tests/DirectionTests.cs index 2331fa1..56240ac 100644 --- a/Tests/DirectionTests.cs +++ b/Tests/DirectionTests.cs @@ -1,22 +1,64 @@ using Microsoft.Xna.Framework; using MLEM.Misc; using NUnit.Framework; +using static MLEM.Misc.Direction2; namespace Tests { public class DirectionTests { [Test] public void TestDirections() { - Assert.AreEqual(new Vector2(0.5F, 0.5F).ToDirection(), Direction2.DownRight); - Assert.AreEqual(new Vector2(0.25F, 0.5F).ToDirection(), Direction2.DownRight); - Assert.AreEqual(new Vector2(0.15F, 0.5F).ToDirection(), Direction2.Down); + Assert.AreEqual(new Vector2(0.5F, 0.5F).ToDirection(), DownRight); + Assert.AreEqual(new Vector2(0.25F, 0.5F).ToDirection(), DownRight); + Assert.AreEqual(new Vector2(0.15F, 0.5F).ToDirection(), Down); } [Test] public void Test90Directions() { - Assert.AreEqual(new Vector2(0.75F, 0.5F).To90Direction(), Direction2.Right); - Assert.AreEqual(new Vector2(0.5F, 0.5F).To90Direction(), Direction2.Down); - Assert.AreEqual(new Vector2(0.25F, 0.5F).To90Direction(), Direction2.Down); + Assert.AreEqual(new Vector2(0.75F, 0.5F).To90Direction(), Right); + Assert.AreEqual(new Vector2(0.5F, 0.5F).To90Direction(), Down); + Assert.AreEqual(new Vector2(0.25F, 0.5F).To90Direction(), Down); + } + + [Test] + public void TestRotations() { + // rotate cw + Assert.AreEqual(Up.RotateCw(), Right); + Assert.AreEqual(Up.RotateCw(true), UpRight); + Assert.AreEqual(Left.RotateCw(), Up); + Assert.AreEqual(UpLeft.RotateCw(), UpRight); + + // rotate ccw + Assert.AreEqual(Up.RotateCcw(), Left); + Assert.AreEqual(Up.RotateCcw(true), UpLeft); + Assert.AreEqual(Left.RotateCcw(), Down); + Assert.AreEqual(UpLeft.RotateCcw(), DownLeft); + + // rotate 360 degrees + foreach (var dir in Direction2Helper.AllExceptNone) { + Assert.AreEqual(RotateMultipleTimes(dir, true, false, 4), dir); + Assert.AreEqual(RotateMultipleTimes(dir, true, true, 8), dir); + Assert.AreEqual(RotateMultipleTimes(dir, false, false, 4), dir); + Assert.AreEqual(RotateMultipleTimes(dir, false, true, 8), dir); + } + + // rotate by with start Up + Assert.AreEqual(Right.RotateBy(Right), Down); + Assert.AreEqual(Right.RotateBy(Down), Left); + Assert.AreEqual(Right.RotateBy(Left), Up); + Assert.AreEqual(Right.RotateBy(Up), Right); + + // rotate by with start Left + Assert.AreEqual(Up.RotateBy(Right, Left), Down); + Assert.AreEqual(Up.RotateBy(Down, Left), Left); + Assert.AreEqual(Up.RotateBy(Left, Left), Up); + Assert.AreEqual(Up.RotateBy(Up, Left), Right); + } + + private static Direction2 RotateMultipleTimes(Direction2 dir, bool clockwise, bool fortyFiveDegrees, int times) { + for (var i = 0; i < times; i++) + dir = clockwise ? dir.RotateCw(fortyFiveDegrees) : dir.RotateCcw(fortyFiveDegrees); + return dir; } }