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
ObliqueRightCoordinates.cs
1using System.Drawing;
3
5
23internal sealed class ObliqueRightCoordinates : ISceneLayerCoordinates
24{
32 public Point GetAnchorPixelAtSceneLayerCoordinates(SceneLayer sceneLayer, PointF layerPoint)
33 {
34 GetGeometry(sceneLayer, out _, out int H, out int skewX, out int faceWidth);
35
36 float x = -sceneLayer.OriginPx.X
37 + layerPoint.X * faceWidth
38 + layerPoint.Y * skewX;
39
40 float y = -sceneLayer.OriginPx.Y
41 + layerPoint.Y * H;
42
43 return new Point(
44 (int)Math.Floor(x),
45 (int)Math.Floor(y));
46 }
47
54 public PointF GetSceneLayerCoordinatesAtPixel(SceneLayer sceneLayer, PointF pixelPt)
55 {
56 GetGeometry(sceneLayer, out _, out int H, out int skewX, out int faceWidth);
57
58 float row = (pixelPt.Y + sceneLayer.OriginPx.Y) / H;
59 float col = (pixelPt.X + sceneLayer.OriginPx.X - row * skewX) / faceWidth;
60
61 return new PointF(col, row);
62 }
63
71 public List<SceneLayerTile> GetSceneLayerTilesInPixelRange(
72 SceneLayer sceneLayer,
73 Rectangle worldPixelRange,
74 bool includeOverhang)
75 {
76 var result = new List<SceneLayerTile>();
77 var candidateRange = TileBounds.GetTransformedTileCandidateRange(sceneLayer, worldPixelRange, includeOverhang);
78
79 var upperLeft = GetSceneLayerCoordinatesAtPixel(
80 sceneLayer,
81 new PointF(candidateRange.Left, candidateRange.Top));
82
83 var upperRight = GetSceneLayerCoordinatesAtPixel(
84 sceneLayer,
85 new PointF(candidateRange.Right, candidateRange.Top));
86
87 var lowerLeft = GetSceneLayerCoordinatesAtPixel(
88 sceneLayer,
89 new PointF(candidateRange.Left, candidateRange.Bottom));
90
91 var lowerRight = GetSceneLayerCoordinatesAtPixel(
92 sceneLayer,
93 new PointF(candidateRange.Right, candidateRange.Bottom));
94
95 int minX = (int)Math.Floor(new[]
96 {
97 upperLeft.X,
98 upperRight.X,
99 lowerLeft.X,
100 lowerRight.X
101 }.Min()) - 1;
102
103 int maxX = (int)Math.Ceiling(new[]
104 {
105 upperLeft.X,
106 upperRight.X,
107 lowerLeft.X,
108 lowerRight.X
109 }.Max()) + 1;
110
111 int minY = (int)Math.Floor(new[]
112 {
113 upperLeft.Y,
114 upperRight.Y,
115 lowerLeft.Y,
116 lowerRight.Y
117 }.Min()) - 1;
118
119 int maxY = (int)Math.Ceiling(new[]
120 {
121 upperLeft.Y,
122 upperRight.Y,
123 lowerLeft.Y,
124 lowerRight.Y
125 }.Max()) + 1;
126
127 for (int y = minY; y <= maxY; y++)
128 {
129 for (int x = minX; x <= maxX; x++)
130 {
131 var tile = sceneLayer[x, y];
132 if (tile is null)
133 continue;
134
135 var tileRange = GetPixelRangeForTile(tile, includeOverhang);
136 if (tileRange.IntersectsWith(worldPixelRange))
137 result.Add(tile);
138 }
139 }
140
141 return result;
142 }
143
150 public Rectangle GetPixelRangeForTile(Tile tile, bool includeOverhang)
151 {
152 var anchor = GetAnchorPixelAtSceneLayerCoordinates(
153 tile.SceneLayer,
154 tile.SceneLayerCoordinates);
155
156 var baseRect = new Rectangle(
157 anchor.X,
158 anchor.Y,
159 tile.SceneLayer.TileWidth,
160 tile.SceneLayer.TileHeight);
161
162 return TileBounds.ApplyTileGeometry(baseRect, tile, includeOverhang);
163 }
164
171 public Rectangle GetPixelRangeForTileList(List<Tile> tileList, bool includeOverhang)
172 {
173 Rectangle result = Rectangle.Empty;
174
175 foreach (var tile in tileList)
176 {
177 var tileRange = GetPixelRangeForTile(tile, includeOverhang);
178 result = result.IsEmpty
179 ? tileRange
180 : Rectangle.Union(result, tileRange);
181 }
182
183 return result;
184 }
185
193 public SceneLayerTile GetAdjacentSceneLayerTile(
194 SceneLayerTile layerPoint,
195 CardinalDirections direction)
196 {
197 var sceneLayer = layerPoint.SceneLayer;
198 int x = layerPoint.GridCoordinatesAbs.X;
199 int y = layerPoint.GridCoordinatesAbs.Y;
200
201 return direction switch
202 {
203 CardinalDirections.N => sceneLayer.ResolveWrappedTile(x, y - 1),
204 CardinalDirections.NE => sceneLayer.ResolveWrappedTile(x + 1, y - 1),
205 CardinalDirections.E => sceneLayer.ResolveWrappedTile(x + 1, y),
206 CardinalDirections.SE => sceneLayer.ResolveWrappedTile(x + 1, y + 1),
207 CardinalDirections.S => sceneLayer.ResolveWrappedTile(x, y + 1),
208 CardinalDirections.SW => sceneLayer.ResolveWrappedTile(x - 1, y + 1),
209 CardinalDirections.W => sceneLayer.ResolveWrappedTile(x - 1, y),
210 CardinalDirections.NW => sceneLayer.ResolveWrappedTile(x - 1, y - 1),
211 _ => null
212 };
213 }
214
221 public Point[] GetPolygonPts(Tile tile, bool includeOverhang)
222 {
223 GetGeometry(
224 tile.SceneLayer,
225 out int W,
226 out int H,
227 out int skewX,
228 out int faceWidth);
229
230 var anchor = GetAnchorPixelAtSceneLayerCoordinates(
231 tile.SceneLayer,
232 tile.SceneLayerCoordinates);
233
234 var overhang = includeOverhang
235 ? tile.Overhang
236 : Spacing.None;
237
238 return new[]
239 {
240 new Point(
241 anchor.X - overhang.Left,
242 anchor.Y - overhang.Top),
243
244 new Point(
245 anchor.X + faceWidth + overhang.Right,
246 anchor.Y - overhang.Top),
247
248 new Point(
249 anchor.X + W + overhang.Right,
250 anchor.Y + H + overhang.Bottom),
251
252 new Point(
253 anchor.X + skewX - overhang.Left,
254 anchor.Y + H + overhang.Bottom)
255 };
256 }
257
265 public PointF FindEquivalentSceneLayerCoordinates(
266 PointF valColRow,
267 int xUpperBound,
268 int yUpperBound)
269 {
270 float modX = valColRow.X % (xUpperBound + 1);
271 float modY = valColRow.Y % (yUpperBound + 1);
272
273 if (modX < 0)
274 modX += xUpperBound + 1;
275
276 if (modY < 0)
277 modY += yUpperBound + 1;
278
279 return new PointF(modX, modY);
280 }
281
282 private static void GetGeometry(
283 SceneLayer sceneLayer,
284 out int width,
285 out int height,
286 out int skewX,
287 out int faceWidth)
288 {
289 width = sceneLayer.TileWidth;
290 height = sceneLayer.TileHeight;
291
292 // The full tile image remains W x H. Half of W is used by the
293 // row-wise shear; the remaining width is the horizontal tile face.
294 skewX = width / 2;
295 faceWidth = width - skewX;
296 }
297}
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 TileHeight
Gets or sets the height of each tile in this layer, measured in pixels.
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