mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-23 03:04:29 +08:00
- 将标题从"架构模式最佳实践"改为"架构设计模式指南" - 添加全面的架构设计模式介绍和概述 - 新增MVC模式详细说明,包括概念、GFramework实现示例和最佳实践 - 新增MVVM模式详细说明,包括概念、GFramework实现示例和最佳实践 - 新增命令模式详细说明,包括概念、实现示例和撤销功能支持 - 新增查询模式详细说明,包括CQRS概念和复杂查询示例 - 新增事件驱动模式详细说明,包括事件定义和监听实现 - 新增依赖注入模式详细说明,包括构造函数注入示例 - 新增服务定位器模式详细说明,包括与依赖注入对比 - 新增对象池模式详细说明,包括通用对象池实现 - 新增状态模式详细说明,包括异步状态和状态机系统 - 补充模式选择与组合建议,针对小型、中型、大型项目提供不同方案 - 更新代码示例中的泛型语法格式,统一使用尖括号表示法
47 KiB
47 KiB
title, description
| title | description |
|---|---|
| 大型项目组织 | 学习如何使用 GFramework 组织和管理大型游戏项目 |
大型项目组织
学习目标
完成本教程后,你将能够:
- 理解大型游戏项目的组织原则
- 设计清晰的项目结构和模块划分
- 实现分层架构和依赖管理
- 使用模块化设计分离功能
- 建立代码组织规范和团队协作流程
- 应用最佳实践提高项目可维护性
前置条件
步骤 1: 项目结构设计
首先,让我们设计一个清晰的项目结构,将代码按功能和层次组织。
1.1 推荐的目录结构
MyLargeGame/
├── src/
│ ├── MyGame.Core/ # 核心层
│ │ ├── Architecture/ # 架构定义
│ │ │ ├── GameArchitecture.cs
│ │ │ └── GameContext.cs
│ │ ├── Constants/ # 常量定义
│ │ │ ├── GameConstants.cs
│ │ │ └── LayerConstants.cs
│ │ └── Extensions/ # 扩展方法
│ │ └── GameExtensions.cs
│ │
│ ├── MyGame.Domain/ # 领域层
│ │ ├── Models/ # 数据模型
│ │ │ ├── Player/
│ │ │ │ ├── PlayerModel.cs
│ │ │ │ └── PlayerStatsModel.cs
│ │ │ ├── Inventory/
│ │ │ │ ├── InventoryModel.cs
│ │ │ │ └── ItemModel.cs
│ │ │ └── Combat/
│ │ │ ├── CombatModel.cs
│ │ │ └── SkillModel.cs
│ │ ├── Events/ # 领域事件
│ │ │ ├── Player/
│ │ │ │ ├── PlayerLevelUpEvent.cs
│ │ │ │ └── PlayerHealthChangedEvent.cs
│ │ │ └── Combat/
│ │ │ └── DamageDealtEvent.cs
│ │ └── Enums/ # 枚举定义
│ │ ├── ItemType.cs
│ │ └── SkillType.cs
│ │
│ ├── MyGame.Application/ # 应用层
│ │ ├── Systems/ # 业务系统
│ │ │ ├── Player/
│ │ │ │ ├── PlayerSystem.cs
│ │ │ │ └── PlayerLevelSystem.cs
│ │ │ ├── Inventory/
│ │ │ │ └── InventorySystem.cs
│ │ │ └── Combat/
│ │ │ ├── CombatSystem.cs
│ │ │ └── SkillSystem.cs
│ │ ├── Commands/ # 命令
│ │ │ ├── Player/
│ │ │ │ └── MovePlayerCommand.cs
│ │ │ └── Inventory/
│ │ │ └── AddItemCommand.cs
│ │ ├── Queries/ # 查询
│ │ │ ├── Player/
│ │ │ │ └── GetPlayerStatsQuery.cs
│ │ │ └── Inventory/
│ │ │ └── GetItemsQuery.cs
│ │ └── Utilities/ # 工具类
│ │ ├── MathUtility.cs
│ │ └── PathfindingUtility.cs
│ │
│ ├── MyGame.Infrastructure/ # 基础设施层
│ │ ├── Data/ # 数据访问
│ │ │ ├── Repositories/
│ │ │ │ ├── PlayerRepository.cs
│ │ │ │ └── SaveRepository.cs
│ │ │ └── Serializers/
│ │ │ └── JsonGameSerializer.cs
│ │ ├── Resources/ # 资源管理
│ │ │ ├── AssetLoader.cs
│ │ │ └── ResourceCache.cs
│ │ └── Services/ # 外部服务
│ │ ├── AudioService.cs
│ │ └── NetworkService.cs
│ │
│ ├── MyGame.Presentation/ # 表现层
│ │ ├── Controllers/ # 控制器
│ │ │ ├── Player/
│ │ │ │ └── PlayerController.cs
│ │ │ └── UI/
│ │ │ └── UIController.cs
│ │ ├── Views/ # 视图
│ │ │ ├── HUD/
│ │ │ │ ├── HealthBarView.cs
│ │ │ │ └── MiniMapView.cs
│ │ │ └── Menus/
│ │ │ ├── MainMenuView.cs
│ │ │ └── InventoryView.cs
│ │ └── ViewModels/ # 视图模型
│ │ └── InventoryViewModel.cs
│ │
│ └── MyGame.Modules/ # 功能模块
│ ├── PlayerModule/
│ │ └── PlayerModule.cs
│ ├── CombatModule/
│ │ └── CombatModule.cs
│ ├── InventoryModule/
│ │ └── InventoryModule.cs
│ └── QuestModule/
│ └── QuestModule.cs
│
├── tests/
│ ├── MyGame.Core.Tests/
│ ├── MyGame.Domain.Tests/
│ └── MyGame.Application.Tests/
│
└── docs/
├── architecture.md
├── coding-standards.md
└── api/
结构说明:
- Core: 核心架构和基础设施,不依赖其他层
- Domain: 领域模型和业务规则,纯业务逻辑
- Application: 应用服务和用例,协调领域对象
- Infrastructure: 技术实现,如数据访问、资源加载
- Presentation: 表现层,处理用户交互和显示
- Modules: 功能模块,封装完整的功能单元
1.2 创建核心架构
using GFramework.Core.architecture;
using GFramework.Core.Abstractions.architecture;
namespace MyGame.Core.Architecture
{
/// <summary>
/// 游戏主架构
/// </summary>
public class GameArchitecture : Architecture
{
public static IArchitecture Interface { get; private set; }
protected override void Init()
{
Interface = this;
Console.WriteLine("初始化游戏架构...");
}
protected override void InstallModules()
{
// 模块将在步骤 3 中安装
Console.WriteLine("安装功能模块...");
}
}
}
步骤 2: 架构分层
实现清晰的分层架构,确保各层职责明确,依赖关系单向。
2.1 领域层 - 玩家模型
using GFramework.Core.model;
using GFramework.Core.property;
namespace MyGame.Domain.Models.Player
{
/// <summary>
/// 玩家数据模型
/// </summary>
public class PlayerModel : AbstractModel
{
// 基础属性
public BindableProperty<string> Name { get; } = new("Player");
public BindableProperty<int> Level { get; } = new(1);
public BindableProperty<int> Experience { get; } = new(0);
// 战斗属性
public BindableProperty<int> Health { get; } = new(100);
public BindableProperty<int> MaxHealth { get; } = new(100);
public BindableProperty<int> Mana { get; } = new(50);
public BindableProperty<int> MaxMana { get; } = new(50);
// 位置信息
public BindableProperty<float> PositionX { get; } = new(0f);
public BindableProperty<float> PositionY { get; } = new(0f);
public BindableProperty<float> PositionZ { get; } = new(0f);
protected override void OnInit()
{
Console.WriteLine($"玩家模型初始化: {Name.Value}");
// 监听等级变化
Level.Register(OnLevelChanged);
}
private void OnLevelChanged(int newLevel)
{
Console.WriteLine($"玩家升级到 {newLevel} 级");
// 升级时恢复生命值和法力值
Health.Value = MaxHealth.Value;
Mana.Value = MaxMana.Value;
}
/// <summary>
/// 受到伤害
/// </summary>
public void TakeDamage(int damage)
{
Health.Value = Math.Max(0, Health.Value - damage);
if (Health.Value == 0)
{
Console.WriteLine("玩家死亡");
}
}
/// <summary>
/// 获得经验
/// </summary>
public void GainExperience(int exp)
{
Experience.Value += exp;
// 检查是否升级
int expNeeded = GetExperienceForNextLevel();
if (Experience.Value >= expNeeded)
{
LevelUp();
}
}
private void LevelUp()
{
Level.Value++;
Experience.Value = 0;
// 提升属性
MaxHealth.Value += 10;
MaxMana.Value += 5;
}
private int GetExperienceForNextLevel()
{
return Level.Value * 100;
}
}
}
2.2 领域层 - 领域事件
using GFramework.Core.Abstractions.events;
namespace MyGame.Domain.Events.Player
{
/// <summary>
/// 玩家升级事件
/// </summary>
public record PlayerLevelUpEvent(int NewLevel, int OldLevel) : IEvent;
/// <summary>
/// 玩家生命值变化事件
/// </summary>
public record PlayerHealthChangedEvent(int NewHealth, int OldHealth, int MaxHealth) : IEvent;
/// <summary>
/// 玩家死亡事件
/// </summary>
public record PlayerDeathEvent(string Reason) : IEvent;
/// <summary>
/// 玩家位置变化事件
/// </summary>
public record PlayerPositionChangedEvent(float X, float Y, float Z) : IEvent;
}
2.3 应用层 - 玩家系统
using GFramework.Core.system;
using GFramework.Core.Abstractions.events;
using MyGame.Domain.Models.Player;
using MyGame.Domain.Events.Player;
namespace MyGame.Application.Systems.Player
{
/// <summary>
/// 玩家管理系统
/// </summary>
public class PlayerSystem : AbstractSystem
{
private PlayerModel _playerModel;
private IEventBus _eventBus;
protected override void OnInit()
{
// 获取依赖
_playerModel = this.GetModel<PlayerModel>();
_eventBus = this.GetService<IEventBus>();
// 监听玩家属性变化
_playerModel.Level.Register(OnLevelChanged);
_playerModel.Health.Register(OnHealthChanged);
Console.WriteLine("玩家系统初始化完成");
}
private void OnLevelChanged(int newLevel)
{
// 发布升级事件
_eventBus.Publish(new PlayerLevelUpEvent(newLevel, newLevel - 1));
}
private void OnHealthChanged(int newHealth)
{
// 发布生命值变化事件
_eventBus.Publish(new PlayerHealthChangedEvent(
newHealth,
_playerModel.Health.Value,
_playerModel.MaxHealth.Value
));
// 检查死亡
if (newHealth == 0)
{
_eventBus.Publish(new PlayerDeathEvent("生命值耗尽"));
}
}
/// <summary>
/// 移动玩家
/// </summary>
public void MovePlayer(float x, float y, float z)
{
_playerModel.PositionX.Value = x;
_playerModel.PositionY.Value = y;
_playerModel.PositionZ.Value = z;
_eventBus.Publish(new PlayerPositionChangedEvent(x, y, z));
}
/// <summary>
/// 治疗玩家
/// </summary>
public void HealPlayer(int amount)
{
int newHealth = Math.Min(
_playerModel.Health.Value + amount,
_playerModel.MaxHealth.Value
);
_playerModel.Health.Value = newHealth;
Console.WriteLine($"玩家恢复 {amount} 点生命值");
}
}
}
2.4 应用层 - 命令模式
using GFramework.Core.command;
using MyGame.Domain.Models.Player;
namespace MyGame.Application.Commands.Player
{
/// <summary>
/// 移动玩家命令
/// </summary>
public class MovePlayerCommand : AbstractCommand
{
private readonly float _x;
private readonly float _y;
private readonly float _z;
private float _oldX;
private float _oldY;
private float _oldZ;
public MovePlayerCommand(float x, float y, float z)
{
_x = x;
_y = y;
_z = z;
}
protected override void OnExecute()
{
var playerModel = this.GetModel<PlayerModel>();
// 保存旧位置(用于撤销)
_oldX = playerModel.PositionX.Value;
_oldY = playerModel.PositionY.Value;
_oldZ = playerModel.PositionZ.Value;
// 移动到新位置
playerModel.PositionX.Value = _x;
playerModel.PositionY.Value = _y;
playerModel.PositionZ.Value = _z;
Console.WriteLine($"玩家移动到 ({_x}, {_y}, {_z})");
}
protected override void OnUndo()
{
var playerModel = this.GetModel<PlayerModel>();
// 恢复旧位置
playerModel.PositionX.Value = _oldX;
playerModel.PositionY.Value = _oldY;
playerModel.PositionZ.Value = _oldZ;
Console.WriteLine($"撤销移动,返回 ({_oldX}, {_oldY}, {_oldZ})");
}
}
}
步骤 3: 模块化设计
使用 IArchitectureModule 将相关功能封装成独立模块。
3.1 创建玩家模块
using GFramework.Core.Abstractions.architecture;
using MyGame.Domain.Models.Player;
using MyGame.Application.Systems.Player;
namespace MyGame.Modules.PlayerModule
{
/// <summary>
/// 玩家功能模块
/// </summary>
public class PlayerModule : IArchitectureModule
{
public string Name => "PlayerModule";
public string Version => "1.0.0";
public void Install(IArchitecture architecture)
{
Console.WriteLine($"安装模块: {Name} v{Version}");
// 注册玩家相关的 Model
architecture.RegisterModel(new PlayerModel());
// 注册玩家相关的 System
architecture.RegisterSystem(new PlayerSystem());
architecture.RegisterSystem(new PlayerLevelSystem());
Console.WriteLine($"模块 {Name} 安装完成");
}
public void Uninstall(IArchitecture architecture)
{
Console.WriteLine($"卸载模块: {Name}");
// 清理资源
// 注意: GFramework 会自动处理组件的清理
}
}
/// <summary>
/// 玩家等级系统
/// </summary>
public class PlayerLevelSystem : AbstractSystem
{
protected override void OnInit()
{
var playerModel = this.GetModel<PlayerModel>();
// 监听升级事件
playerModel.Level.Register(level =>
{
Console.WriteLine($"等级系统: 玩家达到 {level} 级");
CalculateStats(level);
});
}
private void CalculateStats(int level)
{
// 根据等级计算属性
Console.WriteLine($"重新计算 {level} 级的属性");
}
}
}
3.2 创建战斗模块
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.system;
using MyGame.Domain.Models.Player;
namespace MyGame.Modules.CombatModule
{
/// <summary>
/// 战斗功能模块
/// </summary>
public class CombatModule : IArchitectureModule
{
public string Name => "CombatModule";
public string Version => "1.0.0";
public void Install(IArchitecture architecture)
{
Console.WriteLine($"安装模块: {Name} v{Version}");
// 注册战斗系统
architecture.RegisterSystem(new CombatSystem());
architecture.RegisterSystem(new SkillSystem());
architecture.RegisterSystem(new DamageCalculationSystem());
Console.WriteLine($"模块 {Name} 安装完成");
}
public void Uninstall(IArchitecture architecture)
{
Console.WriteLine($"卸载模块: {Name}");
}
}
/// <summary>
/// 战斗系统
/// </summary>
public class CombatSystem : AbstractSystem
{
private PlayerModel _playerModel;
protected override void OnInit()
{
_playerModel = this.GetModel<PlayerModel>();
Console.WriteLine("战斗系统初始化完成");
}
/// <summary>
/// 攻击目标
/// </summary>
public void Attack(string targetName, int damage)
{
Console.WriteLine($"玩家攻击 {targetName},造成 {damage} 点伤害");
// 获取伤害计算系统
var damageSystem = this.GetSystem<DamageCalculationSystem>();
int finalDamage = damageSystem.CalculateDamage(damage);
Console.WriteLine($"最终伤害: {finalDamage}");
}
}
/// <summary>
/// 技能系统
/// </summary>
public class SkillSystem : AbstractSystem
{
private readonly Dictionary<string, float> _cooldowns = new();
protected override void OnInit()
{
Console.WriteLine("技能系统初始化完成");
}
/// <summary>
/// 使用技能
/// </summary>
public bool UseSkill(string skillName, int manaCost)
{
var playerModel = this.GetModel<PlayerModel>();
// 检查法力值
if (playerModel.Mana.Value < manaCost)
{
Console.WriteLine($"法力值不足,无法使用 {skillName}");
return false;
}
// 检查冷却
if (_cooldowns.ContainsKey(skillName))
{
Console.WriteLine($"技能 {skillName} 冷却中");
return false;
}
// 消耗法力值
playerModel.Mana.Value -= manaCost;
Console.WriteLine($"使用技能: {skillName}");
return true;
}
}
/// <summary>
/// 伤害计算系统
/// </summary>
public class DamageCalculationSystem : AbstractSystem
{
protected override void OnInit()
{
Console.WriteLine("伤害计算系统初始化完成");
}
/// <summary>
/// 计算最终伤害
/// </summary>
public int CalculateDamage(int baseDamage)
{
var playerModel = this.GetModel<PlayerModel>();
// 根据等级增加伤害
float levelBonus = 1.0f + (playerModel.Level.Value * 0.1f);
int finalDamage = (int)(baseDamage * levelBonus);
return finalDamage;
}
}
}
3.3 创建库存模块
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.model;
using GFramework.Core.system;
using GFramework.Core.property;
namespace MyGame.Modules.InventoryModule
{
/// <summary>
/// 库存功能模块
/// </summary>
public class InventoryModule : IArchitectureModule
{
public string Name => "InventoryModule";
public string Version => "1.0.0";
public void Install(IArchitecture architecture)
{
Console.WriteLine($"安装模块: {Name} v{Version}");
// 注册库存模型和系统
architecture.RegisterModel(new InventoryModel());
architecture.RegisterSystem(new InventorySystem());
Console.WriteLine($"模块 {Name} 安装完成");
}
public void Uninstall(IArchitecture architecture)
{
Console.WriteLine($"卸载模块: {Name}");
}
}
/// <summary>
/// 物品数据
/// </summary>
public class Item
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int Quantity { get; set; }
public ItemType Type { get; set; }
}
public enum ItemType
{
Weapon,
Armor,
Consumable,
Material,
Quest
}
/// <summary>
/// 库存模型
/// </summary>
public class InventoryModel : AbstractModel
{
public BindableProperty<int> MaxSlots { get; } = new(50);
public BindableProperty<int> Gold { get; } = new(0);
private readonly List<Item> _items = new();
protected override void OnInit()
{
Console.WriteLine("库存模型初始化完成");
}
/// <summary>
/// 添加物品
/// </summary>
public bool AddItem(Item item)
{
if (_items.Count >= MaxSlots.Value)
{
Console.WriteLine("库存已满");
return false;
}
// 检查是否已有相同物品
var existingItem = _items.FirstOrDefault(i => i.Id == item.Id);
if (existingItem != null)
{
existingItem.Quantity += item.Quantity;
}
else
{
_items.Add(item);
}
Console.WriteLine($"添加物品: {item.Name} x{item.Quantity}");
return true;
}
/// <summary>
/// 移除物品
/// </summary>
public bool RemoveItem(string itemId, int quantity)
{
var item = _items.FirstOrDefault(i => i.Id == itemId);
if (item == null)
{
Console.WriteLine($"物品不存在: {itemId}");
return false;
}
if (item.Quantity < quantity)
{
Console.WriteLine($"物品数量不足: {item.Name}");
return false;
}
item.Quantity -= quantity;
if (item.Quantity == 0)
{
_items.Remove(item);
}
Console.WriteLine($"移除物品: {item.Name} x{quantity}");
return true;
}
/// <summary>
/// 获取所有物品
/// </summary>
public IReadOnlyList<Item> GetAllItems() => _items.AsReadOnly();
}
/// <summary>
/// 库存系统
/// </summary>
public class InventorySystem : AbstractSystem
{
private InventoryModel _inventoryModel;
protected override void OnInit()
{
_inventoryModel = this.GetModel<InventoryModel>();
Console.WriteLine("库存系统初始化完成");
}
/// <summary>
/// 使用物品
/// </summary>
public void UseItem(string itemId)
{
var items = _inventoryModel.GetAllItems();
var item = items.FirstOrDefault(i => i.Id == itemId);
if (item == null)
{
Console.WriteLine($"物品不存在: {itemId}");
return;
}
Console.WriteLine($"使用物品: {item.Name}");
// 根据物品类型执行不同逻辑
switch (item.Type)
{
case ItemType.Consumable:
UseConsumable(item);
break;
case ItemType.Weapon:
EquipWeapon(item);
break;
default:
Console.WriteLine($"无法使用该类型的物品: {item.Type}");
break;
}
}
private void UseConsumable(Item item)
{
Console.WriteLine($"消耗物品: {item.Name}");
_inventoryModel.RemoveItem(item.Id, 1);
}
private void EquipWeapon(Item item)
{
Console.WriteLine($"装备武器: {item.Name}");
}
}
}
步骤 4: 依赖管理
使用 IoC 容器管理依赖关系,实现松耦合设计。
4.1 注册服务
using GFramework.Core.architecture;
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.ioc;
using MyGame.Modules.PlayerModule;
using MyGame.Modules.CombatModule;
using MyGame.Modules.InventoryModule;
namespace MyGame.Core.Architecture
{
/// <summary>
/// 游戏主架构(完整版)
/// </summary>
public class GameArchitecture : Architecture
{
public static IArchitecture Interface { get; private set; }
protected override void Init()
{
Interface = this;
Console.WriteLine("=== 初始化游戏架构 ===");
// 注册核心服务
RegisterCoreServices();
}
protected override void InstallModules()
{
Console.WriteLine("\n=== 安装功能模块 ===");
// 按依赖顺序安装模块
InstallModule(new PlayerModule()); // 基础模块
InstallModule(new InventoryModule()); // 依赖玩家模块
InstallModule(new CombatModule()); // 依赖玩家模块
InstallModule(new QuestModule()); // 依赖多个模块
Console.WriteLine("\n=== 所有模块安装完成 ===");
}
/// <summary>
/// 注册核心服务
/// </summary>
private void RegisterCoreServices()
{
// 注册日志服务
var loggerFactory = new ConsoleLoggerFactory();
RegisterService<ILoggerFactory>(loggerFactory);
// 注册配置服务
var configManager = new ConfigurationManager();
RegisterService<IConfigurationManager>(configManager);
// 注册资源管理器
var resourceManager = new ResourceManager();
RegisterService<IResourceManager>(resourceManager);
Console.WriteLine("核心服务注册完成");
}
}
// 简化的服务实现示例
public interface ILoggerFactory { }
public class ConsoleLoggerFactory : ILoggerFactory { }
public interface IConfigurationManager { }
public class ConfigurationManager : IConfigurationManager { }
public interface IResourceManager { }
public class ResourceManager : IResourceManager { }
}
4.2 创建任务模块(展示模块间依赖)
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.model;
using GFramework.Core.system;
using MyGame.Domain.Models.Player;
using MyGame.Modules.InventoryModule;
namespace MyGame.Modules.QuestModule
{
/// <summary>
/// 任务功能模块
/// </summary>
public class QuestModule : IArchitectureModule
{
public string Name => "QuestModule";
public string Version => "1.0.0";
public void Install(IArchitecture architecture)
{
Console.WriteLine($"安装模块: {Name} v{Version}");
// 注册任务模型和系统
architecture.RegisterModel(new QuestModel());
architecture.RegisterSystem(new QuestSystem());
Console.WriteLine($"模块 {Name} 安装完成");
}
public void Uninstall(IArchitecture architecture)
{
Console.WriteLine($"卸载模块: {Name}");
}
}
/// <summary>
/// 任务数据
/// </summary>
public class Quest
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsCompleted { get; set; }
public int RewardExp { get; set; }
public int RewardGold { get; set; }
}
/// <summary>
/// 任务模型
/// </summary>
public class QuestModel : AbstractModel
{
private readonly List<Quest> _activeQuests = new();
private readonly List<Quest> _completedQuests = new();
protected override void OnInit()
{
Console.WriteLine("任务模型初始化完成");
}
public void AddQuest(Quest quest)
{
_activeQuests.Add(quest);
Console.WriteLine($"接受任务: {quest.Name}");
}
public void CompleteQuest(int questId)
{
var quest = _activeQuests.FirstOrDefault(q => q.Id == questId);
if (quest != null)
{
quest.IsCompleted = true;
_activeQuests.Remove(quest);
_completedQuests.Add(quest);
Console.WriteLine($"完成任务: {quest.Name}");
}
}
public IReadOnlyList<Quest> GetActiveQuests() => _activeQuests.AsReadOnly();
}
/// <summary>
/// 任务系统(依赖多个模块)
/// </summary>
public class QuestSystem : AbstractSystem
{
private QuestModel _questModel;
private PlayerModel _playerModel;
private InventoryModel _inventoryModel;
protected override void OnInit()
{
// 获取依赖的模型
_questModel = this.GetModel<QuestModel>();
_playerModel = this.GetModel<PlayerModel>();
_inventoryModel = this.GetModel<InventoryModel>();
Console.WriteLine("任务系统初始化完成");
}
/// <summary>
/// 完成任务并发放奖励
/// </summary>
public void CompleteQuest(int questId)
{
var quest = _questModel.GetActiveQuests()
.FirstOrDefault(q => q.Id == questId);
if (quest == null)
{
Console.WriteLine($"任务不存在: {questId}");
return;
}
// 标记任务完成
_questModel.CompleteQuest(questId);
// 发放奖励
GiveRewards(quest);
}
private void GiveRewards(Quest quest)
{
Console.WriteLine($"\n=== 任务奖励 ===");
// 经验奖励
if (quest.RewardExp > 0)
{
_playerModel.GainExperience(quest.RewardExp);
Console.WriteLine($"获得经验: {quest.RewardExp}");
}
// 金币奖励
if (quest.RewardGold > 0)
{
_inventoryModel.Gold.Value += quest.RewardGold;
Console.WriteLine($"获得金币: {quest.RewardGold}");
}
Console.WriteLine("=================\n");
}
}
}
步骤 5: 代码组织
建立清晰的代码组织规范,提高代码可读性和可维护性。
5.1 命名规范
namespace MyGame.Core.Constants
{
/// <summary>
/// 游戏常量定义
/// </summary>
public static class GameConstants
{
// 游戏配置
public const string GameName = "MyLargeGame";
public const string GameVersion = "1.0.0";
// 玩家配置
public const int DefaultPlayerLevel = 1;
public const int MaxPlayerLevel = 100;
public const int DefaultHealth = 100;
public const int DefaultMana = 50;
// 库存配置
public const int DefaultInventorySlots = 50;
public const int MaxInventorySlots = 200;
// 战斗配置
public const float BaseDamageMultiplier = 1.0f;
public const float CriticalDamageMultiplier = 2.0f;
}
/// <summary>
/// 层级常量
/// </summary>
public static class LayerConstants
{
public const string PlayerLayer = "Player";
public const string EnemyLayer = "Enemy";
public const string EnvironmentLayer = "Environment";
public const string UILayer = "UI";
}
/// <summary>
/// 事件名称常量
/// </summary>
public static class EventNames
{
public const string PlayerLevelUp = "Player.LevelUp";
public const string PlayerDeath = "Player.Death";
public const string QuestCompleted = "Quest.Completed";
public const string ItemAcquired = "Item.Acquired";
}
}
5.2 文件组织规范
// 文件: PlayerModel.cs
// 位置: MyGame.Domain/Models/Player/PlayerModel.cs
using GFramework.Core.model;
using GFramework.Core.property;
namespace MyGame.Domain.Models.Player
{
/// <summary>
/// 玩家数据模型
/// 职责: 管理玩家的核心数据和状态
/// </summary>
/// <remarks>
/// 该模型包含:
/// - 基础属性(名称、等级、经验)
/// - 战斗属性(生命值、法力值)
/// - 位置信息
/// </remarks>
public class PlayerModel : AbstractModel
{
#region Properties
// 基础属性
public BindableProperty<string> Name { get; } = new("Player");
public BindableProperty<int> Level { get; } = new(1);
public BindableProperty<int> Experience { get; } = new(0);
// 战斗属性
public BindableProperty<int> Health { get; } = new(100);
public BindableProperty<int> MaxHealth { get; } = new(100);
#endregion
#region Lifecycle
protected override void OnInit()
{
RegisterEventHandlers();
}
#endregion
#region Public Methods
/// <summary>
/// 受到伤害
/// </summary>
/// <param name="damage">伤害值</param>
public void TakeDamage(int damage)
{
Health.Value = Math.Max(0, Health.Value - damage);
}
#endregion
#region Private Methods
private void RegisterEventHandlers()
{
Level.Register(OnLevelChanged);
}
private void OnLevelChanged(int newLevel)
{
Console.WriteLine($"玩家升级到 {newLevel} 级");
}
#endregion
}
}
5.3 扩展方法组织
using GFramework.Core.Abstractions.architecture;
using MyGame.Domain.Models.Player;
namespace MyGame.Core.Extensions
{
/// <summary>
/// 游戏扩展方法
/// </summary>
public static class GameExtensions
{
/// <summary>
/// 获取玩家模型(快捷方法)
/// </summary>
public static PlayerModel GetPlayerModel(this IArchitecture architecture)
{
return architecture.GetModel<PlayerModel>();
}
/// <summary>
/// 检查玩家是否存活
/// </summary>
public static bool IsPlayerAlive(this IArchitecture architecture)
{
var player = architecture.GetPlayerModel();
return player.Health.Value > 0;
}
/// <summary>
/// 获取玩家位置
/// </summary>
public static (float x, float y, float z) GetPlayerPosition(this IArchitecture architecture)
{
var player = architecture.GetPlayerModel();
return (player.PositionX.Value, player.PositionY.Value, player.PositionZ.Value);
}
}
/// <summary>
/// 玩家模型扩展方法
/// </summary>
public static class PlayerModelExtensions
{
/// <summary>
/// 检查是否满血
/// </summary>
public static bool IsFullHealth(this PlayerModel player)
{
return player.Health.Value == player.MaxHealth.Value;
}
/// <summary>
/// 获取生命值百分比
/// </summary>
public static float GetHealthPercentage(this PlayerModel player)
{
return (float)player.Health.Value / player.MaxHealth.Value;
}
/// <summary>
/// 检查是否低血量
/// </summary>
public static bool IsLowHealth(this PlayerModel player, float threshold = 0.3f)
{
return player.GetHealthPercentage() < threshold;
}
}
}
步骤 6: 团队协作
建立团队协作规范,确保代码质量和开发效率。
6.1 代码审查清单
创建代码审查清单文档:
# 代码审查清单
## 架构设计
- [ ] 组件是否放在正确的层级(Core/Domain/Application/Infrastructure/Presentation)
- [ ] 是否遵循单一职责原则
- [ ] 依赖关系是否合理(避免循环依赖)
- [ ] 是否正确使用了模块化设计
## 代码质量
- [ ] 命名是否清晰且符合规范
- [ ] 是否有适当的注释和文档
- [ ] 是否有单元测试覆盖
- [ ] 是否处理了异常情况
## GFramework 使用
- [ ] 是否正确继承了基类(AbstractModel/AbstractSystem等)
- [ ] 是否正确使用了生命周期方法(OnInit/OnDestroy)
- [ ] 是否正确使用了依赖注入(GetModel/GetSystem/GetService)
- [ ] 事件是否正确注册和注销
## 性能考虑
- [ ] 是否避免了不必要的对象创建
- [ ] 是否正确使用了对象池
- [ ] 是否避免了频繁的 GC 分配
- [ ] 协程使用是否合理
## 可维护性
- [ ] 代码是否易于理解和修改
- [ ] 是否有适当的日志记录
- [ ] 配置是否可外部化
- [ ] 是否便于测试
6.2 Git 工作流
# 功能分支命名规范
feature/player-system # 新功能
bugfix/inventory-crash # Bug 修复
refactor/combat-module # 重构
docs/api-documentation # 文档更新
# 提交信息规范
feat: 添加玩家升级系统
fix: 修复库存物品重复添加的问题
refactor: 重构战斗系统的伤害计算
docs: 更新架构设计文档
test: 添加玩家系统单元测试
chore: 更新依赖包版本
6.3 项目配置文件
创建 .editorconfig 统一代码风格:
# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
[*.cs]
# 命名规则
dotnet_naming_rule.interfaces_should_be_prefixed_with_i.severity = warning
dotnet_naming_rule.interfaces_should_be_prefixed_with_i.symbols = interface
dotnet_naming_rule.interfaces_should_be_prefixed_with_i.style = begins_with_i
# 代码风格
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
[*.md]
trim_trailing_whitespace = false
完整代码
Program.cs - 主程序
using MyGame.Core.Architecture;
using MyGame.Application.Systems.Player;
using MyGame.Modules.InventoryModule;
using MyGame.Modules.QuestModule;
using MyGame.Core.Extensions;
namespace MyGame
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("=== 大型游戏项目示例 ===\n");
// 1. 初始化架构
var architecture = new GameArchitecture();
architecture.Initialize();
await architecture.WaitUntilReadyAsync();
Console.WriteLine("\n=== 架构初始化完成 ===\n");
// 2. 测试玩家系统
await TestPlayerSystem(architecture);
// 3. 测试库存系统
await TestInventorySystem(architecture);
// 4. 测试任务系统
await TestQuestSystem(architecture);
// 5. 测试模块协作
await TestModuleIntegration(architecture);
Console.WriteLine("\n=== 测试完成 ===");
}
static async Task TestPlayerSystem(GameArchitecture architecture)
{
Console.WriteLine("\n--- 测试玩家系统 ---");
var playerSystem = architecture.GetSystem<PlayerSystem>();
var playerModel = architecture.GetPlayerModel();
// 移动玩家
playerSystem.MovePlayer(10, 0, 5);
Console.WriteLine($"玩家位置: {architecture.GetPlayerPosition()}");
// 受到伤害
playerModel.TakeDamage(30);
Console.WriteLine($"当前生命值: {playerModel.Health.Value}/{playerModel.MaxHealth.Value}");
// 治疗
playerSystem.HealPlayer(20);
Console.WriteLine($"治疗后生命值: {playerModel.Health.Value}/{playerModel.MaxHealth.Value}");
// 获得经验
playerModel.GainExperience(150);
await Task.Delay(500);
}
static async Task TestInventorySystem(GameArchitecture architecture)
{
Console.WriteLine("\n--- 测试库存系统 ---");
var inventoryModel = architecture.GetModel<InventoryModel>();
var inventorySystem = architecture.GetSystem<InventorySystem>();
// 添加物品
inventoryModel.AddItem(new Item
{
Id = "potion_health",
Name = "生命药水",
Description = "恢复 50 点生命值",
Quantity = 5,
Type = ItemType.Consumable
});
inventoryModel.AddItem(new Item
{
Id = "sword_iron",
Name = "铁剑",
Description = "基础武器",
Quantity = 1,
Type = ItemType.Weapon
});
// 显示库存
var items = inventoryModel.GetAllItems();
Console.WriteLine($"\n当前库存 ({items.Count}/{inventoryModel.MaxSlots.Value}):");
foreach (var item in items)
{
Console.WriteLine($" - {item.Name} x{item.Quantity} ({item.Type})");
}
// 使用物品
inventorySystem.UseItem("potion_health");
await Task.Delay(500);
}
static async Task TestQuestSystem(GameArchitecture architecture)
{
Console.WriteLine("\n--- 测试任务系统 ---");
var questModel = architecture.GetModel<QuestModel>();
var questSystem = architecture.GetSystem<QuestSystem>();
// 添加任务
questModel.AddQuest(new Quest
{
Id = 1,
Name = "击败史莱姆",
Description = "击败 10 只史莱姆",
RewardExp = 100,
RewardGold = 50
});
// 显示活动任务
var activeQuests = questModel.GetActiveQuests();
Console.WriteLine($"\n活动任务 ({activeQuests.Count}):");
foreach (var quest in activeQuests)
{
Console.WriteLine($" - {quest.Name}: {quest.Description}");
}
// 完成任务
await Task.Delay(1000);
questSystem.CompleteQuest(1);
await Task.Delay(500);
}
static async Task TestModuleIntegration(GameArchitecture architecture)
{
Console.WriteLine("\n--- 测试模块协作 ---");
var playerModel = architecture.GetPlayerModel();
var inventoryModel = architecture.GetModel<InventoryModel>();
Console.WriteLine($"\n玩家状态:");
Console.WriteLine($" 等级: {playerModel.Level.Value}");
Console.WriteLine($" 经验: {playerModel.Experience.Value}");
Console.WriteLine($" 生命值: {playerModel.Health.Value}/{playerModel.MaxHealth.Value}");
Console.WriteLine($" 金币: {inventoryModel.Gold.Value}");
Console.WriteLine($" 库存物品: {inventoryModel.GetAllItems().Count}");
// 检查玩家状态
if (architecture.IsPlayerAlive())
{
Console.WriteLine("\n玩家状态: 存活");
if (playerModel.IsLowHealth())
{
Console.WriteLine("警告: 生命值过低!");
}
}
await Task.Delay(500);
}
}
}
运行结果
运行程序后,你将看到类似以下的输出:
=== 大型游戏项目示例 ===
=== 初始化游戏架构 ===
初始化游戏架构...
核心服务注册完成
=== 安装功能模块 ===
安装模块: PlayerModule v1.0.0
玩家模型初始化: Player
玩家系统初始化完成
等级系统: 玩家达到 1 级
重新计算 1 级的属性
模块 PlayerModule 安装完成
安装模块: InventoryModule v1.0.0
库存模型初始化完成
库存系统初始化完成
模块 InventoryModule 安装完成
安装模块: CombatModule v1.0.0
战斗系统初始化完成
技能系统初始化完成
伤害计算系统初始化完成
模块 CombatModule 安装完成
安装模块: QuestModule v1.0.0
任务模型初始化完成
任务系统初始化完成
模块 QuestModule 安装完成
=== 所有模块安装完成 ===
=== 架构初始化完成 ===
--- 测试玩家系统 ---
玩家移动到 (10, 0, 5)
玩家位置: (10, 0, 5)
当前生命值: 70/100
玩家恢复 20 点生命值
治疗后生命值: 90/100
玩家升级到 2 级
等级系统: 玩家达到 2 级
重新计算 2 级的属性
--- 测试库存系统 ---
添加物品: 生命药水 x5
添加物品: 铁剑 x1
当前库存 (2/50):
- 生命药水 x5 (Consumable)
- 铁剑 x1 (Weapon)
使用物品: 生命药水
消耗物品: 生命药水
移除物品: 生命药水 x1
--- 测试任务系统 ---
接受任务: 击败史莱姆
活动任务 (1):
- 击败史莱姆: 击败 10 只史莱姆
完成任务: 击败史莱姆
=== 任务奖励 ===
玩家升级到 3 级
等级系统: 玩家达到 3 级
重新计算 3 级的属性
获得经验: 100
获得金币: 50
=================
--- 测试模块协作 ---
玩家状态:
等级: 3
经验: 50
生命值: 110/110
金币: 50
库存物品: 2
玩家状态: 存活
=== 测试完成 ===
验证步骤:
- 架构正确初始化,所有模块按顺序加载
- 各模块功能正常工作
- 模块间依赖关系正确
- 事件系统正常触发
- 数据在模块间正确共享
下一步
恭喜!你已经掌握了大型项目的组织方法。接下来可以学习:
- Godot 完整项目 - 在 Godot 中应用这些原则
- 资源管理最佳实践 - 管理大型项目的资源
- 实现存档系统 - 保存复杂的游戏状态
- 架构模式最佳实践 - 高级架构模式