diff --git a/DungeonShooting_Godot/src/framework/Grid.cs b/DungeonShooting_Godot/src/framework/Grid.cs index 782da26..7971d73 100644 --- a/DungeonShooting_Godot/src/framework/Grid.cs +++ b/DungeonShooting_Godot/src/framework/Grid.cs @@ -12,9 +12,14 @@ public bool Contains(int x, int y) { + if (_map.TryGetValue(x, out var value)) + { + return value.ContainsKey(y); + } + return false; } - + public void Set(int x, int y, T data) { if (_map.TryGetValue(x, out var value)) @@ -38,13 +43,50 @@ return default; } - public void AddRect(Vector2 pos, Vector2 size) + public void AddRect(Vector2 pos, Vector2 size, T data) { - + var x = (int)pos.x; + var y = (int)pos.y; + for (var i = 0; i < size.x; i++) + { + for (var j = 0; j < size.y; j++) + { + if (_map.TryGetValue(x + i, out var value)) + { + value[y + j] = data; + } + else + { + value = new Dictionary(); + value.Add(y + j, data); + _map.Add(x + i, value); + } + } + } } - public bool TestRect() + public bool RectCollision(Vector2 pos, Vector2 size) { - return true; + var x = (int)pos.x; + var y = (int)pos.y; + var w = (int)size.x; + var h = (int)size.y; + //先判断四个角 + if (Contains(x, y) || Contains(x + w, y) || Contains(x, y + h) || Contains(x + w, y + h)) + { + return true; + } + //逐个点判断 + for (int i = 1; i < w; i++) + { + for (int j = 0; j < h; j++) + { + if (Contains(x + i, y + j)) + { + return true; + } + } + } + return false; } } diff --git a/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs b/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs index 264a35c..e1fd172 100644 --- a/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs +++ b/DungeonShooting_Godot/src/framework/generate/GenerateDungeon.cs @@ -8,7 +8,12 @@ public class GenerateDungeon { public readonly TileMap TileMap; - + + private Grid _roomGrid = new Grid(); + private List _roomInfos = new List(); + private int _count = 0; + private int _maxCount = 3; + public GenerateDungeon(TileMap tileMap) { TileMap = tileMap; @@ -16,27 +21,9 @@ public void Generate() { - List roomInfos = new List(); - var x = 0; - var y = 0; - for (int i = 0; i < 10; i++) - { - var roomInfo = GenerateRoom(); - roomInfos.Add(roomInfo); - roomInfo.Position = new Vector2(x + 2, y + 2); - - if (Utils.RandBoolean()) - { - x = x + 2 + (int)roomInfo.Size.x; - } - else - { - y = y + 2 + (int)roomInfo.Size.y; - } - - } + GenerateRoom(null); - foreach (var info in roomInfos) + foreach (var info in _roomInfos) { //临时铺上地砖 var id = (int)TileMap.TileSet.GetTilesIds()[0]; @@ -50,13 +37,62 @@ } } - public RoomInfo GenerateRoom() + public void GenerateRoom(RoomInfo prevRoomInfo) { - var info = new RoomInfo(); - //房间大小 - info.Size = new Vector2(Utils.RandRange(5, 10), Utils.RandRange(5, 10)); + if (_count >= _maxCount) + { + return; + } + var pos = Vector2.Zero; + var size = new Vector2(Utils.RandRangeInt(5, 10), Utils.RandRangeInt(5, 10)); - return info; + if (prevRoomInfo != null) //表示这不是第一个房间, 就得判断当前位置下的房间是否被遮挡 + { + var dir = Utils.RandRangeInt(0, 3); //0上, 1右, 2下, 3左 + var space = Utils.RandRangeInt(3, 10); + int offset; + if (dir == 0 || dir == 2) + { + offset = Utils.RandRangeInt(-(int)prevRoomInfo.Size.y, (int)prevRoomInfo.Size.y); + } + else + { + offset = Utils.RandRangeInt(-(int)prevRoomInfo.Size.x, (int)prevRoomInfo.Size.x); + } + + if (dir == 0) + { + pos = new Vector2(prevRoomInfo.Position.x + offset, + prevRoomInfo.Position.y - prevRoomInfo.Size.y - space); + } + else if (dir == 1) + { + pos = new Vector2(prevRoomInfo.Position.x + prevRoomInfo.Size.y + space, prevRoomInfo.Position.y + offset - space); + } + else if (dir == 2) + { + pos = new Vector2(prevRoomInfo.Position.x + offset, prevRoomInfo.Position.y + space); + } + else if (dir == 3) + { + pos = new Vector2(prevRoomInfo.Position.x - prevRoomInfo.Size.x - space, + prevRoomInfo.Position.y + prevRoomInfo.Size.y + offset); + } + + if (_roomGrid.RectCollision(pos, size)) + { + return; + } + } + + + _count++; + var info = new RoomInfo(); + info.Size = size; + info.Position = pos; + _roomInfos.Add(info); + _roomGrid.AddRect(info.Position, info.Size, true); + GenerateRoom(info); } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/Utils.cs b/DungeonShooting_Godot/src/game/common/Utils.cs index 9bfa45e..8ee8ec3 100644 --- a/DungeonShooting_Godot/src/game/common/Utils.cs +++ b/DungeonShooting_Godot/src/game/common/Utils.cs @@ -35,4 +35,14 @@ return Mathf.FloorToInt(GD.Randf() * (min - max + 1) + max); return Mathf.FloorToInt(GD.Randf() * (max - min + 1) + min); } + + public static T RandChoose(params T[] list) + { + if (list.Length == 0) + { + return default; + } + + return list[list.Length - 1]; + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs b/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs index 88b1272..1026f5f 100644 --- a/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs +++ b/DungeonShooting_Godot/src/test/TestGenerateDungeon.cs @@ -14,12 +14,14 @@ public override void _Ready() { - GD.Randomize(); + //GD.Randomize(); _tileMap = GetNode(TileMapPath); _camera = GetNode(Camera); var temp = new GenerateDungeon(_tileMap); + var nowTicks = DateTime.Now.Ticks; temp.Generate(); + GD.Print("useTime: " + (DateTime.Now.Ticks - nowTicks) / 10000 + "毫秒"); } public override void _Process(float delta)