Gondwana Game Engine Development (master) - 2.6.1
Gondwana is a cross-platform 2.5D game and rendering engine written in C#/.NET 8. It provides fine-grained control over rendering, timing, and scene composition, with built-in support for parallax, z-ordering, pixel overhang, collision detection, and particle effects. Gondwana targets desktop and web platforms using SkiaSharp for graphics and pluggable audio backends for desktop and browser targets.
Loading...
Searching...
No Matches
IsometricAxialCoordinates.cs
1using System.Drawing;
3
5
12internal sealed class IsometricAxialCoordinates : ISceneLayerCoordinates
13{
14 // Precompute half sizes repeatedly used
15 private static void WH(SceneLayer m, out int W, out int H, out float halfW, out float halfH)
16 {
17 W = m.TileWidth;
18 H = m.TileHeight;
19 halfW = W * 0.5f;
20 halfH = H * 0.5f;
21 }
22
29 public Point GetAnchorPixelAtSceneLayerCoordinates(SceneLayer sceneLayer, PointF gp)
30 {
31 WH(sceneLayer, out int W, out _, out float halfW, out float halfH);
32
33 int originX = sceneLayer.OriginPx.X;
34 int originY = sceneLayer.OriginPx.Y;
35
36 float px = -originX + gp.X * W + gp.Y * halfW;
37 float py = -originY + gp.Y * halfH;
38
39 return new Point((int)Math.Floor(px), (int)Math.Floor(py));
40 }
41
48 public PointF GetSceneLayerCoordinatesAtPixel(SceneLayer sceneLayer, PointF pixelPt)
49 {
50 WH(sceneLayer, out int W, out _, out float halfW, out float halfH);
51
52 int originX = sceneLayer.OriginPx.X;
53 int originY = sceneLayer.OriginPx.Y;
54
55 float gyF = (pixelPt.Y + originY) / halfH;
56 float gxF = (pixelPt.X + originX - gyF * halfW) / W;
57
58 return new PointF(gxF, gyF);
59 }
60
68 public List<SceneLayerTile> GetSceneLayerTilesInPixelRange(SceneLayer sceneLayer, Rectangle worldPixelRange, bool includeOverhang)
69 {
70 var result = new List<SceneLayerTile>();
71 WH(sceneLayer, out _, out _, out _, out _);
72 var candidateRange = TileBounds.GetTransformedTileCandidateRange(sceneLayer, worldPixelRange, includeOverhang);
73
74 // Corner → coarse grid bounds (continuous)
75 var ul = GetSceneLayerCoordinatesAtPixel(sceneLayer, new PointF(candidateRange.Left, candidateRange.Top));
76 var ur = GetSceneLayerCoordinatesAtPixel(sceneLayer, new PointF(candidateRange.Right, candidateRange.Top));
77 var ll = GetSceneLayerCoordinatesAtPixel(sceneLayer, new PointF(candidateRange.Left, candidateRange.Bottom));
78 var lr = GetSceneLayerCoordinatesAtPixel(sceneLayer, new PointF(candidateRange.Right, candidateRange.Bottom));
79
80 int minX = (int)System.Math.Floor(System.Math.Min(System.Math.Min(ul.X, ur.X), System.Math.Min(ll.X, lr.X))) - 2;
81 int maxX = (int)System.Math.Ceiling(System.Math.Max(System.Math.Max(ul.X, ur.X), System.Math.Max(ll.X, lr.X))) + 2;
82 int minY = (int)System.Math.Floor(System.Math.Min(System.Math.Min(ul.Y, ur.Y), System.Math.Min(ll.Y, lr.Y))) - 2;
83 int maxY = (int)System.Math.Ceiling(System.Math.Max(System.Math.Max(ul.Y, ur.Y), System.Math.Max(ll.Y, lr.Y))) + 2;
84
85 // Clamp to layer bounds (no wrapping)
86 int cols = sceneLayer.GridColumnCount;
87 int rows = sceneLayer.GridRowCount;
88
89 int xStart = System.Math.Max(minX, 0);
90 int xEnd = System.Math.Min(maxX, cols - 1);
91 int yStart = System.Math.Max(minY, 0);
92 int yEnd = System.Math.Min(maxY, rows - 1);
93 if (xStart > xEnd || yStart > yEnd) return result;
94
95 for (int y = yStart; y <= yEnd; y++)
96 {
97 for (int x = xStart; x <= xEnd; x++)
98 {
99 var gp = sceneLayer[x, y];
100 if (gp == null) continue;
101
102 var r = GetPixelRangeForTile(gp, includeOverhang);
103 if (r.IntersectsWith(worldPixelRange)) result.Add(gp);
104 }
105 }
106 return result;
107 }
108
115 public Rectangle GetPixelRangeForTile(Tile tile, bool includeOverhang)
116 {
117 WH(tile.SceneLayer, out int W, out int H, out float halfW, out _);
118
119 // Top vertex of the diamond
120 var top = GetAnchorPixelAtSceneLayerCoordinates(tile.SceneLayer, tile.SceneLayerCoordinates);
121
122 // Diamond fits exactly in W×H box whose top-left is (top.X - W/2, top.Y)
123 var rect = new Rectangle(top.X - (int)halfW, top.Y, W, H);
124 return TileBounds.ApplyTileGeometry(rect, tile, includeOverhang);
125 }
126
133 public Rectangle GetPixelRangeForTileList(List<Tile> tileList, bool includeOverhang)
134 {
135 Rectangle ret = Rectangle.Empty;
136 foreach (var t in tileList)
137 {
138 var r = GetPixelRangeForTile(t, includeOverhang);
139 ret = ret.IsEmpty ? r : Rectangle.Union(ret, r);
140 }
141 return ret;
142 }
143
150 public SceneLayerTile GetAdjacentSceneLayerTile(SceneLayerTile gp, CardinalDirections dir)
151 {
152 var m = gp.SceneLayer; int x = gp.GridCoordinatesAbs.X; int y = gp.GridCoordinatesAbs.Y;
153 // Square-like adjacency over the rectangular index space
154 return dir switch
155 {
156 CardinalDirections.N => m.ResolveWrappedTile(x, y - 1),
157 CardinalDirections.S => m.ResolveWrappedTile(x, y + 1),
158 CardinalDirections.E => m.ResolveWrappedTile(x + 1, y),
159 CardinalDirections.W => m.ResolveWrappedTile(x - 1, y),
160 CardinalDirections.NE => m.ResolveWrappedTile(x + 1, y - 1),
161 CardinalDirections.NW => m.ResolveWrappedTile(x - 1, y - 1),
162 CardinalDirections.SE => m.ResolveWrappedTile(x + 1, y + 1),
163 CardinalDirections.SW => m.ResolveWrappedTile(x - 1, y + 1),
164 _ => null
165 };
166 }
167
174 public Point[] GetPolygonPts(Tile tile, bool includeOverhang)
175 {
176 WH(tile.SceneLayer, out int W, out int H, out _, out _);
177 var top = GetAnchorPixelAtSceneLayerCoordinates(tile.SceneLayer, tile.SceneLayerCoordinates);
178 var oh = includeOverhang ? tile.Overhang : Spacing.None;
179
180 // Diamond vertices (top, right, bottom, left)
181 return new[]
182 {
183 new Point(top.X, top.Y - oh.Top),
184 new Point(top.X + W/2 + oh.Right, top.Y + H/2),
185 new Point(top.X, top.Y + H + oh.Bottom),
186 new Point(top.X - W/2 - oh.Left, top.Y + H/2)
187 };
188 }
189
197 public PointF FindEquivalentSceneLayerCoordinates(PointF valColRow, int xUpperBound, int yUpperBound)
198 {
199 // For now, keep the simple torus mapping; if you prefer no wrap, clamp upstream.
200 float modX = valColRow.X % (xUpperBound + 1);
201 float modY = valColRow.Y % (yUpperBound + 1);
202 if (modX < 0) modX += xUpperBound + 1;
203 if (modY < 0) modY += yUpperBound + 1;
204 return new PointF(modX, modY);
205 }
206}
Point GridCoordinatesAbs
Gets the absolute grid coordinates of this tile within its parent scene layer as integer values.
override SceneLayer SceneLayer
Gets the parent scene layer that contains this tile.
Point OriginPx
Gets or sets the world-space pixel origin of this layer's (0,0) tile position.
int GridRowCount
Gets the number of rows (tiles high) in this layer's grid.
int TileHeight
Gets or sets the height of each tile in this layer, measured in pixels.
int GridColumnCount
Gets the number of columns (tiles wide) in this layer's grid.
int TileWidth
Gets or sets the width of each tile in this layer, measured in pixels.
CardinalDirections
Represents the eight cardinal and intercardinal directions of the compass.
@ Rectangle
Particles are spawned uniformly within a rectangular area. This is the default distribution.
record struct Spacing([property:JsonProperty("left")] int Left, [property:JsonProperty("top")] int Top, [property:JsonProperty("right")] int Right, [property:JsonProperty("bottom")] int Bottom)
Represents dimensions in pixels when spacing Tilesheets.
Definition Spacing.cs:12