ManiaMap.Unity
Procedural generation of metroidvania style maps for Unity.
MapTileSet.cs
1using MPewsey.ManiaMap;
2using System.Collections.Generic;
3using UnityEngine;
4using UnityEngine.Tilemaps;
5
7{
11 [CreateAssetMenu(menuName = "Mania Map/Map Tile Set")]
12 public class MapTileSet : ScriptableObject
13 {
17 public const int MaxFeatureCount = 64;
18
19 [SerializeField]
20 private int _pixelsPerUnit = 16;
24 public int PixelsPerUnit { get => _pixelsPerUnit; set => _pixelsPerUnit = value; }
25
26 [SerializeField]
27 private Vector2Int _tileSize = new Vector2Int(16, 16);
31 public Vector2Int TileSize { get => _tileSize; set => _tileSize = value; }
32
33 [SerializeField]
34 private FilterMode _filterMode = FilterMode.Point;
38 public FilterMode FilterMode { get => _filterMode; set => _filterMode = value; }
39
40 [Header("Walls")]
41
42 [SerializeField]
43 private Texture2D _northWall;
47 public Texture2D NorthWall { get => _northWall; set => _northWall = value; }
48
49 [SerializeField]
50 private Texture2D _southWall;
54 public Texture2D SouthWall { get => _southWall; set => _southWall = value; }
55
56 [SerializeField]
57 private Texture2D _westWall;
61 public Texture2D WestWall { get => _westWall; set => _westWall = value; }
62
63 [SerializeField]
64 private Texture2D _eastWall;
68 public Texture2D EastWall { get => _eastWall; set => _eastWall = value; }
69
70 [Header("Doors")]
71
72 [SerializeField]
73 private Texture2D _northDoor;
77 public Texture2D NorthDoor { get => _northDoor; set => _northDoor = value; }
78
79 [SerializeField]
80 private Texture2D _southDoor;
84 public Texture2D SouthDoor { get => _southDoor; set => _southDoor = value; }
85
86 [SerializeField]
87 private Texture2D _westDoor;
91 public Texture2D WestDoor { get => _westDoor; set => _westDoor = value; }
92
93 [SerializeField]
94 private Texture2D _eastDoor;
98 public Texture2D EastDoor { get => _eastDoor; set => _eastDoor = value; }
99
100 [SerializeField]
101 private Texture2D _topDoor;
105 public Texture2D TopDoor { get => _topDoor; set => _topDoor = value; }
106
107 [SerializeField]
108 private Texture2D _bottomDoor;
112 public Texture2D BottomDoor { get => _bottomDoor; set => _bottomDoor = value; }
113
114 [Header("Grid")]
115
116 [SerializeField]
117 private Texture2D _grid;
121 public Texture2D Grid { get => _grid; set => _grid = value; }
122
123 [Header("Features")]
124
125 [SerializeField]
126 private Texture2D _savePoint;
130 public Texture2D SavePoint { get => _savePoint; set => _savePoint = value; }
131
132 [SerializeField]
133 private List<FeatureMapTile> _featureTiles = new List<FeatureMapTile>();
137 public List<FeatureMapTile> FeatureTiles { get => _featureTiles; set => _featureTiles = value; }
138
142 private Dictionary<string, Texture2D> Textures { get; } = new Dictionary<string, Texture2D>();
143
147 private Dictionary<string, long> FeatureFlags { get; } = new Dictionary<string, long>();
148
152 private Dictionary<long, string> FeatureNames { get; } = new Dictionary<long, string>();
153
157 private Dictionary<MapTileKey, Tile> Tiles { get; } = new Dictionary<MapTileKey, Tile>();
158
162 public bool IsDirty { get; private set; } = true;
163
164 private void OnValidate()
165 {
166 MarkDirty();
167 }
168
172 public void MarkDirty()
173 {
174 IsDirty = true;
175 }
176
180 private void PopulateIfDirty()
181 {
182 if (IsDirty)
183 {
184 Tiles.Clear();
187 IsDirty = false;
188 }
189 }
190
194 private void PopulateTextures()
195 {
196 Textures.Clear();
197 Textures.Add(MapTileType.NorthDoor, NorthDoor);
198 Textures.Add(MapTileType.SouthDoor, SouthDoor);
199 Textures.Add(MapTileType.EastDoor, EastDoor);
200 Textures.Add(MapTileType.WestDoor, WestDoor);
201 Textures.Add(MapTileType.TopDoor, TopDoor);
202 Textures.Add(MapTileType.BottomDoor, BottomDoor);
203 Textures.Add(MapTileType.NorthWall, NorthWall);
204 Textures.Add(MapTileType.SouthWall, SouthWall);
205 Textures.Add(MapTileType.EastWall, EastWall);
206 Textures.Add(MapTileType.WestWall, WestWall);
207 Textures.Add(MapTileType.Grid, Grid);
208 Textures.Add(MapTileType.SavePoint, SavePoint);
209
210 foreach (var feature in FeatureTiles)
211 {
212 Textures.Add(feature.Feature, feature.Tile);
213 }
214 }
215
219 private void PopulateFeatureFlags()
220 {
221 FeatureFlags.Clear();
222 FeatureNames.Clear();
223 AddFeatureFlag(MapTileType.Grid);
224 AddFeatureFlag(MapTileType.NorthDoor);
225 AddFeatureFlag(MapTileType.SouthDoor);
226 AddFeatureFlag(MapTileType.EastDoor);
227 AddFeatureFlag(MapTileType.WestDoor);
228 AddFeatureFlag(MapTileType.TopDoor);
229 AddFeatureFlag(MapTileType.BottomDoor);
230 AddFeatureFlag(MapTileType.NorthWall);
231 AddFeatureFlag(MapTileType.SouthWall);
232 AddFeatureFlag(MapTileType.EastWall);
233 AddFeatureFlag(MapTileType.WestWall);
234 AddFeatureFlag(MapTileType.SavePoint);
235
236 foreach (var feature in FeatureTiles)
237 {
238 AddFeatureFlag(feature.Feature);
239 }
240 }
241
248 private bool AddFeatureFlag(string name)
249 {
250 if (string.IsNullOrWhiteSpace(name))
251 throw new System.ArgumentException($"Invalid feature name: {name}.");
252
253 if (FeatureFlags.ContainsKey(name))
254 return false;
255
256 if (FeatureFlags.Count >= MaxFeatureCount)
257 throw new System.ArgumentException($"Feature count exceeded. Cannot add feature: {name}.");
258
259 var flag = 1 << FeatureFlags.Count;
260 FeatureFlags.Add(name, flag);
261 FeatureNames.Add(flag, name);
262 return true;
263 }
264
270 public Texture2D GetTexture(string name)
271 {
273
274 if (string.IsNullOrWhiteSpace(name))
275 return null;
276 if (Textures.TryGetValue(name, out Texture2D tile))
277 return tile;
278 return null;
279 }
280
286 public long GetFeatureFlag(string name)
287 {
289
290 if (string.IsNullOrWhiteSpace(name))
291 return 0;
292 if (FeatureFlags.TryGetValue(name, out long feature))
293 return feature;
294 return 0;
295 }
296
302 public string GetFeatureName(long flag)
303 {
305
306 if (FeatureNames.TryGetValue(flag, out string name))
307 return name;
308 return null;
309 }
310
317 public Tile GetTile(long flags, Color32 color)
318 {
319 var key = new MapTileKey(flags, color);
320
321 if (!Tiles.TryGetValue(key, out Tile tile))
322 {
323 tile = CreateTile(flags, color);
324 Tiles.Add(key, tile);
325 }
326
327 return tile;
328 }
329
335 private Tile CreateTile(long flags, Color32 color)
336 {
337 var tile = CreateInstance<Tile>();
338 var sprite = CreateSprite(CreateFeatureTexture(flags, color));
339 sprite.name = "Mania Map Tile Sprite";
340 tile.sprite = sprite;
341 tile.name = "Mania Map Tile";
342 return tile;
343 }
344
349 private Sprite CreateSprite(Texture2D texture)
350 {
351 var pivot = new Vector2(0.5f, 0.5f);
352 var rect = new Rect(1, 1, texture.width - 2, texture.height - 2);
353 var sprite = Sprite.Create(texture, rect, pivot, PixelsPerUnit);
354 sprite.name = "Mania Map Tile Sprite";
355 return sprite;
356 }
357
364 private Texture2D CreateFeatureTexture(long flags, Color32 color)
365 {
366 var texture = new Texture2D(TileSize.x + 2, TileSize.y + 2);
367 texture.filterMode = FilterMode;
368 TextureUtility.Fill(texture, color);
369 DrawFeatures(texture, flags);
370 TextureUtility.FillBorder(texture);
371 texture.Apply();
372 return texture;
373 }
374
380 private void DrawFeatures(Texture2D texture, long flags)
381 {
382 for (long i = flags; i != 0; i &= i - 1)
383 {
384 var flag = ~(i - 1) & i;
385 var tile = GetTexture(GetFeatureName(flag));
386 TextureUtility.DrawImage(texture, tile, Vector2Int.one);
387 }
388 }
389 }
390}
Contains the map tiles used to draw maps for a Layout.
Definition: MapTileSet.cs:13
string GetFeatureName(long flag)
Returns the feature name corresponding to the specified flag if it exists. Returns null otherwise.
Definition: MapTileSet.cs:302
Dictionary< MapTileKey, Tile > Tiles
A dictionary of map tiles by map tile keys.
Definition: MapTileSet.cs:157
long GetFeatureFlag(string name)
Returns the feature flag corresponding to the feature name if it exists. Returns zero otherwise.
Definition: MapTileSet.cs:286
Dictionary< string, long > FeatureFlags
A dictionary of feature flags by feature name.
Definition: MapTileSet.cs:147
void PopulateFeatureFlags()
Populates the feature flag dictionaries.
Definition: MapTileSet.cs:219
Tile CreateTile(long flags, Color32 color)
Returns a new tile with the specified feature flags and background color.
Definition: MapTileSet.cs:335
const int MaxFeatureCount
The maximum number of features that can be managed by the set.
Definition: MapTileSet.cs:17
Texture2D Grid
The tile used for the LayoutMap grid (optional).
Definition: MapTileSet.cs:121
Texture2D NorthWall
The superinposed tile when a north wall exists.
Definition: MapTileSet.cs:47
Texture2D BottomDoor
The superimposed tile when a bottom door exists.
Definition: MapTileSet.cs:112
Texture2D SavePoint
The tile used for save point features (optional).
Definition: MapTileSet.cs:130
Texture2D CreateFeatureTexture(long flags, Color32 color)
Creates a new texture with the specified features and background color. The returned texture has 1 pi...
Definition: MapTileSet.cs:364
void PopulateIfDirty()
Populates the map tile set textures and feature flags if it is dirty.
Definition: MapTileSet.cs:180
Sprite CreateSprite(Texture2D texture)
Creates a new sprite with the specified texture. The texture should include 1 pixel of padding.
Definition: MapTileSet.cs:349
Dictionary< long, string > FeatureNames
A dictionary of feature names by flag.
Definition: MapTileSet.cs:152
Texture2D WestWall
The superimposed tile when a west wall exists.
Definition: MapTileSet.cs:61
Texture2D NorthDoor
The superimposed tile when a north door exists.
Definition: MapTileSet.cs:77
Dictionary< string, Texture2D > Textures
A dictionary of referenced tiles.
Definition: MapTileSet.cs:142
Texture2D TopDoor
The superimposed tile when a top door exists.
Definition: MapTileSet.cs:105
Texture2D GetTexture(string name)
Returns the texture corresponding to the feature name if it exists. Returns null otherwise.
Definition: MapTileSet.cs:270
Texture2D EastDoor
The superimposed tile when an east door exists.
Definition: MapTileSet.cs:98
List< FeatureMapTile > FeatureTiles
A list of cell feature tiles.
Definition: MapTileSet.cs:137
void DrawFeatures(Texture2D texture, long flags)
Draws the feature tiles for the specified flags onto a texture.
Definition: MapTileSet.cs:380
int PixelsPerUnit
The number of pixels per unit for each tile.
Definition: MapTileSet.cs:24
void PopulateTextures()
Populates the textures dictionary.
Definition: MapTileSet.cs:194
Texture2D SouthWall
The superinposed tile when a south wall exists.
Definition: MapTileSet.cs:54
Vector2Int TileSize
The width and height of each tile.
Definition: MapTileSet.cs:31
Tile GetTile(long flags, Color32 color)
Returns the map tile with the specified feature flags and background color. Creates the tile if it do...
Definition: MapTileSet.cs:317
Texture2D SouthDoor
The superimposed tile when a south door exists.
Definition: MapTileSet.cs:84
Texture2D EastWall
The superimposed tile when an east wall exists.
Definition: MapTileSet.cs:68
FilterMode FilterMode
The map tile texture filter mode.
Definition: MapTileSet.cs:38
bool AddFeatureFlag(string name)
Adds the specified feature to the feature dictionaries. Returns false if the feature already exists.
Definition: MapTileSet.cs:248
void MarkDirty()
Sets the map tile set as dirty.
Definition: MapTileSet.cs:172
Texture2D WestDoor
The superimposed tile when a west door exists.
Definition: MapTileSet.cs:91
bool IsDirty
True if the map tile set is dirty and requires update.
Definition: MapTileSet.cs:162
Contains methods for manipulating textures.
static void Fill(Texture2D texture, Color32 color)
Fills the texture with the specified color.
static void FillBorder(Texture2D texture)
Fills the 1 pixel border around the texture with the colors at a 1 pixel inset.
static void DrawImage(Texture2D texture, Texture2D brush, Vector2Int point)
Draws the brush texture at the specified point.
A structure containing map tile type flags and an associated color.
Definition: MapTileKey.cs:11