diff --git "a/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.md" "b/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.md" new file mode 100644 index 0000000..8c52557 --- /dev/null +++ "b/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.md" @@ -0,0 +1,14 @@ +### 2023-02-28 +进过数十天开发, 已经完成自定义房间功能, 支持配置连接门生成区域, 而不是像之前一样整个矩形外框都能生成门, 并且还做了在编辑器中可视化编辑连接们生成区域的功能
+所有的自定义房间放在`resource/map/tileMaps`, 路径下, 使用`automation`面板下的`打包地牢配置`即可将所有房间的配置信息整合到`RoomConfig.json`文件内, 方便代码获取房间数据
+在编辑器中添加`DungeonRoomTemplate`节点, 用于创建模板房间 + +### 2023-02-15 +第一篇开发日志, 后面会更加频繁更新日志
+用了大半年事件完成完成项目基础架构搭建, 已经包含的功能有: +* 所有物体的父物体为`ActivityObject`, 可以在编辑器中找到节点`ActivityObjectTemplate`来快速创建物体模板 +* 玩家, 敌人的基础移动, 拾起/扔掉武器, 武器袋存放武器, 切换武器, 手持武器开火, 换弹, +* 武器类别有近战/远程武器, 武器由属性类控制 +* ai行为逻辑, 包括自动寻路, 发现玩家后追踪玩家, 通知其它ai玩家位置, 射程足够时朝玩家射击, 在玩家周围徘徊, 没有武器/弹药时寻找可用的武器 +* 随机生成地牢, 地牢房间与房间由过道连接, 一个房间至少连接一个其它房间 +* 游戏中UI, 包括血条, 玩家手持武器, 武器弹药, 换弹进度, 拾起武器提示 \ No newline at end of file diff --git "a/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.txt" "b/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.txt" deleted file mode 100644 index e69de29..0000000 --- "a/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.txt" +++ /dev/null diff --git a/DungeonShooting_Godot/DungeonShooting.csproj b/DungeonShooting_Godot/DungeonShooting.csproj index cea5645..d2f5fb2 100644 --- a/DungeonShooting_Godot/DungeonShooting.csproj +++ b/DungeonShooting_Godot/DungeonShooting.csproj @@ -1,4 +1,4 @@ - + net6.0 true diff --git a/DungeonShooting_Godot/DungeonShooting.csproj.old b/DungeonShooting_Godot/DungeonShooting.csproj.old deleted file mode 100644 index cdcc424..0000000 --- a/DungeonShooting_Godot/DungeonShooting.csproj.old +++ /dev/null @@ -1,14 +0,0 @@ - - - net472 - - - - - - - - - - - \ No newline at end of file diff --git a/DungeonShooting_Godot/DungeonShooting.csproj.old.1 b/DungeonShooting_Godot/DungeonShooting.csproj.old.1 deleted file mode 100644 index dd1e7a3..0000000 --- a/DungeonShooting_Godot/DungeonShooting.csproj.old.1 +++ /dev/null @@ -1,6 +0,0 @@ - - - net6.0 - true - - \ No newline at end of file diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.cs b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.cs index c98af3c..d33af7d 100644 --- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.cs +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.cs @@ -1,6 +1,9 @@ #if TOOLS +using System; +using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.Json; using System.Text.RegularExpressions; using Godot; using File = System.IO.File; @@ -11,7 +14,7 @@ //支持后缀 private string[] suffix = { - ".png", ".jpg", ".txt", ".json", ".ini", ".tscn", ".tres", ".otf", ".gdshader", ".tmx", ".tsx", ".ogg", ".mp3", ".wav", ".svg" + ".png", ".jpg", ".txt", ".json", ".ini", ".tscn", ".tres", ".otf", ".gdshader", ".ogg", ".mp3", ".wav", ".svg" }; //排除第一层的文件夹 private string[] exclude = @@ -22,7 +25,9 @@ private string resultStr = ""; - //更新 ResourcePath + /// + /// 更新 ResourcePath + /// private void _on_Button_pressed() { resultStr = "/// \n" + @@ -56,6 +61,94 @@ GD.Print("ResourcePath.cs 写出完成!"); } + /// + /// 重新打包房间配置 + /// + private void _on_Button2_pressed() + { + //地图路径 + var tileDir = DungeonRoomTemplate.RoomTileDir; + //地图描述数据路径 + var tileDataDir = DungeonRoomTemplate.RoomTileDataDir; + + var tileDirInfo = new DirectoryInfo(tileDir); + var tileDataDirInfo = new DirectoryInfo(tileDataDir); + + //所有地图列表 + var mapList = new HashSet(); + + //收集所有名称 + var fileDataInfos = tileDataDirInfo.GetFiles(); + foreach (var fileInfo in fileDataInfos) + { + mapList.Add(RemoveExtension(fileInfo.Name)); + } + //收集所有名称 + var fileInfos = tileDirInfo.GetFiles(); + foreach (var fileInfo in fileInfos) + { + if (fileInfo.Extension == ".tscn") + { + mapList.Add(RemoveExtension(fileInfo.Name)); + } + } + + //剔除多余的 tile.json + var arrays = mapList.ToArray(); + foreach (var item in arrays) + { + if (!File.Exists(tileDir + item + ".tscn")) + { + mapList.Remove(item); + var filePath = tileDataDir + item + ".json"; + if (File.Exists(filePath)) + { + GD.Print($"未找到'{tileDir + item}.tscn', 删除配置文件: {filePath}"); + File.Delete(filePath); + } + } + } + + //手动生成缺失的 tile.json + foreach (var item in mapList) + { + if (!File.Exists(tileDataDir + item + ".json")) + { + var tscnName = tileDir + item + ".tscn"; + var packedScene = ResourceManager.Load(tscnName, false); + if (packedScene != null) + { + var dungeonRoomTemplate = packedScene.Instantiate(); + var usedRect = dungeonRoomTemplate.GetUsedRect(); + DungeonRoomTemplate.SaveConfig(new List(), usedRect.Position, usedRect.Size, item); + dungeonRoomTemplate.QueueFree(); + } + } + } + + var list = new List(); + //整合操作 + foreach (var item in mapList) + { + var configPath = tileDataDir + item + ".json"; + var configText = File.ReadAllText(configPath); + var roomInfo = DungeonRoomTemplate.DeserializeDungeonRoomInfo(configText); + var split = new DungeonRoomSplit(); + split.ScenePath = ToResPath(tileDir + item + ".tscn"); + split.ConfigPath = ToResPath(configPath); + split.RoomInfo = roomInfo; + list.Add(split); + } + + //写出配置 + var config = new JsonSerializerOptions(); + config.WriteIndented = true; + var text = JsonSerializer.Serialize(list, config); + File.WriteAllText(DungeonRoomTemplate.RoomTileConfigFile, text); + + GD.Print("地牢房间配置, 重新打包完成!"); + } + private void EachDir(DirectoryInfo directoryInfos) { var fileInfos = directoryInfos.GetFiles(); @@ -84,5 +177,23 @@ resultStr += $" public const string {field} = \"{resPath}\";\n"; } } + + private string ToResPath(string path) + { + var field = path.Substring(currDir.Length + 1); + field = field.Replace("\\", "/"); + return "res://" + field; + } + + private string RemoveExtension(string name) + { + var index = name.LastIndexOf(".", StringComparison.Ordinal); + if (index >= 0) + { + return name.Substring(0, index); + } + + return name; + } } #endif \ No newline at end of file diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.tscn b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.tscn index 89e7ef5..66d1942 100644 --- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.tscn +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.tscn @@ -1,34 +1,46 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=2 format=3 uid="uid://bygnukrvvm1vi"] -[ext_resource path="res://addons/dungeonShooting_plugin/Automation.cs" type="Script" id=1] +[ext_resource type="Script" path="res://addons/dungeonShooting_plugin/Automation.cs" id="1"] [node name="Automation" type="Control"] +layout_mode = 3 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -script = ExtResource( 1 ) +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1") [node name="ScrollContainer" type="ScrollContainer" parent="."] +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 [node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"] -offset_right = 1920.0 -offset_bottom = 35.0 +layout_mode = 2 size_flags_horizontal = 3 [node name="HBoxContainer" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"] -offset_right = 1920.0 -offset_bottom = 35.0 +layout_mode = 2 [node name="Label" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer"] -offset_right = 158.0 -offset_bottom = 35.0 +layout_mode = 2 text = "ResourcePath.cs" [node name="Button" type="Button" parent="ScrollContainer/VBoxContainer/HBoxContainer"] -offset_left = 162.0 -offset_right = 246.0 -offset_bottom = 35.0 +layout_mode = 2 text = "重新生成" +[node name="HBoxContainer2" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "地牢房间配置" + +[node name="Button" type="Button" parent="ScrollContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "重新打包" + [connection signal="pressed" from="ScrollContainer/VBoxContainer/HBoxContainer/Button" to="." method="_on_Button_pressed"] +[connection signal="pressed" from="ScrollContainer/VBoxContainer/HBoxContainer2/Button" to="." method="_on_Button2_pressed"] diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Map.svg b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Map.svg new file mode 100644 index 0000000..53529e1 --- /dev/null +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Map.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Map.svg.import b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Map.svg.import new file mode 100644 index 0000000..c664f8f --- /dev/null +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Map.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://downmhbbm43yu" +path="res://.godot/imported/Map.svg-dcee5d8c5d80d0921a3de443b022f3d9.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/dungeonShooting_plugin/Map.svg" +dest_files=["res://.godot/imported/Map.svg-dcee5d8c5d80d0921a3de443b022f3d9.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs index 89526b8..5d60ede 100644 --- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs @@ -22,6 +22,10 @@ var script = GD.Load