TiledMapReader.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.Xna.Framework;
  5. using Microsoft.Xna.Framework.Content;
  6. using Microsoft.Xna.Framework.Graphics;
  7. using MonoGame.Extended.Content;
  8. namespace MonoGame.Extended.Tiled
  9. {
  10. public class TiledMapReader : ContentTypeReader<TiledMap>
  11. {
  12. protected override TiledMap Read(ContentReader reader, TiledMap existingInstance)
  13. {
  14. if (existingInstance != null)
  15. return existingInstance;
  16. var map = ReadTiledMap(reader);
  17. reader.ReadTiledMapProperties(map.Properties);
  18. ReadTilesets(reader, map);
  19. ReadLayers(reader, map);
  20. return map;
  21. }
  22. private static TiledMap ReadTiledMap(ContentReader reader)
  23. {
  24. var name = reader.AssetName;
  25. var type = reader.ReadString();
  26. var width = reader.ReadInt32();
  27. var height = reader.ReadInt32();
  28. var tileWidth = reader.ReadInt32();
  29. var tileHeight = reader.ReadInt32();
  30. var backgroundColor = reader.ReadColor();
  31. var renderOrder = (TiledMapTileDrawOrder)reader.ReadByte();
  32. var orientation = (TiledMapOrientation)reader.ReadByte();
  33. return new TiledMap(name, type, width, height, tileWidth, tileHeight, renderOrder, orientation, backgroundColor);
  34. }
  35. private static void ReadTilesets(ContentReader reader, TiledMap map)
  36. {
  37. var tilesetCount = reader.ReadInt32();
  38. for (var i = 0; i < tilesetCount; i++)
  39. {
  40. var firstGlobalIdentifier = reader.ReadInt32();
  41. var tileset = ReadTileset(reader, map);
  42. map.AddTileset(tileset, firstGlobalIdentifier);
  43. }
  44. }
  45. private static TiledMapTileset ReadTileset(ContentReader reader, TiledMap map)
  46. {
  47. var external = reader.ReadBoolean();
  48. var tileset = external ? reader.ReadExternalReference<TiledMapTileset>() : TiledMapTilesetReader.ReadTileset(reader);
  49. return tileset;
  50. }
  51. private static void ReadLayers(ContentReader reader, TiledMap map)
  52. {
  53. foreach (var layer in ReadGroup(reader, map))
  54. map.AddLayer(layer);
  55. }
  56. private static List<TiledMapLayer> ReadGroup(ContentReader reader, TiledMap map)
  57. {
  58. var layerCount = reader.ReadInt32();
  59. var value = new List<TiledMapLayer>(layerCount);
  60. for (var i = 0; i < layerCount; i++)
  61. value.Add(ReadLayer(reader, map));
  62. return value;
  63. }
  64. private static TiledMapLayer ReadLayer(ContentReader reader, TiledMap map)
  65. {
  66. var layerType = (TiledMapLayerType)reader.ReadByte();
  67. var name = reader.ReadString();
  68. var type = reader.ReadString();
  69. var isVisible = reader.ReadBoolean();
  70. var opacity = reader.ReadSingle();
  71. var offsetX = reader.ReadSingle();
  72. var offsetY = reader.ReadSingle();
  73. var offset = new Vector2(offsetX, offsetY);
  74. var parallaxX = reader.ReadSingle();
  75. var parallaxY = reader.ReadSingle();
  76. var parallaxFactor = new Vector2(parallaxX, parallaxY);
  77. var properties = new TiledMapProperties();
  78. reader.ReadTiledMapProperties(properties);
  79. TiledMapLayer layer;
  80. switch (layerType)
  81. {
  82. case TiledMapLayerType.ImageLayer:
  83. layer = ReadImageLayer(reader, name, type, offset, parallaxFactor, opacity, isVisible);
  84. break;
  85. case TiledMapLayerType.TileLayer:
  86. layer = ReadTileLayer(reader, name, type, offset, parallaxFactor, opacity, isVisible, map);
  87. break;
  88. case TiledMapLayerType.ObjectLayer:
  89. layer = ReadObjectLayer(reader, name, type, offset, parallaxFactor, opacity, isVisible, map);
  90. break;
  91. case TiledMapLayerType.GroupLayer:
  92. layer = new TiledMapGroupLayer(name, type, ReadGroup(reader, map), offset, parallaxFactor, opacity, isVisible);
  93. break;
  94. default:
  95. throw new ArgumentOutOfRangeException();
  96. }
  97. foreach (var property in properties)
  98. layer.Properties.Add(property.Key, property.Value);
  99. return layer;
  100. }
  101. private static TiledMapLayer ReadObjectLayer(ContentReader reader, string name, string type, Vector2 offset, Vector2 parallaxFactor, float opacity, bool isVisible, TiledMap map)
  102. {
  103. var color = reader.ReadColor();
  104. var drawOrder = (TiledMapObjectDrawOrder)reader.ReadByte();
  105. var objectCount = reader.ReadInt32();
  106. var objects = new TiledMapObject[objectCount];
  107. for (var i = 0; i < objectCount; i++)
  108. objects[i] = ReadTiledMapObject(reader, map);
  109. return new TiledMapObjectLayer(name, type, objects, color, drawOrder, offset, parallaxFactor, opacity, isVisible);
  110. }
  111. private static TiledMapObject ReadTiledMapObject(ContentReader reader, TiledMap map)
  112. {
  113. var objectType = (TiledMapObjectType)reader.ReadByte();
  114. var identifier = reader.ReadInt32();
  115. var name = reader.ReadString();
  116. var type = reader.ReadString();
  117. var position = new Vector2(reader.ReadSingle(), reader.ReadSingle());
  118. var width = reader.ReadSingle();
  119. var height = reader.ReadSingle();
  120. var size = new SizeF(width, height);
  121. var rotation = reader.ReadSingle();
  122. var isVisible = reader.ReadBoolean();
  123. var properties = new TiledMapProperties();
  124. const float opacity = 1.0f;
  125. reader.ReadTiledMapProperties(properties);
  126. TiledMapObject mapObject;
  127. switch (objectType)
  128. {
  129. case TiledMapObjectType.Rectangle:
  130. mapObject = new TiledMapRectangleObject(identifier, name, size, position, rotation, opacity, isVisible, type);
  131. break;
  132. case TiledMapObjectType.Tile:
  133. var globalTileIdentifierWithFlags = reader.ReadUInt32();
  134. var tile = new TiledMapTile(globalTileIdentifierWithFlags, (ushort)position.X, (ushort)position.Y);
  135. var tileset = map.GetTilesetByTileGlobalIdentifier(tile.GlobalIdentifier);
  136. var localTileIdentifier = tile.GlobalIdentifier - map.GetTilesetFirstGlobalIdentifier(tileset);
  137. var tilesetTile = tileset.Tiles.FirstOrDefault(x => x.LocalTileIdentifier == localTileIdentifier);
  138. mapObject = new TiledMapTileObject(identifier, name, tileset, tilesetTile, size, position, rotation, opacity, isVisible, type);
  139. break;
  140. case TiledMapObjectType.Ellipse:
  141. mapObject = new TiledMapEllipseObject(identifier, name, size, position, rotation, opacity, isVisible);
  142. break;
  143. case TiledMapObjectType.Polygon:
  144. mapObject = new TiledMapPolygonObject(identifier, name, ReadPoints(reader), size, position, rotation, opacity, isVisible, type);
  145. break;
  146. case TiledMapObjectType.Polyline:
  147. mapObject = new TiledMapPolylineObject(identifier, name, ReadPoints(reader), size, position, rotation, opacity, isVisible, type);
  148. break;
  149. default:
  150. throw new ArgumentOutOfRangeException();
  151. }
  152. foreach (var property in properties)
  153. mapObject.Properties.Add(property.Key, property.Value);
  154. return mapObject;
  155. }
  156. private static Vector2[] ReadPoints(ContentReader reader)
  157. {
  158. var pointCount = reader.ReadInt32();
  159. var points = new Vector2[pointCount];
  160. for (var i = 0; i < pointCount; i++)
  161. {
  162. var x = reader.ReadSingle();
  163. var y = reader.ReadSingle();
  164. points[i] = new Vector2(x, y);
  165. }
  166. return points;
  167. }
  168. private static TiledMapImageLayer ReadImageLayer(ContentReader reader, string name, string type, Vector2 offset, Vector2 parallaxFactor, float opacity, bool isVisible)
  169. {
  170. var texture = reader.ReadExternalReference<Texture2D>();
  171. var x = reader.ReadSingle();
  172. var y = reader.ReadSingle();
  173. var position = new Vector2(x, y);
  174. return new TiledMapImageLayer(name, type, texture, position, offset, parallaxFactor, opacity, isVisible);
  175. }
  176. private static TiledMapTileLayer ReadTileLayer(ContentReader reader, string name, string type, Vector2 offset, Vector2 parallaxFactor, float opacity, bool isVisible, TiledMap map)
  177. {
  178. var width = reader.ReadInt32();
  179. var height = reader.ReadInt32();
  180. var tileWidth = map.TileWidth;
  181. var tileHeight = map.TileHeight;
  182. var tileCount = reader.ReadInt32();
  183. var layer = new TiledMapTileLayer(name, type, width, height, tileWidth, tileHeight, offset, parallaxFactor, opacity, isVisible);
  184. for (var i = 0; i < tileCount; i++)
  185. {
  186. var globalTileIdentifierWithFlags = reader.ReadUInt32();
  187. var x = reader.ReadUInt16();
  188. var y = reader.ReadUInt16();
  189. layer.Tiles[x + y * width] = new TiledMapTile(globalTileIdentifierWithFlags, x, y);
  190. }
  191. return layer;
  192. }
  193. }
  194. }