OpenRCT2/src/openrct2/world/Location.hpp

386 lines
8.2 KiB
C++
Raw Normal View History

/*****************************************************************************
* Copyright (c) 2014-2019 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include "../common.h"
2019-01-02 12:59:37 +01:00
#include <algorithm>
2018-06-22 23:17:03 +02:00
#define LOCATION_NULL ((int16_t)(uint16_t)0x8000)
#define RCT_XY8_UNDEFINED 0xFFFF
2018-06-22 23:17:03 +02:00
#define MakeXY16(x, y) \
{ \
(int16_t)(x), (int16_t)(y) \
}
#pragma pack(push, 1)
2018-06-22 23:17:03 +02:00
struct LocationXY8
{
union
{
struct
{
uint8_t x, y;
};
uint16_t xy;
};
};
assert_struct_size(LocationXY8, 2);
2018-06-22 23:17:03 +02:00
struct sLocationXY8
{
int8_t x, y;
};
assert_struct_size(sLocationXY8, 2);
2018-06-22 23:17:03 +02:00
struct LocationXY16
{
int16_t x, y;
};
assert_struct_size(LocationXY16, 4);
2018-06-22 23:17:03 +02:00
struct LocationXYZ16
{
int16_t x, y, z;
};
assert_struct_size(LocationXYZ16, 6);
#pragma pack(pop)
constexpr int32_t COORDS_NULL = -1;
struct ScreenCoordsXY
{
int32_t x = 0;
int32_t y = 0;
ScreenCoordsXY() = default;
constexpr ScreenCoordsXY(int32_t _x, int32_t _y)
: x(_x)
, y(_y)
{
}
const ScreenCoordsXY operator-(const ScreenCoordsXY& rhs) const
{
2019-10-21 04:44:26 +02:00
return { x - rhs.x, y - rhs.y };
}
};
/**
* Tile coordinates use 1 x/y increment per tile and 1 z increment per step.
* Regular ('big', 'sprite') coordinates use 32 x/y increments per tile and 8 z increments per step.
*/
struct CoordsXY
{
2019-01-02 12:59:37 +01:00
int32_t x = 0;
int32_t y = 0;
CoordsXY() = default;
constexpr CoordsXY(int32_t _x, int32_t _y)
: x(_x)
, y(_y)
{
}
CoordsXY& operator+=(const CoordsXY rhs)
{
x += rhs.x;
y += rhs.y;
return *this;
}
CoordsXY& operator-=(const CoordsXY rhs)
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
2019-08-10 09:17:47 +02:00
const CoordsXY operator+(const CoordsXY& rhs) const
{
return { x + rhs.x, y + rhs.y };
2019-08-10 09:17:47 +02:00
}
const CoordsXY operator-(const CoordsXY& rhs) const
{
return { x - rhs.x, y - rhs.y };
2019-08-10 09:17:47 +02:00
}
CoordsXY Rotate(int32_t direction) const
{
CoordsXY rotatedCoords;
switch (direction & 3)
{
default:
case 0:
rotatedCoords.x = x;
rotatedCoords.y = y;
break;
case 1:
rotatedCoords.x = y;
rotatedCoords.y = -x;
break;
case 2:
rotatedCoords.x = -x;
rotatedCoords.y = -y;
break;
case 3:
rotatedCoords.x = -y;
rotatedCoords.y = x;
break;
}
return rotatedCoords;
}
};
struct TileCoordsXY
{
TileCoordsXY() = default;
2019-11-01 02:07:14 +01:00
constexpr TileCoordsXY(int32_t x_, int32_t y_)
2018-06-22 23:17:03 +02:00
: x(x_)
, y(y_)
{
}
explicit TileCoordsXY(CoordsXY c)
: x(c.x / 32)
, y(c.y / 32)
{
}
TileCoordsXY& operator+=(const TileCoordsXY rhs)
{
x += rhs.x;
y += rhs.y;
return *this;
}
TileCoordsXY& operator-=(const TileCoordsXY rhs)
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
TileCoordsXY Rotate(int32_t direction)
{
TileCoordsXY rotatedCoords;
switch (direction & 3)
{
default:
case 0:
rotatedCoords.x = x;
rotatedCoords.y = y;
break;
case 1:
rotatedCoords.x = y;
rotatedCoords.y = -x;
break;
case 2:
rotatedCoords.x = -x;
rotatedCoords.y = -y;
break;
case 3:
rotatedCoords.x = -y;
rotatedCoords.y = x;
break;
}
return rotatedCoords;
}
int32_t x = 0, y = 0;
};
2019-08-16 19:32:44 +02:00
struct CoordsXYZ : public CoordsXY
{
2019-01-02 12:59:37 +01:00
int32_t z = 0;
CoordsXYZ() = default;
constexpr CoordsXYZ(int32_t _x, int32_t _y, int32_t _z)
2019-08-16 19:32:44 +02:00
: CoordsXY(_x, _y)
2019-01-02 12:59:37 +01:00
, z(_z)
{
}
2019-08-10 09:17:47 +02:00
constexpr CoordsXYZ(CoordsXY c, int32_t _z)
2019-08-16 19:32:44 +02:00
: CoordsXY(c)
2019-08-10 09:17:47 +02:00
, z(_z)
{
}
};
struct TileCoordsXYZ
{
TileCoordsXYZ() = default;
2018-06-22 23:17:03 +02:00
TileCoordsXYZ(int32_t x_, int32_t y_, int32_t z_)
: x(x_)
, y(y_)
, z(z_)
{
}
explicit TileCoordsXYZ(CoordsXY c, int32_t z_)
: x(c.x / 32)
, y(c.y / 32)
, z(z_)
{
}
explicit TileCoordsXYZ(CoordsXYZ c)
: x(c.x / 32)
, y(c.y / 32)
, z(c.z / 8)
{
}
2018-04-18 20:56:09 +02:00
TileCoordsXYZ& operator+=(const TileCoordsXY rhs)
{
x += rhs.x;
y += rhs.y;
return *this;
2018-04-18 20:56:09 +02:00
}
TileCoordsXYZ& operator-=(const TileCoordsXY rhs)
{
x -= rhs.x;
y -= rhs.y;
return *this;
}
bool operator==(const TileCoordsXYZ& other) const
{
return x == other.x && y == other.y && z == other.z;
}
bool operator!=(const TileCoordsXYZ& other) const
{
return !(*this == other);
}
int32_t x = 0, y = 0, z = 0;
};
/**
* Cardinal directions are represented by the Direction type. It has four
* possible values:
* 0 is X-decreasing
* 1 is Y-increasing
* 2 is X-increasing
* 3 is Y-decreasing
* Direction is not used to model up/down, or diagonal directions.
*/
typedef uint8_t Direction;
2019-08-26 11:57:44 +02:00
const Direction INVALID_DIRECTION = 0xFF;
2019-08-26 19:50:37 +02:00
/**
2019-09-01 20:10:27 +02:00
* Array of all valid cardinal directions, to make it easy to write range-based for loops like:
* for (Direction d : ALL_DIRECTIONS)
2019-08-26 19:50:37 +02:00
*/
constexpr Direction ALL_DIRECTIONS[] = { 0, 1, 2, 3 };
/**
* Given a direction, return the direction that points the other way,
* on the same axis.
*/
2019-02-09 22:56:50 +01:00
[[maybe_unused]] static constexpr Direction direction_reverse(Direction dir)
{
return dir ^ 2;
}
[[maybe_unused]] static constexpr bool direction_valid(Direction dir)
{
return dir < 4;
}
/**
2019-09-01 20:10:27 +02:00
* Given a direction, return the next cardinal direction, wrapping around if necessary.
* (TODO: Figure out if this is CW or CCW)
*/
[[maybe_unused]] static constexpr Direction direction_next(Direction dir)
{
return (dir + 1) & 0x03;
}
/**
2019-09-01 20:10:27 +02:00
* Given a direction, return the previous cardinal direction, wrapping around if necessary.
* (TODO: Figure out if this is CW or CCW)
*/
[[maybe_unused]] static constexpr Direction direction_prev(Direction dir)
{
return (dir - 1) & 0x03;
}
2019-08-16 19:32:44 +02:00
struct CoordsXYZD : public CoordsXYZ
{
2019-08-16 19:32:44 +02:00
Direction direction = 0;
CoordsXYZD() = default;
constexpr CoordsXYZD(int32_t _x, int32_t _y, int32_t _z, Direction _d)
: CoordsXYZ(_x, _y, _z)
, direction(_d)
{
}
2018-06-22 23:17:03 +02:00
bool isNull() const
{
return x == COORDS_NULL;
};
};
struct TileCoordsXYZD
{
int32_t x, y, z;
Direction direction;
2018-06-22 23:17:03 +02:00
bool isNull() const
{
return x == COORDS_NULL;
};
};
2019-01-02 12:59:37 +01:00
/**
* Represents a rectangular range of the map using regular coordinates (32 per tile).
*/
struct MapRange
{
CoordsXY LeftTop;
CoordsXY RightBottom;
int32_t GetLeft() const
{
return LeftTop.x;
}
int32_t GetTop() const
{
return LeftTop.y;
}
int32_t GetRight() const
{
return RightBottom.x;
}
int32_t GetBottom() const
{
return RightBottom.y;
}
MapRange()
: MapRange(0, 0, 0, 0)
{
}
MapRange(int32_t left, int32_t top, int32_t right, int32_t bottom)
: LeftTop(left, top)
, RightBottom(right, bottom)
{
}
MapRange Normalise() const
{
auto result = MapRange(
std::min(GetLeft(), GetRight()), std::min(GetTop(), GetBottom()), std::max(GetLeft(), GetRight()),
std::max(GetTop(), GetBottom()));
return result;
}
};