diff --git a/docs/zh-CN/tutorials/basic-tutorial.md b/docs/zh-CN/tutorials/basic-tutorial.md index 44aaf43..8803b80 100644 --- a/docs/zh-CN/tutorials/basic-tutorial.md +++ b/docs/zh-CN/tutorials/basic-tutorial.md @@ -1,14 +1,38 @@ -# 基础教程 +# GFramework 基础教程 -这是一个完整的从零开始的教程,将带领你创建一个使用 GFramework 的简单的计数器应用。 +这是一个循序渐进的教程,将带你从零开始学习 GFramework,通过构建一个计数器应用来理解框架的核心概念和最佳实践。 ## 目录 +### 第一部分:入门准备 + - [环境准备](#环境准备) -- [项目创建](#项目创建) -- [项目初始化](#项目初始化) -- [功能实现](#功能实现) -- [测试验证](#测试验证) +- [GFramework 核心概念](#gframework-核心概念) + +### 第二部分:基础实践 + +- [创建第一个项目](#创建第一个项目) +- [实现基础计数器](#实现基础计数器) + +### 第三部分:架构深化 + +- [Model层设计](#model层设计) + +### 第四部分:架构完善 + +- [System层实现](#system层实现) +- [Utility层设计](#utility层设计) + +### 第五部分:架构整合 + +- [完整架构集成](#完整架构集成) + +### 第六部分:进阶理解 + +- [架构原理深入](#架构原理深入) +- [最佳实践总结](#最佳实践总结) + +--- ## 环境准备 @@ -46,7 +70,7 @@ dotnet --version dotnet new console -n TestProject cd TestProject -# 如果使用 Godot,添加 Godot 引用 +# 添加 GFramework 引用 dotnet add package GeWuYou.GFramework.Core dotnet add package GeWuYou.GFramework.Godot @@ -54,1310 +78,656 @@ dotnet add package GeWuYou.GFramework.Godot dotnet build ``` -## 项目创建 +--- -### 1. 创建新的 Godot 项目 +## GFramework 核心概念 -1. 打开 Godot 编辑器 +### MVC 架构模式简介 -2. 点击 "新建项目" +在传统的 MVC(Model-View-Controller)架构中: -3. 创建项目文件夹,命名为 "MyGFrameworkGame" +- **Model(模型)**: 管理应用程序的数据和业务逻辑 +- **View(视图)**: 负责数据的展示和用户界面 +- **Controller(控制器)**: 处理用户输入,协调 Model 和 View -4. 创建项目后初始化C#项目 +### GFramework 架构组件概述 - ![image-20260211210657387](assets/basic-tutorial/image-20260211210657387.png) - -### 2. 配置项目结构 - -在项目根目录创建以下文件夹结构: +GFramework 在传统 MVC 基础上进行了扩展,包含以下核心组件: +```mermaid +graph TD + A[GFramework Architecture] --> B[Model] + A --> C[View] + A --> D[Controller] + A --> E[System] + A --> F[Utility] + A --> G[EventBus] + + B --> B1[数据模型层] + C --> C1[视图层] + D --> D1[控制器层] + E --> E1[系统业务逻辑层] + F --> F1[工具服务层] + G --> G1[事件总线] ``` + +### 为什么选择事件驱动架构 + +传统的直接调用方式存在耦合问题: + +```csharp +// 传统方式 - 强耦合 +Model.Increment(); +View.UpdateDisplay(Model.Count); +``` + +事件驱动架构的优势: + +```csharp +// 事件驱动 - 松耦合 +Model.Increment(); // 只关心业务逻辑 +// View 通过事件订阅自动更新 +``` + +--- + +## 创建第一个项目 + +### 项目结构规划 + +创建以下文件夹结构: + +```text MyGFrameworkGame/ -├── sripts/ # 脚本 -├── scenes/ # 场景 -├── assets/ # 游戏资源 -├── global/ # 全局类 -└── project.godot +├── scripts/ # 脚本代码 +│ ├── architecture/ # 架构定义 +│ ├── model/ # 数据模型 +│ ├── system/ # 业务系统 +│ ├── utility/ # 工具服务 +│ ├── module/ # 模块定义 +│ └── app/ # 应用入口 +├── scenes/ # 场景文件 +├── assets/ # 游戏资源 +└── global/ # 全局类 ``` -当然,你也可以选择你喜欢的代码组织方式 +### 包管理配置 -### 3. 引入GFramework +推荐使用以下包配置: -一般我们有两种引入方式 - -第一种是使用命令的方式引入 - -```sh -# 核心能力(推荐最小起步) -dotnet add package GeWuYou.GFramework.Core -dotnet add package GeWuYou.GFramework.Core.Abstractions - -# 游戏扩展 -dotnet add package GeWuYou.GFramework.Game -dotnet add package GeWuYou.GFramework.Game.Abstractions - -# Godot 集成(仅 Godot 项目需要) -dotnet add package GeWuYou.GFramework.Godot - -# 源码生成器(可选,但推荐) -dotnet add package GeWuYou.GFramework.SourceGenerators -``` - -当然这样包太多了,太费劲了,因此可以通过下方的命令直接将Core和Game模块都引入到项目中,再通过另外两个引入godot支持和源代码生成器 - -```sh -# Core+Game +```bash +# 核心框架 dotnet add package GeWuYou.GFramework -# Godot + +# Godot 集成 dotnet add package GeWuYou.GFramework.Godot -# 源码生成器 + +# 源码生成器(可选但推荐) dotnet add package GeWuYou.GFramework.SourceGenerators ``` -第二种方法可以通过ide(比如VS和Rider) +### 基础场景搭建 -它们都提供NuGet管理,允许你基于图形界面来搜索并下载相关的NuGet包 +创建一个简单的 UI 场景: -![image-20260211211756993](assets/basic-tutorial/image-20260211211756993.png) +```text +Control (App) +├── VBoxContainer +│ ├── Label ("%Label") +│ ├── HBoxContainer +│ │ ├── Button ("%AddButton") +│ │ └── Button ("%SubButton") +``` -## 项目初始化 +--- -### 1. 定义游戏架构 +## 实现基础计数器 -创建 `scripts/architecture/GameArchitecture.cs`: +### 传统 MVC 实现方式 + +让我们先用传统方式实现一个简单的计数器: ```csharp -using GFramework.Godot.architecture; - -namespace MyGFrameworkGame.scripts.architecture; - -public class GameArchitecture : AbstractArchitecture -{ - protected override void InstallModules() - { - - } -} -``` - -游戏架构类提供一个InstallModules方法用于注册模块,模块可以看作是一个个相关的Model、System、Utility的集合,按照开发者的意愿进行组织。 - -这里以一个示例代码进行说明 - -```C# -using GFramework.Core.Abstractions.architecture; -using GFramework.Core.Abstractions.environment; -using GFramework.Godot.architecture; -using GFrameworkGodotTemplate.scripts.module; - -namespace GFrameworkGodotTemplate.scripts.core; - -/// -/// 游戏架构类,负责安装和管理游戏所需的各种模块 -/// 继承自AbstractArchitecture,用于构建游戏的整体架构体系 -/// -public sealed class GameArchitecture(IArchitectureConfiguration configuration, IEnvironment environment) - : AbstractArchitecture(configuration, environment) -{ - public IArchitectureConfiguration Configuration { get; set; } = configuration; - - /// - /// 安装游戏所需的各个功能模块 - /// 该方法在架构初始化时被调用,用于注册系统、模型和工具模块 - /// - protected override void InstallModules() - { - // 安装数据模型相关的Godot模块 - InstallModule(new ModelModule()); - // 安装系统相关的Godot模块 - InstallModule(new SystemModule()); - // 安装工具类相关的Godot模块 - InstallModule(new UtilityModule()); - // 安装状态相关的Godot模块 - InstallModule(new StateModule()); - } -} -``` - -从这里可以看到我们把 Model、 System、 Utility 进行了拆分,这是一种方式,使用这种方式的前提是,项目依赖不复杂,如果项目依赖复杂可能就得拆分多个Module来控制初始化顺序 - -### 2. 创建模型模块 - -创建 `scripts/module/ModelModule.cs`: - -```csharp -using GFramework.Core.Abstractions.architecture; -using GFramework.Game.architecture; - -namespace MyGFrameworkGame.scripts.module; - -public class ModelModule: AbstractModule -{ - public override void Install(IArchitecture architecture) - { - - } -} -``` - -这个Install(IArchitecture architecture)方法用于注册所需要的类即各种model - -> Model在框架中表示游戏的状态和数据。模型是简单的数据容器,它们公开描述游戏实体当前状态的属性。 - -这里以一个示例代码进行说明 - -```C# -using GFramework.Core.Abstractions.architecture; -using GFramework.Core.functional.pipe; -using GFramework.Game.Abstractions.data; -using GFramework.Game.architecture; -using GFramework.Game.setting; -using GFramework.Godot.setting; -using GFramework.Godot.setting.data; -using GFrameworkGodotTemplate.scripts.setting; - -namespace GFrameworkGodotTemplate.scripts.module; - - -/// -/// ModelModule 类继承自 AbstractModule,用于在架构中安装和注册模型。 -/// 该模块主要负责初始化设置相关的模型,并将其注册到架构中。 -/// -public class ModelModule : AbstractModule -{ - /// - /// 安装方法,用于将模型注册到指定的架构中。 - /// - /// IArchitecture 接口实例,表示当前的应用程序架构。 - public override void Install(IArchitecture architecture) - { - // 获取设置数据仓库的实例,用于后续模型的初始化 - var settingsDataRepository = architecture.Context.GetUtility()!; - - // 注册设置模型,并配置其应用器(Applicator) - architecture.RegisterModel( - new SettingsModel(new SettingDataLocationProvider(), settingsDataRepository) - .Also(it => - { - // 注册音频设置应用器,用于处理音频相关配置 - it.RegisterApplicator(new GodotAudioSettings(it, new AudioBusMap())) - // 注册图形设置应用器,用于处理图形相关配置 - .RegisterApplicator(new GodotGraphicsSettings(it)) - // 注册本地化设置应用器,用于处理语言和区域相关配置 - .RegisterApplicator(new GodotLocalizationSettings(it, new LocalizationMap())); - }) - ); - } -} - -``` - -可以看到这里把设置数据模型注册进了架构中 - -### 3. 创建系统模块 - -创建 `scripts/module/SystemModule.cs`: - -```C# -using GFramework.Core.Abstractions.architecture; -using GFramework.Game.architecture; - -namespace MyGFrameworkGame.scripts.module; - -public class SystemModule: AbstractModule -{ - public override void Install(IArchitecture architecture) - { - - } -} -``` - -这个Install(IArchitecture architecture)方法用于注册所需要的类即各种system - -> System 包含游戏的业务逻辑和规则。系统操作模型并实现核心机制,如战斗、物理、库存管理或进度系统。 - -这里以一个示例代码进行说明 - -```C# -using GFramework.Core.Abstractions.architecture; -using GFramework.Game.architecture; -using GFramework.Game.setting; -using GFrameworkGodotTemplate.scripts.core.scene; -using GFrameworkGodotTemplate.scripts.core.ui; - -namespace GFrameworkGodotTemplate.scripts.module; - -/// -/// 系统Godot模块类,负责安装和注册游戏所需的各种系统组件 -/// 继承自AbstractGodotModule,用于在游戏架构中集成系统功能 -/// -public class SystemModule : AbstractModule -{ - /// - /// 安装方法,用于向游戏架构注册各种系统组件 - /// - /// 游戏架构接口实例,用于注册系统 - public override void Install(IArchitecture architecture) - { - architecture.RegisterSystem(new UiRouter()); - architecture.RegisterSystem(new SceneRouter()); - architecture.RegisterSystem(new SettingsSystem()); - } -} -``` - -可以看到我们向框架里注册了ui路由,场景路由,设置系统,这便是系统模块的作用 - -### 4. 创建工具模块 - -创建 `scripts/module/UtilityModule.cs`: - -```C# -using GFramework.Core.Abstractions.architecture; -using GFramework.Game.architecture; - -namespace MyGFrameworkGame.scripts.module; - -public class UtilityModule: AbstractModule -{ - public override void Install(IArchitecture architecture) - { - - } -} -``` - -同理这个Install(IArchitecture architecture)方法用于注册所需要的类即各种utility - -> Utility 提供可在整个应用程序中使用的无状态辅助函数和算法——数学计算、路径查找、数据验证和其他纯函数。 - -这里以一个示例代码进行说明 - -```C# -using GFramework.Core.Abstractions.architecture; -using GFramework.Game.Abstractions.data; -using GFramework.Game.architecture; -using GFramework.Game.data; -using GFramework.Game.serializer; -using GFramework.Godot.scene; -using GFramework.Godot.storage; -using GFramework.Godot.ui; -using GFrameworkGodotTemplate.scripts.data; -using GFrameworkGodotTemplate.scripts.utility; using Godot; -namespace GFrameworkGodotTemplate.scripts.module; - -/// -/// 工具模块类,负责安装和管理游戏中的实用工具组件 -/// -public class UtilityModule : AbstractModule +public partial class App : Control { - /// - /// 安装模块到指定的游戏架构中 - /// - /// 要安装模块的目标游戏架构实例 - public override void Install(IArchitecture architecture) - { - architecture.RegisterUtility(new GodotUiRegistry()); - architecture.RegisterUtility(new GodotSceneRegistry()); - architecture.RegisterUtility(new GodotTextureRegistry()); - architecture.RegisterUtility(new GodotUiFactory()); - var jsonSerializer = new JsonSerializer(); - architecture.RegisterUtility(jsonSerializer); - var storage = new GodotFileStorage(jsonSerializer); - architecture.RegisterUtility(storage); - architecture.RegisterUtility(new UnifiedSettingsDataRepository(storage, jsonSerializer, - new DataRepositoryOptions - { - BasePath = ProjectSettings.GetSetting("application/config/save/setting_path").AsString(), - AutoBackup = true - })); - architecture.RegisterUtility(new SaveStorageUtility()); - } -} -``` + private Button _addButton => GetNode