diff --git a/README.md b/README.md
index ee567a1..4a6a3e3 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,68 @@
-## Star History
+## Intro 简介
+
+Mint's new game.
+
+薄荷的新作游戏。
+
+A pixel cross-platform Roguelite game.
+
+一款像素的跨平台的Roguelite游戏。
+
+## Recent Development progress 近期研发进度
+
+| Task 任务 | status 状态 |
+| ----------------------------------------------------------- | ------------------ |
+| Randomly generated map 随机生成地图 | In progress 进行中 |
+| loot 战利品 | await 等待 |
+| Support still out of the knapsack system 支持仍出的背包系统 | await 等待 |
+
+## Run the project locally 在本地运行项目
+
+#### Download engine 下载引擎
+1. Download [Godot Engine .Net](https://godotengine.org/).
+
+ 下载[Godot Engine .Net](https://godotengine.org/)。
+
+ After downloading the engine, you will need to download an additional export template to export as an executable program.
+
+ 下载引擎后,您需要额外下载导出模板才能导出为可执行程序。
+
+2. Download [.NetSDK](https://dotnet.microsoft.com/download).
+
+ 下载 [.NetSDK](https://dotnet.microsoft.com/download).
+
+#### Clone project 克隆项目
+
+Enter the following command in your working directory:
+
+在您的工作目录输入以下指令:
+
+```
+git clone https://github.com/Cold-Mint/Traveller.git
+```
+
+## Participate in translation 参与翻译
+
+The project is prepared for localization at the beginning of writing. You can edit the csv file in the locals directory. To modify and add new translations.
+
+此项目在编写之初就为本地化做好了准备。您可以编辑locals目录下的csv文件。来修改和添加新的翻译。
+
+## License 许可证
+
+[GPL-3.0 license](LICENSE)
+
+Chinese translation version:[GPL-3.0 license 简体中文](LICENSE_ZH)
+
+查看协议的中文翻译版本:[GPL-3.0 license 简体中文](LICENSE_ZH)
+
+Support commercial, anyone can modify, build, and sell or distribute for free. For all derivative versions of this project, under the GPL, you shall **retain the author copyright** and **publish the modified source code**.
+
+支持商用,任何人可修改,构建,并用于售卖或免费发布。对于此项目的所有衍生版本,根据GPL协议,您应当**保留作者版权**,以及**公开修改后的源代码**。
+
+> Note: You have the right to sell the modified version, but not the original.
+>
+> 注意:您有权售卖修改后的版本,但不能售卖原版。
+
+## Star History 点赞历史
[![Star History Chart](https://api.star-history.com/svg?repos=Cold-Mint/Traveller&type=Date)](https://star-history.com/#Cold-Mint/Traveller&Date)
\ No newline at end of file
diff --git a/locals/Error.csv b/locals/Error.csv
index fca2966..90bdb00 100644
--- a/locals/Error.csv
+++ b/locals/Error.csv
@@ -4,6 +4,4 @@ missing_parameters,缺少参数。,Missing parameters.,パラメータが不足
room_root_node_must_be_node2d,房间根节点必须是 Node2D。,Room root node must be Node2D.,ルートノードはNode2Dでなければなりません。
width_or_height_of_room_slot_must_be_1,房间槽的宽度或高度必须为1。,The width or height of the room slot must be 1.,部屋の溝の幅または高さは1でなければなりません。
connected_room_timeout,连接房间超时。,Connecting the room timed out.,接続部屋はタイムアウトです。
-projectiles_is_empty,未设置抛射体。,The projectile is not set.,射出体は設置されていません。
-map_generator_is_not_set_up,未设置地图生成器。,Map generator is not set up.,マップ生成器は設置されていません。
-map_generator_is_not_configured,地图生成器没有有效配置。,Map Generator is not configured.,地図生成器は機能していません。
\ No newline at end of file
+projectiles_is_empty,未设置抛射体。,The projectile is not set.,射出体は設置されていません。
\ No newline at end of file
diff --git a/locals/Error.en.translation b/locals/Error.en.translation
index 9d1983d..6bd3e94 100644
Binary files a/locals/Error.en.translation and b/locals/Error.en.translation differ
diff --git a/locals/Error.jp.translation b/locals/Error.jp.translation
index e938919..a8edd94 100644
Binary files a/locals/Error.jp.translation and b/locals/Error.jp.translation differ
diff --git a/locals/Error.zh.translation b/locals/Error.zh.translation
index 1a786bb..701d03f 100644
Binary files a/locals/Error.zh.translation and b/locals/Error.zh.translation differ
diff --git a/scripts/Config.cs b/scripts/Config.cs
index 70d77dc..1247775 100644
--- a/scripts/Config.cs
+++ b/scripts/Config.cs
@@ -333,6 +333,15 @@ public static class Config
public const int Platform = 6;
public const int Mob = 7;
}
+
+ public class RoomDataTag
+ {
+ ///
+ /// Mark the starting room
+ /// 起点房间的标记
+ ///
+ public const string StartingRoom = "StartingRoom";
+ }
///
/// Specify the type of damage used in the game
diff --git a/scripts/levelGraphEditor/RoomNodeData.cs b/scripts/levelGraphEditor/RoomNodeData.cs
index bc647f4..4b5aa4d 100644
--- a/scripts/levelGraphEditor/RoomNodeData.cs
+++ b/scripts/levelGraphEditor/RoomNodeData.cs
@@ -1,4 +1,6 @@
-namespace ColdMint.scripts.levelGraphEditor;
+using System.Linq;
+
+namespace ColdMint.scripts.levelGraphEditor;
public class RoomNodeData
{
@@ -7,4 +9,18 @@ public class RoomNodeData
public string? Description { get; set; }
public string[]? RoomTemplateSet { get; set; }
+
+ public string[]? Tags { get; set; }
+
+
+ ///
+ /// Whether a tag is held
+ /// 是否持有某个标签
+ ///
+ ///
+ ///
+ public bool HasTag(string tag)
+ {
+ return Tags != null && Tags.Any(t => t == tag);
+ }
}
\ No newline at end of file
diff --git a/scripts/loader/sceneLoader/GameSceneLoader.cs b/scripts/loader/sceneLoader/GameSceneLoader.cs
index d48f4f3..549064e 100644
--- a/scripts/loader/sceneLoader/GameSceneLoader.cs
+++ b/scripts/loader/sceneLoader/GameSceneLoader.cs
@@ -3,7 +3,6 @@ using ColdMint.scripts.character;
using ColdMint.scripts.debug;
using ColdMint.scripts.inventory;
using ColdMint.scripts.map;
-using ColdMint.scripts.map.interfaces;
using ColdMint.scripts.map.room;
using ColdMint.scripts.map.roomHolder;
using ColdMint.scripts.map.RoomPlacer;
@@ -15,8 +14,6 @@ namespace ColdMint.scripts.loader.sceneLoader;
public partial class GameSceneLoader : SceneLoaderTemplate
{
- private IMapGenerator? _mapGenerator;
- private IMapGeneratorConfig? _mapGeneratorConfig;
public override Task InitializeData()
{
@@ -32,77 +29,11 @@ public partial class GameSceneLoader : SceneLoaderTemplate
//加载武器容器
var weaponContainer = GetNode("WeaponContainer");
GameSceneNodeHolder.WeaponContainer = weaponContainer;
-
- _mapGenerator = new MapGenerator();
- _mapGenerator.TimeOutPeriod = 15;
- _mapGenerator.RoomHolder = new RoomHolder();
- _mapGenerator.RoomSlotsMatcher = new RoomSlotsMatcher();
- var roomProvider = new RoomProvider();
- //添加房间模板
- var initialRoom = new RoomTemplate("res://prefab/roomTemplates/dungeon/initialRoom.tscn");
- var utilityRoom = new RoomTemplate("res://prefab/roomTemplates/dungeon/utilityRoom.tscn");
- initialRoom.MaxNumber = 1;
- var horizontalCorridorWithSewer =
- new RoomTemplate("res://prefab/roomTemplates/dungeon/horizontalCorridorWithSewer.tscn");
- var horizontalCorridor = new RoomTemplate("res://prefab/roomTemplates/dungeon/horizontalCorridor.tscn");
- roomProvider.AddRoom(initialRoom);
- roomProvider.AddRoom(horizontalCorridorWithSewer);
- roomProvider.AddRoom(horizontalCorridor);
- roomProvider.AddRoom(utilityRoom);
- _mapGenerator.RoomProvider = roomProvider;
-
- var roomPlacer = new RoomPlacer();
- _mapGeneratorConfig = new MapGeneratorConfig(GetNode("MapRoot"), 1);
- roomPlacer.MapGeneratorConfig = _mapGeneratorConfig;
- _mapGenerator.RoomPlacer = roomPlacer;
return Task.CompletedTask;
}
public override async Task LoadScene()
{
- if (_mapGenerator == null)
- {
- LogCat.LogError("map_generator_is_not_set_up");
- return;
- }
-
- if (_mapGeneratorConfig == null)
- {
- LogCat.LogError("map_generator_is_not_configured");
- return;
- }
-
- await _mapGenerator.Generate(_mapGeneratorConfig);
- var packedScene = GD.Load("res://prefab/entitys/Character.tscn");
- //Register players in the holder
- //在持有者内注册玩家
- var node2D = (Node2D)packedScene.Instantiate();
- if (node2D is Player player)
- {
- GameSceneNodeHolder.Player = player;
- //Allow the player to pick up items.
- //使玩家可以捡起物品。
- player.ItemContainer = GameSceneNodeHolder.HotBar;
- }
-
- var gameRoot = GetNode(".");
- gameRoot.AddChild(node2D);
- node2D.Position = new Vector2(55, 70);
-
- var delivererOfDarkMagicPackedScene = GD.Load("res://prefab/entitys/DelivererOfDarkMagic.tscn");
- var delivererOfDarkMagicPackedSceneNode2D = (Node2D)delivererOfDarkMagicPackedScene.Instantiate();
- gameRoot.AddChild(delivererOfDarkMagicPackedSceneNode2D);
- delivererOfDarkMagicPackedSceneNode2D.Position = new Vector2(70, 70);
-
- //Load a weapon
- //加载武器
- var w = GD.Load("res://prefab/weapons/staffOfTheUndead.tscn");
- for (int i = 0; i < 3; i++)
- {
- var wn = (Node2D)w.Instantiate();
- wn.Position = new Vector2(55, 90);
- var weaponContainer = GameSceneNodeHolder.WeaponContainer;
- weaponContainer?.AddChild(wn);
- }
+
}
}
\ No newline at end of file
diff --git a/scripts/loader/uiLoader/LevelGraphEditorLoader.cs b/scripts/loader/uiLoader/LevelGraphEditorLoader.cs
index a333382..edd842a 100644
--- a/scripts/loader/uiLoader/LevelGraphEditorLoader.cs
+++ b/scripts/loader/uiLoader/LevelGraphEditorLoader.cs
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
-using ColdMint.scripts.debug;
using ColdMint.scripts.levelGraphEditor;
+using ColdMint.scripts.nodeBinding;
using ColdMint.scripts.serialization;
using ColdMint.scripts.utils;
using Godot;
@@ -17,41 +17,18 @@ namespace ColdMint.scripts.loader.uiLoader;
///
public partial class LevelGraphEditorLoader : UiLoaderTemplate
{
- private GraphEdit? _graphEdit;
-
- ///
- /// Button to display the room creation panel.
- /// 用于展示房间创建面板的按钮。
- ///
- private Button? _showCreateRoomPanelButton;
-
- private PackedScene? _roomNodeScene;
- private Panel? _createOrEditorPanel;
- private Button? _hideCreateRoomPanelButton;
- private LineEdit? _roomNameLineEdit;
- private LineEdit? _roomDescriptionLineEdit;
- private Button? _createRoomButton;
- private Button? _returnButton;
private string? _defaultRoomName;
+ private readonly LevelGraphEditorBinding _nodeBinding = new LevelGraphEditorBinding();
+
///
/// Index of the room
/// 房间的索引
///
private int _roomIndex = 1;
- private TextEdit? _roomTemplateCollectionTextEdit;
- private Label? _roomTemplateTipsLabel;
- private Button? _showSavePanelButton;
- private Button? _openExportFolderButton;
- private HBoxContainer? _hBoxContainer;
- private Panel? _saveOrLoadPanel;
- private Button? _cancelButton;
- private Button? _actionButton;
- private Label? _saveOrLoadPanelTitleLabel;
- private LineEdit? _fileNameLineEdit;
- private Button? _showLoadPanelButton;
- private Button? _deleteSelectedNodeButton;
+ private PackedScene? _roomNodeScene;
+
private readonly List _selectedNodes = new List();
///
@@ -89,38 +66,18 @@ public partial class LevelGraphEditorLoader : UiLoaderTemplate
public override void InitializeUi()
{
base.InitializeUi();
- _roomTemplateTipsLabel = GetNode
private void HideCreateRoomPanel()
{
- if (_graphEdit != null)
+ if (_nodeBinding.GraphEdit != null)
{
- _graphEdit.Visible = true;
+ _nodeBinding.GraphEdit.Visible = true;
}
- if (_createOrEditorPanel != null)
+ if (_nodeBinding.CreateOrEditorPanel != null)
{
- _createOrEditorPanel.Visible = false;
+ _nodeBinding.CreateOrEditorPanel.Visible = false;
}
- if (_hBoxContainer != null)
+ if (_nodeBinding.HBoxContainer != null)
{
- _hBoxContainer.Visible = true;
+ _nodeBinding.HBoxContainer.Visible = true;
}
}
}
\ No newline at end of file
diff --git a/scripts/map/ILayoutStrategy.cs b/scripts/map/ILayoutStrategy.cs
new file mode 100644
index 0000000..0bbe1d7
--- /dev/null
+++ b/scripts/map/ILayoutStrategy.cs
@@ -0,0 +1,14 @@
+using System.Threading.Tasks;
+using ColdMint.scripts.levelGraphEditor;
+
+namespace ColdMint.scripts.map;
+
+public interface ILayoutStrategy
+{
+ ///
+ /// Get layout
+ /// 获取布局图
+ ///
+ ///
+ public Task GetLayout();
+}
\ No newline at end of file
diff --git a/scripts/map/MapGenerator.cs b/scripts/map/MapGenerator.cs
index 5994ee6..03daf44 100644
--- a/scripts/map/MapGenerator.cs
+++ b/scripts/map/MapGenerator.cs
@@ -1,110 +1,60 @@
-using System;
-using System.Threading.Tasks;
-using ColdMint.scripts.debug;
-using ColdMint.scripts.map.interfaces;
-using ColdMint.scripts.map.room;
-using ColdMint.scripts.map.RoomPlacer;
-using Godot;
+using System.Threading.Tasks;
+using ColdMint.scripts.levelGraphEditor;
namespace ColdMint.scripts.map;
-public class MapGenerator : IMapGenerator
+///
+/// Map generator
+/// 地图生成器
+///
+///
+///Responsible for the overall map generation process control
+///负责地图的整体生成流程控制
+///
+public static class MapGenerator
{
- public int TimeOutPeriod { get; set; }
- public IRoomSlotsMatcher? RoomSlotsMatcher { get; set; }
- public IRoomHolder? RoomHolder { get; set; }
+ ///
+ /// Layout map selection strategy
+ /// 布局图选择策略
+ ///
+ private static ILayoutStrategy? _layoutStrategy;
- public IRoomPlacer? RoomPlacer { get; set; }
-
- public IRoomProvider? RoomProvider { get; set; }
-
- public async Task Generate(IMapGeneratorConfig mapGeneratorConfig)
+ public static ILayoutStrategy? LayoutStrategy
{
- if (RoomPlacer == null || RoomHolder == null || RoomProvider == null || RoomSlotsMatcher == null ||
- RoomProvider.InitialRoom == null)
+ get => _layoutStrategy;
+ set => _layoutStrategy = value;
+ }
+
+ ///
+ /// Generating a map
+ /// 生成地图
+ ///
+ public static async Task GenerateMap()
+ {
+ if (_layoutStrategy == null)
{
- PrintMissingParametersError();
return;
}
- try
+ //Get the layout data
+ //拿到布局图数据
+ var levelGraphEditorSaveData = await _layoutStrategy.GetLayout();
+ //Finding the starting room
+ //查找起点房间
+ if (levelGraphEditorSaveData.RoomNodeDataList == null || levelGraphEditorSaveData.RoomNodeDataList.Count == 0)
{
- var roomPlacerConfig = new RoomPlacerConfig();
- //获取原点
- var origin = Vector2.Zero;
- //在提供者哪里获取房间,并放置他(首次拿初始房间)
- var originRoom =
- RoomFactory.CreateRoom(RoomProvider.InitialRoom.RoomResPath);
- await PlaceRoom(origin, originRoom);
- var endTime = DateTime.Now + TimeSpan.FromSeconds(TimeOutPeriod);
- while (RoomHolder.PlacedRoomNumber < mapGeneratorConfig.RoomCount)
- {
- if (DateTime.Now > endTime)
- {
- LogCat.LogError("connected_room_timeout");
- break;
- }
-
- //我们会一直尝试放置房间,直到达到指定的数量
- var roomRes = RoomProvider.GetRoomRes(RoomHolder.PlacedRoomNumber, mapGeneratorConfig);
- if (roomRes == null)
- {
- continue;
- }
-
- var newRoom =
- RoomFactory.CreateRoom(roomRes
- .RoomResPath);
- if (await RoomSlotsMatcher.IsMatch(RoomHolder.LastRoom, newRoom))
- {
- // LogCat.Log("匹配成功" + RoomSlotsMatcher.LastMatchedMainSlot.DistanceToMidpointOfRoom[0] + " " +
- // RoomSlotsMatcher.LastMatchedMainSlot.DistanceToMidpointOfRoom[1] + "到" +
- // RoomSlotsMatcher.LastMatchedMinorSlot.DistanceToMidpointOfRoom[0] + " " +
- // RoomSlotsMatcher.LastMatchedMinorSlot.DistanceToMidpointOfRoom[1]);
- await PlaceRoom(
- await RoomPlacer.CalculatedPosition(originRoom, newRoom, RoomSlotsMatcher.LastMatchedMainSlot,
- RoomSlotsMatcher.LastMatchedMinorSlot, roomPlacerConfig), newRoom);
- originRoom = newRoom;
- }
- }
- }
- catch (Exception e)
- {
- LogCat.WhenCaughtException(e);
- }
- }
-
- ///
- /// PrintMissingParametersError
- /// 打印缺少参数错误
- ///
- private void PrintMissingParametersError()
- {
- LogCat.LogError("missing_parameters");
- }
-
- ///
- /// PlaceRoom
- /// 放置房间
- ///
- ///
- ///
- ///
- private async Task PlaceRoom(Vector2 position, IRoom room)
- {
- if (RoomPlacer == null || RoomHolder == null)
- {
- return false;
+ return;
}
- if (await RoomPlacer.PlaceRoom(position, room))
+ var startRoomNodeData = levelGraphEditorSaveData.RoomNodeDataList.Find(roomNodeData =>
+ roomNodeData.HasTag(Config.RoomDataTag.StartingRoom));
+ if (startRoomNodeData == null)
{
- RoomHolder.AddRoom(room);
- // LogCat.Log("我要放置房间,但是成功");
- return true;
+ //Can't find the starting room
+ //找不到起点房间
+ return;
}
-
- // LogCat.Log("我要放置房间,但是失败了");
- return false;
+ //The starting room is regarded as the root node, and the map is generated from the root node to the leaf node like the tree structure.
+ //TODO:将起点房间看作根节点,像树结构一样,从根节点到叶节点生成地图。
}
}
\ No newline at end of file
diff --git a/scripts/map/interfaces/IMapGenerator.cs b/scripts/map/interfaces/IMapGenerator.cs
deleted file mode 100644
index 0c0db87..0000000
--- a/scripts/map/interfaces/IMapGenerator.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System.Threading.Tasks;
-
-namespace ColdMint.scripts.map.interfaces;
-
-public interface IMapGenerator
-{
- ///
- /// Setting the timeout period
- /// 设置超时时间
- ///
- ///
- ///Causes the engine to terminate generation after a certain amount of time.(Unit: second)
- ///使引擎超过一定时间后终止生成。(单位:秒)
- ///
- public int TimeOutPeriod { get; set; }
-
- public IRoomSlotsMatcher? RoomSlotsMatcher { get; set; }
- public IRoomHolder? RoomHolder { get; set; }
- public IRoomPlacer? RoomPlacer { get; set; }
-
- public IRoomProvider? RoomProvider { get; set; }
-
- Task Generate(IMapGeneratorConfig mapGeneratorConfig);
-}
\ No newline at end of file
diff --git a/scripts/nodeBinding/INodeBinding.cs b/scripts/nodeBinding/INodeBinding.cs
new file mode 100644
index 0000000..6bb93fb
--- /dev/null
+++ b/scripts/nodeBinding/INodeBinding.cs
@@ -0,0 +1,12 @@
+using Godot;
+
+namespace ColdMint.scripts.nodeBinding;
+
+///
+/// Node binding
+/// 节点绑定
+///
+public interface INodeBinding
+{
+ void Binding(Node root);
+}
\ No newline at end of file
diff --git a/scripts/nodeBinding/LevelGraphEditorBinding.cs b/scripts/nodeBinding/LevelGraphEditorBinding.cs
new file mode 100644
index 0000000..2af207b
--- /dev/null
+++ b/scripts/nodeBinding/LevelGraphEditorBinding.cs
@@ -0,0 +1,56 @@
+using Godot;
+
+namespace ColdMint.scripts.nodeBinding;
+
+public class LevelGraphEditorBinding : INodeBinding
+{
+ public GraphEdit? GraphEdit;
+
+ ///
+ /// Button to display the room creation panel.
+ /// 用于展示房间创建面板的按钮。
+ ///
+ public Button? ShowCreateRoomPanelButton;
+
+ public Panel? CreateOrEditorPanel;
+ public Button? HideCreateRoomPanelButton;
+ public LineEdit? RoomNameLineEdit;
+ public LineEdit? RoomDescriptionLineEdit;
+ public Button? CreateRoomButton;
+ public Button? ReturnButton;
+ public TextEdit? RoomTemplateCollectionTextEdit;
+ public Label? RoomTemplateTipsLabel;
+ public Button? ShowSavePanelButton;
+ public Button? OpenExportFolderButton;
+ public HBoxContainer? HBoxContainer;
+ public Panel? SaveOrLoadPanel;
+ public Button? CancelButton;
+ public Button? ActionButton;
+ public Label? SaveOrLoadPanelTitleLabel;
+ public LineEdit? FileNameLineEdit;
+ public Button? ShowLoadPanelButton;
+ public Button? DeleteSelectedNodeButton;
+ public void Binding(Node root)
+ {
+ RoomTemplateTipsLabel = root.GetNode