1 /**
2  * Retrograde Engine
3  *
4  * Authors:
5  *  Mike Bierlee, m.bierlee@lostmoment.com
6  * Copyright: 2014-2021 Mike Bierlee
7  * License:
8  *  This software is licensed under the terms of the MIT license.
9  *  The full terms of the license can be found in the LICENSE.txt file.
10  */
11 
12 module retrograde.tiles;
13 
14 import retrograde.entity;
15 import retrograde.math;
16 
17 import std.exception;
18 
19 class TileCompositionException : Exception {
20     mixin basicExceptionCtors;
21 }
22 
23 enum TilemapOrientation {
24     orthogonal,
25     isometric
26 }
27 
28 class Tilemap {
29     public ulong width;
30     public ulong height;
31     public ulong tileWidth;
32     public ulong tileHeight;
33     public TilemapOrientation orientation;
34 
35     public Tileset[] tilesets;
36     public TileLayer[] layers;
37 }
38 
39 class Tileset {
40     public string name;
41     public string imageName;
42     public ulong imageWidth;
43     public ulong imageHeight;
44     public ulong tileWidth;
45     public ulong tileHeight;
46     public ulong firstGlobalId;
47 
48     public Tile[] tiles;
49 }
50 
51 class Tile {
52     public Tileset parentTileset;
53     public ulong globalTileId;
54     public ulong tilesetTileId;
55     public bool empty;
56     public Vector2UL positionInTileset;
57 }
58 
59 class TileLayer {
60     public Tile[] tileData;
61     public string name;
62 }
63 
64 class TilemapComponent : EntityComponent {
65     mixin EntityComponentIdentity!"TilemapComponent";
66 
67     private Tilemap _tilemap;
68 
69     public this(Tilemap tilemap) {
70         this._tilemap = tilemap;
71     }
72 
73     public @property tilemap() {
74         return _tilemap;
75     }
76 }
77 
78 class RenderableTilemapComponent {
79     mixin EntityComponentIdentity!"RenderableTilemapComponent";
80 }
81 
82 interface CompositionStrategy {
83     public RectangleUL getDimensions(Tilemap tilemap);
84     public RectangleUL getTileDestination(Tilemap tilemap, ulong row, ulong column);
85 }
86 
87 class OrthogonalCompositionStrategy : CompositionStrategy {
88     public RectangleUL getDimensions(Tilemap tilemap) {
89         return RectangleUL(0, 0, tilemap.width * tilemap.tileWidth, tilemap.height * tilemap.tileHeight);
90     }
91 
92     public RectangleUL getTileDestination(Tilemap tilemap, ulong row, ulong column) {
93         return RectangleUL((column - 1) * tilemap.tileWidth, (row - 1) * tilemap.tileHeight, 0, 0);
94     }
95 }
96 
97 class IsometricCompositionStrategy : CompositionStrategy {
98     public RectangleUL getDimensions(Tilemap tilemap) {
99         return RectangleUL(0, 0, tilemap.tileWidth * (tilemap.width + tilemap.height) / 2, tilemap.tileHeight * (tilemap.width + tilemap.height) / 2);
100     }
101 
102     public RectangleUL getTileDestination(Tilemap tilemap, ulong row, ulong column) {
103         auto c = column - 1;
104         auto r = row - 1;
105         auto originShift = cast(int) ((tilemap.height * tilemap.tileWidth) / 2) - (tilemap.tileWidth / 2);
106         auto xPosition = cast(int) (tilemap.tileWidth * (c * 0.5)) - cast(int) (tilemap.tileWidth * (r * 0.5)) + originShift;
107         auto yPosition = cast(int) (tilemap.tileHeight * (r * 0.5)) + cast(int) (tilemap.tileHeight * (c * 0.5));
108         return RectangleUL(xPosition, yPosition, 0, 0);
109     }
110 }
111 
112 class CompositionStrategyFactory {
113     public CompositionStrategy createStrategy(Tilemap tilemap) {
114         switch(tilemap.orientation) {
115             case TilemapOrientation.orthogonal:
116                 return new OrthogonalCompositionStrategy();
117             case TilemapOrientation.isometric:
118                 return new IsometricCompositionStrategy();
119             default:
120                 throw new TileCompositionException("No composition strategy available for orientation " ~ tilemap.orientation.stringof);
121         }
122     }
123 }