OpenRA Coordinate System - guidebee/OpenRA GitHub Wiki
General/OpenRA Coordinate System
OpenRA uses multiple coordinate systems to represent positions in the game world. This document explains the different coordinate types and how they relate to each other.
Coordinate Types
OpenRA has several coordinate types that serve different purposes:
1. World Position (WPos)
WPos
represents a precise 3D position in the game world.
- Components: X, Y, Z as integers
- Units: The world is measured in "world units" (approximately 1/24th of a cell)
- Usage: Used for exact positioning of units, buildings, and other game entities
- Example:
new WPos(1024, 2048, 0)
represents a position at x=1024, y=2048, z=0
2. Cell Position (CPos)
CPos
represents a cell on the game map grid, the fundamental unit of the map.
- Components: X, Y coordinates and a Layer value
- Storage: Packed into a 32-bit integer (12 bits for X, 12 bits for Y, 8 bits for Layer)
- Range: X and Y can range from -2048 to 2047
- Layer: Represents different map layers (0 is ground, other values for bridges, tunnels, etc.)
- Example:
new CPos(5, 10)
represents the cell at x=5, y=10 on the ground layer
3. Map Position (MPos)
MPos
represents a position in the map's internal coordinate system.
- Components: U, V coordinates
- Usage: Used for internal map operations and storage
- Conversion: Can be converted to/from CPos using appropriate transformation
4. Projected Position (PPos)
PPos
represents a projected map position.
- Components: U, V coordinates
- Usage: Used for projection operations, particularly for handling terrain height
- Relationship: Closely related to MPos, but accounts for terrain elevation
Coordinate Transformations
Between CPos and MPos
For rectangular maps:
- CPos(x,y) directly maps to MPos(u,v) where u=x and v=y
For isometric maps:
-
From CPos to MPos:
u = (x - y) / 2 v = x + y
-
From MPos to CPos:
x = (v + 2u) / 2 y = (v - 2u) / 2
With special handling for odd v values
Between WPos and CPos
For rectangular maps:
-
From WPos to CPos:
x = pos.X / 1024 y = pos.Y / 1024
-
From CPos to WPos (center of cell):
x = 1024 * cell.X + 512 y = 1024 * cell.Y + 512 z = height value for the cell
For isometric maps:
- The transformations are more complex due to the isometric projection
- Cell size along the diagonal is 724 units (512 * sqrt(2))
Grid Types
OpenRA supports two main grid types:
-
Rectangular (
MapGridType.Rectangular
):- Traditional grid where cells are square
- Cell size is 1024x1024 world units
- Straightforward coordinate transformations
-
Rectangular Isometric (
MapGridType.RectangularIsometric
):- Isometric grid where cells appear diamond-shaped
- More complex coordinate transformations
- Diagonal cell size is 1448 units (2 * 724)
Terrain Height
- Terrain height is stored in a
Height
layer in the map - Height is measured in steps, where each step is 724 units (isometric) or 512 units (rectangular)
- The
Ramp
layer in the map stores information about terrain slopes
Screen Projection
The WorldRenderer
class handles projection from world coordinates to screen coordinates:
ScreenPosition(WPos)
: Converts a world position to screen coordinatesProjectedPosition(int2)
: Converts screen coordinates to a world position
Practical Usage
When working with the OpenRA coordinate system:
-
Use the appropriate coordinate type for your use case:
WPos
for precise world positioningCPos
for cell-based operationsMPos
/PPos
for map operations
-
Use the provided conversion methods when transitioning between coordinate types
-
Be aware of the grid type (rectangular vs. isometric) as it affects coordinate transformations
-
When dealing with terrain height, remember that it affects the Z component of world positions
Example Conversions
// Get the center of a cell
WPos cellCenter = map.CenterOfCell(new CPos(10, 15));
// Find the cell containing a world position
CPos cell = map.CellContaining(new WPos(5120, 7680, 0));
// Convert between CPos and MPos
MPos mapPos = cell.ToMPos(map.Grid.Type);
CPos cellPos = mapPos.ToCPos(map.Grid.Type);
Conclusion
OpenRA's coordinate system is designed to efficiently handle both rectangular and isometric game maps while supporting features like terrain height, multiple map layers, and proper screen projection. Understanding the different coordinate types and their relationships is essential for modding and development work with the OpenRA engine.