From 9ef77cb4282ba7fae2a4a6abe942b7bee380bf4f Mon Sep 17 00:00:00 2001 From: ephphatha Date: Sun, 29 Aug 2021 21:43:58 +1000 Subject: [PATCH] Use scoped enum for Direction16. Allows renaming the members to share names with Direction members when representing the same conceptual direction. --- Source/missiles.cpp | 20 +++++------ Source/missiles.h | 75 ++++++++++++++++++++++---------------- test/missiles_test.cpp | 82 +++++++++++++++++++++--------------------- 3 files changed, 96 insertions(+), 81 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index c03a52e0b..8f15f8371 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -109,7 +109,7 @@ Monster *FindClosest(Point source, int rad) constexpr Direction16 Direction16Flip(Direction16 x, Direction16 pivot) { - unsigned ret = (2 * pivot + 16 - x) % 16; + std::underlying_type_t ret = (2 * static_cast>(pivot) + 16 - static_cast>(x)) % 16; return static_cast(ret); } @@ -1023,22 +1023,22 @@ Direction16 GetDirection16(Point p1, Point p2) flipMedian = true; } - Direction16 ret = DIR16_S; + Direction16 ret = Direction16::South; if (3 * absolute.deltaX <= (absolute.deltaY * 2)) { // mx/my <= 2/3, approximation of tan(33.75) if (5 * absolute.deltaX < absolute.deltaY) // mx/my < 0.2, approximation of tan(11.25) - ret = DIR16_SW; + ret = Direction16::SouthWest; else - ret = DIR16_Sw; + ret = Direction16::South_SouthWest; } - Direction16 medianPivot = DIR16_S; + Direction16 medianPivot = Direction16::South; if (flipY) { - ret = Direction16Flip(ret, DIR16_SW); - medianPivot = Direction16Flip(medianPivot, DIR16_SW); + ret = Direction16Flip(ret, Direction16::SouthWest); + medianPivot = Direction16Flip(medianPivot, Direction16::SouthWest); } if (flipX) { - ret = Direction16Flip(ret, DIR16_SE); - medianPivot = Direction16Flip(medianPivot, DIR16_SE); + ret = Direction16Flip(ret, Direction16::SouthEast); + medianPivot = Direction16Flip(medianPivot, Direction16::SouthEast); } if (flipMedian) ret = Direction16Flip(ret, medianPivot); @@ -1853,7 +1853,7 @@ void AddArrow(Missile &missile, Point dst, Direction midir) } } UpdateMissileVelocity(missile, dst, av); - missile._miAnimFrame = GetDirection16(missile.position.start, dst) + 1; + missile._miAnimFrame = static_cast(GetDirection16(missile.position.start, dst)) + 1; missile._mirange = 256; } diff --git a/Source/missiles.h b/Source/missiles.h index 325022fc5..f8b65f7b6 100644 --- a/Source/missiles.h +++ b/Source/missiles.h @@ -57,34 +57,39 @@ struct MissilePosition { } }; -/* - * W sW SW Sw S - * ^ - * nW | Se - * | - * NW ------+-----> SE - * | - * Nw | sE - * | - * N Ne NE nE E +/** + * Represent a more fine-grained direction than the 8 value Direction enum. + * + * This is used when rendering projectiles like arrows which have additional sprites for "half-winds" on a 16-point compass. + * The sprite sheets are typically 0-indexed and use the following layout (relative to the screen projection) + * + * W WSW SW SSW S + * ^ + * WNW | SSE + * | + * NW -------+------> SE + * | + * NNW | ESE + * | + * N NNE NE ENE E */ -enum Direction16 { - DIR16_S, - DIR16_Sw, - DIR16_SW, - DIR16_sW, - DIR16_W, - DIR16_nW, - DIR16_NW, - DIR16_Nw, - DIR16_N, - DIR16_Ne, - DIR16_NE, - DIR16_nE, - DIR16_E, - DIR16_sE, - DIR16_SE, - DIR16_Se, +enum class Direction16 { + South, + South_SouthWest, + SouthWest, + West_SouthWest, + West, + West_NorthWest, + NorthWest, + North_NorthWest, + North, + North_NorthEast, + NorthEast, + East_NorthEast, + East, + East_SouthEast, + SouthEast, + South_SouthEast, }; struct Missile { @@ -144,14 +149,14 @@ bool MonsterTrapHit(int m, int mindam, int maxdam, int dist, missile_id t, bool bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, missile_id mtype, bool shift, int earflag, bool *blocked); /** - * @brief Sets the missile sprite to represent the direction of travel + * @brief Sets the missile sprite to the given sheet frame * @param missile this object - * @param dir Sprite frame representing the desired facing + * @param dir Sprite frame, typically representing a direction but there are some exceptions (arrows being 1 indexed, directionless spells) */ void SetMissDir(Missile &missile, int dir); /** - * @brief Overload to convert a Direction value to the appropriate sprite frame + * @brief Sets the sprite for this missile so it matches the given Direction * @param missile this object * @param dir Desired facing */ @@ -160,6 +165,16 @@ inline void SetMissDir(Missile &missile, Direction dir) SetMissDir(missile, static_cast(dir)); } +/** + * @brief Sets the sprite for this missile so it matches the given Direction16 + * @param missile this object + * @param dir Desired facing at a 22.8125 degree resolution +*/ +inline void SetMissDir(Missile &missile, Direction16 dir) +{ + SetMissDir(missile, static_cast(dir)); +} + void InitMissiles(); void AddHiveExplosion(Missile &missile, Point dst, Direction midir); void AddFireRune(Missile &missile, Point dst, Direction midir); diff --git a/test/missiles_test.cpp b/test/missiles_test.cpp index d28988c3a..fa716b486 100644 --- a/test/missiles_test.cpp +++ b/test/missiles_test.cpp @@ -45,47 +45,47 @@ TEST(Missiles, GetDirection8) TEST(Missiles, GetDirection16) { - EXPECT_EQ(Direction16::DIR16_S, GetDirection16({ 0, 0 }, { 15, 15 })); - EXPECT_EQ(Direction16::DIR16_SW, GetDirection16({ 0, 0 }, { 0, 15 })); - EXPECT_EQ(Direction16::DIR16_Sw, GetDirection16({ 0, 0 }, { 8, 15 })); - EXPECT_EQ(Direction16::DIR16_S, GetDirection16({ 0, 0 }, { 8, 8 })); - EXPECT_EQ(Direction16::DIR16_Se, GetDirection16({ 0, 0 }, { 15, 8 })); - EXPECT_EQ(Direction16::DIR16_Se, GetDirection16({ 0, 0 }, { 15, 7 })); - EXPECT_EQ(Direction16::DIR16_Se, GetDirection16({ 0, 0 }, { 11, 7 })); - EXPECT_EQ(Direction16::DIR16_S, GetDirection16({ 0, 0 }, { 8, 11 })); - EXPECT_EQ(Direction16::DIR16_N, GetDirection16({ 15, 15 }, { 0, 0 })); - EXPECT_EQ(Direction16::DIR16_NE, GetDirection16({ 0, 15 }, { 0, 0 })); - EXPECT_EQ(Direction16::DIR16_Ne, GetDirection16({ 8, 15 }, { 0, 0 })); - EXPECT_EQ(Direction16::DIR16_N, GetDirection16({ 8, 8 }, { 0, 0 })); - EXPECT_EQ(Direction16::DIR16_Nw, GetDirection16({ 15, 8 }, { 0, 0 })); - EXPECT_EQ(Direction16::DIR16_Nw, GetDirection16({ 15, 7 }, { 0, 0 })); - EXPECT_EQ(Direction16::DIR16_Nw, GetDirection16({ 11, 7 }, { 0, 0 })); - EXPECT_EQ(Direction16::DIR16_N, GetDirection16({ 8, 11 }, { 0, 0 })); - EXPECT_EQ(Direction16::DIR16_E, GetDirection16({ 0, 15 }, { 15, 0 })); - EXPECT_EQ(Direction16::DIR16_SE, GetDirection16({ 0, 0 }, { 15, 0 })); - EXPECT_EQ(Direction16::DIR16_sE, GetDirection16({ 0, 8 }, { 15, 0 })); - EXPECT_EQ(Direction16::DIR16_E, GetDirection16({ 0, 8 }, { 8, 0 })); - EXPECT_EQ(Direction16::DIR16_nE, GetDirection16({ 0, 15 }, { 8, 0 })); - EXPECT_EQ(Direction16::DIR16_nE, GetDirection16({ 0, 15 }, { 7, 0 })); - EXPECT_EQ(Direction16::DIR16_nE, GetDirection16({ 0, 11 }, { 7, 0 })); - EXPECT_EQ(Direction16::DIR16_E, GetDirection16({ 0, 8 }, { 11, 0 })); + EXPECT_EQ(Direction16::South, GetDirection16({ 0, 0 }, { 15, 15 })); + EXPECT_EQ(Direction16::SouthWest, GetDirection16({ 0, 0 }, { 0, 15 })); + EXPECT_EQ(Direction16::South_SouthWest, GetDirection16({ 0, 0 }, { 8, 15 })); + EXPECT_EQ(Direction16::South, GetDirection16({ 0, 0 }, { 8, 8 })); + EXPECT_EQ(Direction16::South_SouthEast, GetDirection16({ 0, 0 }, { 15, 8 })); + EXPECT_EQ(Direction16::South_SouthEast, GetDirection16({ 0, 0 }, { 15, 7 })); + EXPECT_EQ(Direction16::South_SouthEast, GetDirection16({ 0, 0 }, { 11, 7 })); + EXPECT_EQ(Direction16::South, GetDirection16({ 0, 0 }, { 8, 11 })); + EXPECT_EQ(Direction16::North, GetDirection16({ 15, 15 }, { 0, 0 })); + EXPECT_EQ(Direction16::NorthEast, GetDirection16({ 0, 15 }, { 0, 0 })); + EXPECT_EQ(Direction16::North_NorthEast, GetDirection16({ 8, 15 }, { 0, 0 })); + EXPECT_EQ(Direction16::North, GetDirection16({ 8, 8 }, { 0, 0 })); + EXPECT_EQ(Direction16::North_NorthWest, GetDirection16({ 15, 8 }, { 0, 0 })); + EXPECT_EQ(Direction16::North_NorthWest, GetDirection16({ 15, 7 }, { 0, 0 })); + EXPECT_EQ(Direction16::North_NorthWest, GetDirection16({ 11, 7 }, { 0, 0 })); + EXPECT_EQ(Direction16::North, GetDirection16({ 8, 11 }, { 0, 0 })); + EXPECT_EQ(Direction16::East, GetDirection16({ 0, 15 }, { 15, 0 })); + EXPECT_EQ(Direction16::SouthEast, GetDirection16({ 0, 0 }, { 15, 0 })); + EXPECT_EQ(Direction16::East_SouthEast, GetDirection16({ 0, 8 }, { 15, 0 })); + EXPECT_EQ(Direction16::East, GetDirection16({ 0, 8 }, { 8, 0 })); + EXPECT_EQ(Direction16::East_NorthEast, GetDirection16({ 0, 15 }, { 8, 0 })); + EXPECT_EQ(Direction16::East_NorthEast, GetDirection16({ 0, 15 }, { 7, 0 })); + EXPECT_EQ(Direction16::East_NorthEast, GetDirection16({ 0, 11 }, { 7, 0 })); + EXPECT_EQ(Direction16::East, GetDirection16({ 0, 8 }, { 11, 0 })); - EXPECT_EQ(Direction16::DIR16_S, GetDirection16({ 2, 2 }, { 3, 3 })); - EXPECT_EQ(Direction16::DIR16_Sw, GetDirection16({ 2, 2 }, { 3, 4 })); - EXPECT_EQ(Direction16::DIR16_SW, GetDirection16({ 2, 2 }, { 2, 4 })); - EXPECT_EQ(Direction16::DIR16_sW, GetDirection16({ 2, 2 }, { 1, 4 })); - EXPECT_EQ(Direction16::DIR16_W, GetDirection16({ 2, 2 }, { 1, 3 })); - EXPECT_EQ(Direction16::DIR16_nW, GetDirection16({ 2, 2 }, { 0, 3 })); - EXPECT_EQ(Direction16::DIR16_NW, GetDirection16({ 2, 2 }, { 0, 2 })); - EXPECT_EQ(Direction16::DIR16_Nw, GetDirection16({ 2, 2 }, { 0, 1 })); - EXPECT_EQ(Direction16::DIR16_N, GetDirection16({ 2, 2 }, { 1, 1 })); - EXPECT_EQ(Direction16::DIR16_Ne, GetDirection16({ 2, 2 }, { 1, 0 })); - EXPECT_EQ(Direction16::DIR16_NE, GetDirection16({ 2, 2 }, { 2, 0 })); - EXPECT_EQ(Direction16::DIR16_nE, GetDirection16({ 2, 2 }, { 3, 0 })); - EXPECT_EQ(Direction16::DIR16_E, GetDirection16({ 2, 2 }, { 3, 1 })); - EXPECT_EQ(Direction16::DIR16_sE, GetDirection16({ 2, 2 }, { 4, 1 })); - EXPECT_EQ(Direction16::DIR16_SE, GetDirection16({ 2, 2 }, { 4, 2 })); - EXPECT_EQ(Direction16::DIR16_Se, GetDirection16({ 2, 2 }, { 4, 3 })); + EXPECT_EQ(Direction16::South, GetDirection16({ 2, 2 }, { 3, 3 })); + EXPECT_EQ(Direction16::South_SouthWest, GetDirection16({ 2, 2 }, { 3, 4 })); + EXPECT_EQ(Direction16::SouthWest, GetDirection16({ 2, 2 }, { 2, 4 })); + EXPECT_EQ(Direction16::West_SouthWest, GetDirection16({ 2, 2 }, { 1, 4 })); + EXPECT_EQ(Direction16::West, GetDirection16({ 2, 2 }, { 1, 3 })); + EXPECT_EQ(Direction16::West_NorthWest, GetDirection16({ 2, 2 }, { 0, 3 })); + EXPECT_EQ(Direction16::NorthWest, GetDirection16({ 2, 2 }, { 0, 2 })); + EXPECT_EQ(Direction16::North_NorthWest, GetDirection16({ 2, 2 }, { 0, 1 })); + EXPECT_EQ(Direction16::North, GetDirection16({ 2, 2 }, { 1, 1 })); + EXPECT_EQ(Direction16::North_NorthEast, GetDirection16({ 2, 2 }, { 1, 0 })); + EXPECT_EQ(Direction16::NorthEast, GetDirection16({ 2, 2 }, { 2, 0 })); + EXPECT_EQ(Direction16::East_NorthEast, GetDirection16({ 2, 2 }, { 3, 0 })); + EXPECT_EQ(Direction16::East, GetDirection16({ 2, 2 }, { 3, 1 })); + EXPECT_EQ(Direction16::East_SouthEast, GetDirection16({ 2, 2 }, { 4, 1 })); + EXPECT_EQ(Direction16::SouthEast, GetDirection16({ 2, 2 }, { 4, 2 })); + EXPECT_EQ(Direction16::South_SouthEast, GetDirection16({ 2, 2 }, { 4, 3 })); - EXPECT_EQ(Direction16::DIR16_Sw, GetDirection16({ 0, 0 }, { 0, 0 })) << "GetDirection16 is expected to default to DIR16_Sw when the points occupy the same tile"; + EXPECT_EQ(Direction16::South_SouthWest, GetDirection16({ 0, 0 }, { 0, 0 })) << "GetDirection16 is expected to default to Direction16::South_SouthWest when the points occupy the same tile"; }