TileMap.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.Xna.Framework;
  5. using Microsoft.Xna.Framework.Audio;
  6. using Microsoft.Xna.Framework.Content;
  7. using Microsoft.Xna.Framework.Graphics;
  8. using Microsoft.Xna.Framework.Input;
  9. using Microsoft.Xna.Framework.Media;
  10. using System.IO;
  11. using System.Xml.Serialization;
  12. using System.Runtime.Serialization.Formatters.Binary;
  13. namespace Tile_Engine
  14. {
  15. public static class TileMap
  16. {
  17. public const int TileWidth = 48;
  18. public const int TileHeight = 48;
  19. public const int MapWidth = 160;
  20. public const int MapHeight = 12;
  21. public const int MapLayers = 3;
  22. private const int skyTile = 2;
  23. static public MapSquare[][] mapCells =
  24. CreateJaggedArray(MapWidth, MapHeight);
  25. public static bool EditorMode = false;
  26. public static SpriteFont spriteFont;
  27. static private Texture2D tileSheet;
  28. static public void Initialize(Texture2D tileTexture)
  29. {
  30. tileSheet = tileTexture;
  31. mapCells = CreateJaggedArray(MapWidth, MapHeight);
  32. for (int x = 0; x < MapWidth; x++)
  33. {
  34. for (int y = 0; y < MapHeight; y++)
  35. {
  36. for (int z = 0; z < MapLayers; z++)
  37. {
  38. mapCells[x][y] = new MapSquare(skyTile, 0, 0, "", true);
  39. }
  40. }
  41. }
  42. }
  43. public static int TilesPerRow
  44. {
  45. get { return tileSheet.Width / TileWidth; }
  46. }
  47. public static Rectangle TileSourceRectangle(int tileIndex)
  48. {
  49. return new Rectangle(
  50. (tileIndex % TilesPerRow) * TileWidth,
  51. (tileIndex / TilesPerRow) * TileHeight,
  52. TileWidth,
  53. TileHeight);
  54. }
  55. static public int GetCellByPixelX(int pixelX)
  56. {
  57. return pixelX / TileWidth;
  58. }
  59. static public int GetCellByPixelY(int pixelY)
  60. {
  61. return pixelY / TileHeight;
  62. }
  63. static public Vector2 GetCellByPixel(Vector2 pixelLocation)
  64. {
  65. return new Vector2(
  66. GetCellByPixelX((int)pixelLocation.X),
  67. GetCellByPixelY((int)pixelLocation.Y));
  68. }
  69. static public Vector2 GetCellCenter(int cellX, int cellY)
  70. {
  71. return new Vector2(
  72. (cellX * TileWidth) + (TileWidth / 2),
  73. (cellY * TileHeight) + (TileHeight / 2));
  74. }
  75. static public Vector2 GetCellCenter(Vector2 cell)
  76. {
  77. return GetCellCenter(
  78. (int)cell.X,
  79. (int)cell.Y);
  80. }
  81. static public Rectangle CellWorldRectangle(int cellX, int cellY)
  82. {
  83. return new Rectangle(
  84. cellX * TileWidth,
  85. cellY * TileHeight,
  86. TileWidth,
  87. TileHeight);
  88. }
  89. static public Rectangle CellWorldRectangle(Vector2 cell)
  90. {
  91. return CellWorldRectangle(
  92. (int)cell.X,
  93. (int)cell.Y);
  94. }
  95. static public Rectangle CellScreenRectangle(int cellX, int cellY)
  96. {
  97. return Camera.WorldToScreen(CellWorldRectangle(cellX, cellY));
  98. }
  99. static public Rectangle CellSreenRectangle(Vector2 cell)
  100. {
  101. return CellScreenRectangle((int)cell.X, (int)cell.Y);
  102. }
  103. static public bool CellIsPassable(int cellX, int cellY)
  104. {
  105. MapSquare square = GetMapSquareAtCell(cellX, cellY);
  106. if (square == null)
  107. return false;
  108. else
  109. return square.Passable;
  110. }
  111. static public bool CellIsPassable(Vector2 cell)
  112. {
  113. return CellIsPassable((int)cell.X, (int)cell.Y);
  114. }
  115. static public bool CellIsPassableByPixel(Vector2 pixelLocation)
  116. {
  117. return CellIsPassable(
  118. GetCellByPixelX((int)pixelLocation.X),
  119. GetCellByPixelY((int)pixelLocation.Y));
  120. }
  121. static public string CellCodeValue(int cellX, int cellY)
  122. {
  123. MapSquare square = GetMapSquareAtCell(cellX, cellY);
  124. if (square == null)
  125. return "";
  126. else
  127. return square.CodeValue;
  128. }
  129. static public string CellCodeValue(Vector2 cell)
  130. {
  131. return CellCodeValue((int)cell.X, (int)cell.Y);
  132. }
  133. static public MapSquare GetMapSquareAtCell(int tileX, int tileY)
  134. {
  135. if ((tileX >= 0) && (tileX < MapWidth) &&
  136. (tileY >= 0) && (tileY < MapHeight))
  137. {
  138. return mapCells[tileX][tileY];
  139. }
  140. else
  141. {
  142. return null;
  143. }
  144. }
  145. static public void SetMapSquareAtCell(
  146. int tileX,
  147. int tileY,
  148. MapSquare tile)
  149. {
  150. if ((tileX >= 0) && (tileX < MapWidth) &&
  151. (tileY >= 0) && (tileY < MapHeight))
  152. {
  153. mapCells[tileX][tileY] = tile;
  154. }
  155. }
  156. static public void SetTileAtCell(
  157. int tileX,
  158. int tileY,
  159. int layer,
  160. int tileIndex)
  161. {
  162. if ((tileX >= 0) && (tileX < MapWidth) &&
  163. (tileY >= 0) && (tileY < MapHeight))
  164. {
  165. mapCells[tileX][tileY].LayerTiles[layer] = tileIndex;
  166. }
  167. }
  168. static public MapSquare GetMapSquareAtPixel(int pixelX, int pixelY)
  169. {
  170. return GetMapSquareAtCell(
  171. GetCellByPixelX(pixelX),
  172. GetCellByPixelY(pixelY));
  173. }
  174. static public MapSquare GetMapSquareAtPixel(Vector2 pixelLocation)
  175. {
  176. return GetMapSquareAtPixel(
  177. (int)pixelLocation.X,
  178. (int)pixelLocation.Y);
  179. }
  180. public static void SaveMap(FileStream fileStream)
  181. {
  182. // Assumes mapCells is now a jagged array: MapSquare[][]
  183. var options = new System.Text.Json.JsonSerializerOptions { WriteIndented = true };
  184. using (var writer = new StreamWriter(fileStream, leaveOpen: false))
  185. {
  186. string json = System.Text.Json.JsonSerializer.Serialize(mapCells, options);
  187. writer.Write(json);
  188. }
  189. }
  190. public static void LoadMap(FileStream fileStream)
  191. {
  192. try
  193. {
  194. using (var reader = new StreamReader(fileStream, leaveOpen: false))
  195. {
  196. string json = reader.ReadToEnd();
  197. mapCells = System.Text.Json.JsonSerializer.Deserialize<MapSquare[][]>(json);
  198. }
  199. }
  200. catch
  201. {
  202. ClearMap();
  203. }
  204. }
  205. public static void LoadMapFromStream(Stream stream)
  206. {
  207. try
  208. {
  209. using (var reader = new StreamReader(stream, leaveOpen: true))
  210. {
  211. string json = reader.ReadToEnd();
  212. mapCells = System.Text.Json.JsonSerializer.Deserialize<MapSquare[][]>(json);
  213. }
  214. }
  215. catch
  216. {
  217. ClearMap();
  218. }
  219. }
  220. public static void ClearMap()
  221. {
  222. for (int x = 0; x < MapWidth; x++)
  223. for (int y = 0; y < MapHeight; y++)
  224. for (int z = 0; z < MapLayers; z++)
  225. {
  226. mapCells[x][y] = new MapSquare(2, 0, 0, "", true);
  227. }
  228. }
  229. static public void Draw(SpriteBatch spriteBatch)
  230. {
  231. int startX = GetCellByPixelX((int)Camera.Position.X);
  232. int endX = GetCellByPixelX((int)Camera.Position.X +
  233. Camera.ViewPortWidth);
  234. int startY = GetCellByPixelY((int)Camera.Position.Y);
  235. int endY = GetCellByPixelY((int)Camera.Position.Y +
  236. Camera.ViewPortHeight);
  237. for (int x = startX; x <= endX; x++)
  238. for (int y = startY; y <= endY; y++)
  239. {
  240. for (int z = 0; z < MapLayers; z++)
  241. {
  242. if ((x >= 0) && (y >= 0) &&
  243. (x < MapWidth) && (y < MapHeight))
  244. {
  245. spriteBatch.Draw(
  246. tileSheet,
  247. CellScreenRectangle(x, y),
  248. TileSourceRectangle(mapCells[x][y].LayerTiles[z]),
  249. Color.White,
  250. 0.0f,
  251. Vector2.Zero,
  252. SpriteEffects.None,
  253. 1f - ((float)z * 0.1f));
  254. }
  255. }
  256. if (EditorMode)
  257. {
  258. DrawEditModeItems(spriteBatch, x, y);
  259. }
  260. }
  261. }
  262. public static void DrawEditModeItems(
  263. SpriteBatch spriteBatch,
  264. int x,
  265. int y)
  266. {
  267. if ((x < 0) || (x >= MapWidth) ||
  268. (y < 0) || (y >= MapHeight))
  269. return;
  270. if (!CellIsPassable(x, y))
  271. {
  272. spriteBatch.Draw(
  273. tileSheet,
  274. CellScreenRectangle(x, y),
  275. TileSourceRectangle(1),
  276. new Color(255, 0, 0, 80),
  277. 0.0f,
  278. Vector2.Zero,
  279. SpriteEffects.None,
  280. 0.0f);
  281. }
  282. if (mapCells[x][y].CodeValue != "")
  283. {
  284. Rectangle screenRect = CellScreenRectangle(x, y);
  285. spriteBatch.DrawString(
  286. spriteFont,
  287. mapCells[x][y].CodeValue,
  288. new Vector2(screenRect.X, screenRect.Y),
  289. Color.White,
  290. 0.0f,
  291. Vector2.Zero,
  292. 1.0f,
  293. SpriteEffects.None,
  294. 0.0f);
  295. }
  296. }
  297. // Helper to create a jagged array
  298. private static MapSquare[][] CreateJaggedArray(int width, int height)
  299. {
  300. var arr = new MapSquare[width][];
  301. for (int i = 0; i < width; i++)
  302. arr[i] = new MapSquare[height];
  303. return arr;
  304. }
  305. }
  306. }