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 }