Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / room / DungeonTileManager.cs
@小李xl 小李xl on 16 Feb 2023 19 KB 地牢生成读取预设房间
  1.  
  2. using Godot;
  3.  
  4. public static class DungeonTileManager
  5. {
  6. public static void AutoFillRoomTile(TileMap tileMap, int floorLayer, int middleLayer, int topLayer,
  7. AutoTileConfig config,
  8. RoomInfo roomInfo)
  9. {
  10. foreach (var info in roomInfo.Next)
  11. {
  12. AutoFillRoomTile(tileMap, floorLayer, middleLayer, topLayer, config, info);
  13. }
  14. //铺房间
  15. if (roomInfo.Template == null)
  16. {
  17. FillRect(tileMap, floorLayer, config.Ground, roomInfo.Position + Vector2.One,
  18. roomInfo.Size - new Vector2(2, 2));
  19.  
  20. FillRect(tileMap, topLayer, config.IN_LT, roomInfo.Position, Vector2.One);
  21. FillRect(tileMap, topLayer, config.L, roomInfo.Position + new Vector2(0, 1),
  22. new Vector2(1, roomInfo.Size.Y - 2));
  23. FillRect(tileMap, topLayer, config.IN_LB, roomInfo.Position + new Vector2(0, roomInfo.Size.Y - 1),
  24. new Vector2(1, 1));
  25. FillRect(tileMap, topLayer, config.B, roomInfo.Position + new Vector2(1, roomInfo.Size.Y - 1),
  26. new Vector2(roomInfo.Size.X - 2, 1));
  27. FillRect(tileMap, topLayer, config.IN_RB,
  28. roomInfo.Position + new Vector2(roomInfo.Size.X - 1, roomInfo.Size.Y - 1),
  29. Vector2.One);
  30. FillRect(tileMap, topLayer, config.R, roomInfo.Position + new Vector2(roomInfo.Size.X - 1, 1),
  31. new Vector2(1, roomInfo.Size.Y - 2));
  32. FillRect(tileMap, topLayer, config.IN_RT, roomInfo.Position + new Vector2(roomInfo.Size.X - 1, 0),
  33. Vector2.One);
  34. FillRect(tileMap, middleLayer, config.T, roomInfo.Position + Vector2.Right,
  35. new Vector2(roomInfo.Size.X - 2, 1));
  36. }
  37. else
  38. {
  39. var usedRect = roomInfo.Template.GetUsedRect();
  40. var rectSize = usedRect.Size;
  41. var rectPos = usedRect.Position;
  42. for (int i = 0; i < rectSize.X; i++)
  43. {
  44. for (int j = 0; j < rectSize.Y; j++)
  45. {
  46. var atlasCoords = roomInfo.Template.GetCellAtlasCoords(0, new Vector2I(rectPos.X + i, rectPos.Y + j));
  47. tileMap.SetCell(floorLayer, new Vector2I(roomInfo.Position.X + i, roomInfo.Position.Y + j), 1, atlasCoords);
  48. }
  49. }
  50. }
  51.  
  52. //铺过道
  53. foreach (var doorInfo in roomInfo.Doors)
  54. {
  55. if (doorInfo.ConnectRoom.Id > roomInfo.Id)
  56. {
  57. //普通的直线连接
  58. var doorDir1 = doorInfo.Direction;
  59. var doorDir2 = doorInfo.ConnectDoor.Direction;
  60. if (!doorInfo.HasCross)
  61. {
  62. //方向, 0横向, 1纵向
  63. int dir = 0;
  64. var rect = Utils.CalcRect(
  65. doorInfo.OriginPosition.X,
  66. doorInfo.OriginPosition.Y,
  67. doorInfo.ConnectDoor.OriginPosition.X,
  68. doorInfo.ConnectDoor.OriginPosition.Y
  69. );
  70. if (doorDir1 == DoorDirection.N || doorDir1 == DoorDirection.S)
  71. {
  72. rect.Size = new Vector2(GenerateDungeon.CorridorWidth, rect.Size.Y);
  73. dir = 1;
  74. }
  75. else
  76. {
  77. rect.Size = new Vector2(rect.Size.X, GenerateDungeon.CorridorWidth);
  78. }
  79.  
  80. if (dir == 0) //横向
  81. {
  82. FullHorizontalGalleryWall(tileMap, floorLayer, middleLayer, topLayer, config, rect);
  83. }
  84. else //纵向
  85. {
  86. FullVerticalGalleryWall(tileMap, floorLayer, middleLayer, topLayer, config, rect);
  87. }
  88. }
  89. else //带交叉点
  90. {
  91. //方向, 0横向, 1纵向
  92. int dir1 = 0;
  93. int dir2 = 0;
  94.  
  95. Rect2 rect;
  96. Rect2 rect2;
  97.  
  98. //计算范围
  99. switch (doorDir1)
  100. {
  101. case DoorDirection.E: //→
  102. rect = new Rect2(
  103. doorInfo.OriginPosition.X,
  104. doorInfo.OriginPosition.Y,
  105. doorInfo.Cross.X - doorInfo.OriginPosition.X,
  106. GenerateDungeon.CorridorWidth
  107. );
  108. break;
  109. case DoorDirection.W: //←
  110. rect = new Rect2(
  111. doorInfo.Cross.X + GenerateDungeon.CorridorWidth,
  112. doorInfo.Cross.Y,
  113. doorInfo.OriginPosition.X - (doorInfo.Cross.X + GenerateDungeon.CorridorWidth),
  114. GenerateDungeon.CorridorWidth
  115. );
  116. break;
  117. case DoorDirection.S: //↓
  118. dir1 = 1;
  119. rect = new Rect2(
  120. doorInfo.OriginPosition.X,
  121. doorInfo.OriginPosition.Y,
  122. GenerateDungeon.CorridorWidth,
  123. doorInfo.Cross.Y - doorInfo.OriginPosition.Y
  124. );
  125. break;
  126. case DoorDirection.N: //↑
  127. dir1 = 1;
  128. rect = new Rect2(
  129. doorInfo.Cross.X,
  130. doorInfo.Cross.Y + GenerateDungeon.CorridorWidth,
  131. GenerateDungeon.CorridorWidth,
  132. doorInfo.OriginPosition.Y - (doorInfo.Cross.Y + GenerateDungeon.CorridorWidth)
  133. );
  134. break;
  135. default:
  136. rect = new Rect2();
  137. break;
  138. }
  139.  
  140. switch (doorDir2)
  141. {
  142. case DoorDirection.E: //→
  143. rect2 = new Rect2(
  144. doorInfo.ConnectDoor.OriginPosition.X,
  145. doorInfo.ConnectDoor.OriginPosition.Y,
  146. doorInfo.Cross.X - doorInfo.ConnectDoor.OriginPosition.X,
  147. GenerateDungeon.CorridorWidth
  148. );
  149. break;
  150. case DoorDirection.W: //←
  151. rect2 = new Rect2(
  152. doorInfo.Cross.X + GenerateDungeon.CorridorWidth,
  153. doorInfo.Cross.Y,
  154. doorInfo.ConnectDoor.OriginPosition.X -
  155. (doorInfo.Cross.X + GenerateDungeon.CorridorWidth),
  156. GenerateDungeon.CorridorWidth
  157. );
  158. break;
  159. case DoorDirection.S: //↓
  160. dir2 = 1;
  161. rect2 = new Rect2(
  162. doorInfo.ConnectDoor.OriginPosition.X,
  163. doorInfo.ConnectDoor.OriginPosition.Y,
  164. GenerateDungeon.CorridorWidth,
  165. doorInfo.Cross.Y - doorInfo.ConnectDoor.OriginPosition.Y
  166. );
  167. break;
  168. case DoorDirection.N: //↑
  169. dir2 = 1;
  170. rect2 = new Rect2(
  171. doorInfo.Cross.X,
  172. doorInfo.Cross.Y + GenerateDungeon.CorridorWidth,
  173. GenerateDungeon.CorridorWidth,
  174. doorInfo.ConnectDoor.OriginPosition.Y -
  175. (doorInfo.Cross.Y + GenerateDungeon.CorridorWidth)
  176. );
  177. break;
  178. default:
  179. rect2 = new Rect2();
  180. break;
  181. }
  182.  
  183. FillRect(tileMap, floorLayer, config.Ground, doorInfo.Cross + Vector2.One,
  184. new Vector2(GenerateDungeon.CorridorWidth - 2, GenerateDungeon.CorridorWidth - 2));
  185.  
  186. //墙壁
  187. if (dir1 == 0)
  188. {
  189. FullHorizontalGalleryWall(tileMap, floorLayer, middleLayer, topLayer, config, rect);
  190. }
  191. else
  192. {
  193. FullVerticalGalleryWall(tileMap, floorLayer, middleLayer, topLayer, config, rect);
  194. }
  195.  
  196. if (dir2 == 0)
  197. {
  198. FullHorizontalGalleryWall(tileMap, floorLayer, middleLayer, topLayer, config, rect2);
  199. }
  200. else
  201. {
  202. FullVerticalGalleryWall(tileMap, floorLayer, middleLayer, topLayer, config, rect2);
  203. }
  204.  
  205. if ((doorDir1 == DoorDirection.N && doorDir2 == DoorDirection.E) || //↑→
  206. (doorDir2 == DoorDirection.N && doorDir1 == DoorDirection.E))
  207. {
  208. FillRect(tileMap, topLayer, config.OUT_RT,
  209. doorInfo.Cross + new Vector2(0, GenerateDungeon.CorridorWidth - 1),
  210. Vector2.One);
  211. FillRect(tileMap, topLayer, config.IN_RT, doorInfo.Cross + new Vector2(GenerateDungeon.CorridorWidth - 1, 0),
  212. Vector2.One);
  213. FillRect(tileMap, middleLayer, config.T, doorInfo.Cross, new Vector2(GenerateDungeon.CorridorWidth - 1, 1));
  214. FillRect(tileMap, topLayer, config.R, doorInfo.Cross + new Vector2(GenerateDungeon.CorridorWidth - 1, 1),
  215. new Vector2(1, GenerateDungeon.CorridorWidth - 1));
  216. }
  217. else if ((doorDir1 == DoorDirection.E && doorDir2 == DoorDirection.S) || //→↓
  218. (doorDir2 == DoorDirection.E && doorDir1 == DoorDirection.S))
  219. {
  220. FillRect(tileMap, middleLayer, config.OUT_RB, doorInfo.Cross, Vector2.One);
  221. FillRect(tileMap, topLayer, config.IN_RB,
  222. doorInfo.Cross + new Vector2(GenerateDungeon.CorridorWidth - 1,
  223. GenerateDungeon.CorridorWidth - 1),
  224. Vector2.One);
  225. FillRect(tileMap, topLayer, config.R, doorInfo.Cross + new Vector2(GenerateDungeon.CorridorWidth - 1, 0),
  226. new Vector2(1, GenerateDungeon.CorridorWidth - 1));
  227. FillRect(tileMap, topLayer, config.B, doorInfo.Cross + new Vector2(0, GenerateDungeon.CorridorWidth - 1),
  228. new Vector2(GenerateDungeon.CorridorWidth - 1, 1));
  229. }
  230. else if ((doorDir1 == DoorDirection.S && doorDir2 == DoorDirection.W) || //↓←
  231. (doorDir2 == DoorDirection.S && doorDir1 == DoorDirection.W))
  232. {
  233. FillRect(tileMap, middleLayer, config.OUT_LB,
  234. doorInfo.Cross + new Vector2(GenerateDungeon.CorridorWidth - 1, 0), Vector2.One);
  235. FillRect(tileMap, topLayer, config.IN_LB, doorInfo.Cross + new Vector2(0, GenerateDungeon.CorridorWidth - 1),
  236. Vector2.One);
  237. FillRect(tileMap, topLayer, config.L, doorInfo.Cross, new Vector2(1, GenerateDungeon.CorridorWidth - 1));
  238. FillRect(tileMap, topLayer, config.B, doorInfo.Cross + new Vector2(1, GenerateDungeon.CorridorWidth - 1),
  239. new Vector2(GenerateDungeon.CorridorWidth - 1, 1));
  240. }
  241. else if ((doorDir1 == DoorDirection.W && doorDir2 == DoorDirection.N) || //←↑
  242. (doorDir2 == DoorDirection.W && doorDir1 == DoorDirection.N))
  243. {
  244. FillRect(tileMap, topLayer, config.OUT_LT,
  245. doorInfo.Cross + new Vector2(GenerateDungeon.CorridorWidth - 1,
  246. GenerateDungeon.CorridorWidth - 1),
  247. Vector2.One);
  248. FillRect(tileMap, topLayer, config.IN_LT, doorInfo.Cross, Vector2.One);
  249. FillRect(tileMap, middleLayer, config.T, doorInfo.Cross + new Vector2(1, 0),
  250. new Vector2(GenerateDungeon.CorridorWidth - 1, 1));
  251. FillRect(tileMap, topLayer, config.L, doorInfo.Cross + new Vector2(0, 1),
  252. new Vector2(1, GenerateDungeon.CorridorWidth - 1));
  253. }
  254.  
  255. //在房间墙上开洞
  256. switch (doorDir1)
  257. {
  258. case DoorDirection.E: //→
  259. ClearRect(tileMap, topLayer, doorInfo.OriginPosition + new Vector2(-1, 1),
  260. new Vector2(1, rect.Size.Y - 2));
  261. FillRect(tileMap, floorLayer, config.Ground, doorInfo.OriginPosition + new Vector2(-1, 1),
  262. new Vector2(1, rect.Size.Y - 2));
  263. break;
  264. case DoorDirection.W: //←
  265. ClearRect(tileMap, topLayer, doorInfo.OriginPosition + new Vector2(0, 1),
  266. new Vector2(1, rect.Size.Y - 2));
  267. FillRect(tileMap, floorLayer, config.Ground, doorInfo.OriginPosition + new Vector2(0, 1),
  268. new Vector2(1, rect.Size.Y - 2));
  269. break;
  270. case DoorDirection.S: //↓
  271. ClearRect(tileMap, topLayer, doorInfo.OriginPosition + new Vector2(1, -1),
  272. new Vector2(rect.Size.X - 2, 1));
  273. FillRect(tileMap, floorLayer, config.Ground, doorInfo.OriginPosition + new Vector2(1, -1),
  274. new Vector2(rect.Size.X - 2, 1));
  275. break;
  276. case DoorDirection.N: //↑
  277. ClearRect(tileMap, middleLayer, doorInfo.OriginPosition + new Vector2(1, 2),
  278. new Vector2(rect.Size.X - 2, 1));
  279. FillRect(tileMap, floorLayer, config.Ground, doorInfo.OriginPosition + new Vector2(1, 0),
  280. new Vector2(rect.Size.X - 2, 1));
  281. break;
  282. }
  283.  
  284. switch (doorDir2)
  285. {
  286. case DoorDirection.E: //→
  287. ClearRect(tileMap, topLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(-1, 1),
  288. new Vector2(1, rect2.Size.Y - 2));
  289. FillRect(tileMap, floorLayer, config.Ground, doorInfo.ConnectDoor.OriginPosition + new Vector2(-1, 1),
  290. new Vector2(1, rect2.Size.Y - 2));
  291. break;
  292. case DoorDirection.W: //←
  293. ClearRect(tileMap, topLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(0, 1),
  294. new Vector2(1, rect2.Size.Y - 2));
  295. FillRect(tileMap, floorLayer, config.Ground, doorInfo.ConnectDoor.OriginPosition + new Vector2(0, 1),
  296. new Vector2(1, rect2.Size.Y - 2));
  297. break;
  298. case DoorDirection.S: //↓
  299. ClearRect(tileMap, topLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, -1),
  300. new Vector2(rect2.Size.X - 2, 1));
  301. FillRect(tileMap, floorLayer, config.Ground, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, -1),
  302. new Vector2(rect2.Size.X - 2, 1));
  303. break;
  304. case DoorDirection.N: //↑
  305. ClearRect(tileMap, middleLayer, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, 0),
  306. new Vector2(rect2.Size.X - 2, 1));
  307. FillRect(tileMap, floorLayer, config.Ground, doorInfo.ConnectDoor.OriginPosition + new Vector2(1, 0),
  308. new Vector2(rect2.Size.X - 2, 1));
  309. break;
  310. }
  311. }
  312. }
  313. }
  314. }
  315.  
  316. private static void FillRect(TileMap tileMap, int layer, TileCellInfo info, Vector2 pos, Vector2 size)
  317. {
  318. for (int i = 0; i < size.X; i++)
  319. {
  320. for (int j = 0; j < size.Y; j++)
  321. {
  322. //tileMap.SetCell((int)pos.X + i, (int)pos.Y + j, info.Id, false, false, false, info.AutotileCoord);
  323. tileMap.SetCell(layer, new Vector2I((int)pos.X + i, (int)pos.Y + j), 1, info.AutotileCoord);
  324. //tileMap.SetCell(layer, new Vector2I(0, 0), 1, new Vector2I(0, 8), 0);
  325. }
  326. }
  327. }
  328.  
  329. private static void ClearRect(TileMap tileMap, int layer, Vector2 pos, Vector2 size)
  330. {
  331. for (int i = 0; i < size.X; i++)
  332. {
  333. for (int j = 0; j < size.Y; j++)
  334. {
  335. //tileMap.SetCell((int)pos.X + i, (int)pos.Y + j, -1);
  336. tileMap.SetCell(layer, new Vector2I((int)pos.X + i, (int)pos.Y + j), -1);
  337. }
  338. }
  339. }
  340.  
  341. private static void FullHorizontalGalleryWall(TileMap tileMap, int floorLayer, int middleLayer, int topLayer,
  342. AutoTileConfig config, Rect2 rect)
  343. {
  344. FillRect(tileMap, floorLayer, config.Ground, rect.Position + new Vector2(0, 1), rect.Size - new Vector2(0, 2));
  345. FillRect(tileMap, middleLayer, config.T, rect.Position, new Vector2(rect.Size.X, 1));
  346. FillRect(tileMap, topLayer, config.B, rect.Position + new Vector2(0, rect.Size.Y - 1), new Vector2(rect.Size.X, 1));
  347. //左
  348. ClearRect(tileMap, topLayer, rect.Position + new Vector2(-1, 1), new Vector2(1, rect.Size.Y - 2));
  349. FillRect(tileMap, floorLayer, config.Ground, rect.Position + new Vector2(-1, 1), new Vector2(1, rect.Size.Y - 2));
  350. //右
  351. ClearRect(tileMap, topLayer, rect.Position + new Vector2(rect.Size.X, 1), new Vector2(1, rect.Size.Y - 2));
  352. FillRect(tileMap, floorLayer, config.Ground, rect.Position + new Vector2(rect.Size.X, 1), new Vector2(1, rect.Size.Y - 2));
  353. }
  354.  
  355. private static void FullVerticalGalleryWall(TileMap tileMap, int floorLayer, int middleLayer, int topLayer,
  356. AutoTileConfig config, Rect2 rect)
  357. {
  358. FillRect(tileMap, floorLayer, config.Ground, rect.Position + new Vector2(1, 0), rect.Size - new Vector2(2, 0));
  359. FillRect(tileMap, topLayer, config.L, rect.Position, new Vector2(1, rect.Size.Y));
  360. FillRect(tileMap, topLayer, config.R, rect.Position + new Vector2(rect.Size.X - 1, 0), new Vector2(1, rect.Size.Y));
  361. //上
  362. ClearRect(tileMap, topLayer, rect.Position + new Vector2(1, -1), new Vector2(rect.Size.X - 2, 1));
  363. FillRect(tileMap, floorLayer, config.Ground, rect.Position + new Vector2(1, -1), new Vector2(rect.Size.X - 2, 1));
  364. //下
  365. ClearRect(tileMap, middleLayer, rect.Position + new Vector2(1, rect.Size.Y), new Vector2(rect.Size.X - 2, 1));
  366. FillRect(tileMap, floorLayer, config.Ground, rect.Position + new Vector2(1, rect.Size.Y), new Vector2(rect.Size.X - 2, 1));
  367. }
  368.  
  369. }