关于装饰器设计模式在平台游戏敌人类中应用的技术咨询
装饰器模式在平台游戏敌人类的落地实现
嘿JohnnyGat,看到你想把装饰器模式用到平台游戏的敌人类上,这个思路真的很合适!装饰器模式天生就是用来动态给对象叠加功能/属性的,完美匹配你要给基础敌人加不同颜色、属性、AI逻辑的需求。我来给你梳理一套清晰的实现方案,直接就能套进你的项目里:
一、核心类结构设计
首先我们要遵循装饰器模式的经典结构:抽象组件 → 具体组件 → 抽象装饰器 → 具体装饰器,对应到你的敌人类就是:
1. 抽象组件:Enemy基类
这是所有敌人的统一接口,定义敌人的核心属性和行为:
// 抽象组件:所有敌人的基类,定义核心接口 class Enemy { public: float speedX, speedY; int x, y, width, height; // 必须实现的核心行为方法 virtual void move() = 0; virtual void draw() = 0; virtual void updateAI() = 0; // 虚析构函数,防止子类对象内存泄漏 virtual ~Enemy() = default; };
2. 具体组件:基础敌人(BasicEnemy)
这是最基础的敌人实现,只有最核心的属性和行为,没有任何额外扩展:
// 具体组件:基础敌人,仅实现最基础的移动、绘制和AI逻辑 class BasicEnemy : public Enemy { public: BasicEnemy(int startX, int startY) { x = startX; y = startY; width = 32; height = 32; speedX = 1.0f; speedY = 0.0f; } void move() override { // 基础移动逻辑:左右来回巡逻 x += speedX; if (x < 0 || x > 800 - width) { speedX *= -1; } } void draw() override { // 默认绘制灰色方块(这里假设你有drawRectangle绘图函数) drawRectangle(x, y, width, height, GRAY); } void updateAI() override { // 基础AI:无额外逻辑,仅执行移动 } };
3. 抽象装饰器:EnemyDecorator
这是所有装饰器的基类,必须继承Enemy接口,并且持有一个被装饰的Enemy对象,默认转发所有方法给被装饰对象:
// 抽象装饰器:所有敌人装饰器的父类,负责包裹敌人对象 class EnemyDecorator : public Enemy { protected: Enemy* wrappedEnemy; // 被装饰的敌人实例 public: EnemyDecorator(Enemy* enemy) : wrappedEnemy(enemy) {} // 默认转发所有方法给被装饰对象,子类可以按需覆盖 void move() override { wrappedEnemy->move(); } void draw() override { wrappedEnemy->draw(); } void updateAI() override { wrappedEnemy->updateAI(); } // 析构时清理被装饰对象,避免内存泄漏 virtual ~EnemyDecorator() { delete wrappedEnemy; } };
4. 具体装饰器:各类扩展功能
现在我们可以创建各种具体的装饰器,每个装饰器只负责一个扩展功能(遵循单一职责原则):
颜色装饰器(ColoredEnemy)
负责修改敌人的绘制颜色:
// 具体装饰器:给敌人添加自定义颜色 class ColoredEnemy : public EnemyDecorator { private: Color color; // 假设你有Color枚举/结构体 public: ColoredEnemy(Enemy* enemy, Color newColor) : EnemyDecorator(enemy), color(newColor) {} // 覆盖draw方法,用新颜色绘制敌人 void draw() override { drawRectangle(wrappedEnemy->x, wrappedEnemy->y, wrappedEnemy->width, wrappedEnemy->height, color); } };
快速移动装饰器(FastEnemy)
负责提升敌人的移动速度:
// 具体装饰器:提升敌人移动速度 class FastEnemy : public EnemyDecorator { public: FastEnemy(Enemy* enemy) : EnemyDecorator(enemy) { // 直接将原速度翻倍 wrappedEnemy->speedX *= 2.0f; } // 也可以重写move方法,添加速度提升后的额外逻辑(比如调整边界检测) void move() override { wrappedEnemy->move(); // 可选:快速移动时跳过某些地形碰撞检测优化 } };
玩家追踪AI装饰器(PlayerTrackingEnemy)
负责给敌人添加追踪玩家的AI逻辑:
// 具体装饰器:给敌人添加追踪玩家的AI逻辑 class PlayerTrackingEnemy : public EnemyDecorator { private: Player* player; // 假设你有Player类,存储玩家实例 public: PlayerTrackingEnemy(Enemy* enemy, Player* target) : EnemyDecorator(enemy), player(target) {} // 覆盖updateAI方法,添加追踪逻辑 void updateAI() override { // 先执行原敌人的AI逻辑,再叠加追踪逻辑 wrappedEnemy->updateAI(); // 计算朝向玩家的移动方向 if (player->x > wrappedEnemy->x) { wrappedEnemy->speedX = abs(wrappedEnemy->speedX); } else { wrappedEnemy->speedX = -abs(wrappedEnemy->speedX); } } };
二、使用示例:组合不同装饰器
装饰器的优势就是动态组合,你可以任意搭配不同的扩展功能,比如创建一个红色、快速、能追踪玩家的敌人:
// 1. 创建基础敌人实例 Enemy* basicEnemy = new BasicEnemy(100, 200); // 2. 装饰成红色敌人 Enemy* redEnemy = new ColoredEnemy(basicEnemy, RED); // 3. 再装饰成快速移动的敌人 Enemy* fastRedEnemy = new FastEnemy(redEnemy); // 4. 最后添加玩家追踪AI Enemy* finalEnemy = new PlayerTrackingEnemy(fastRedEnemy, playerInstance); // 在游戏循环中使用这个敌人 while (gameIsRunning) { finalEnemy->updateAI(); finalEnemy->move(); finalEnemy->draw(); } // 记得清理内存(抽象装饰器的析构会递归删除所有被装饰的对象) delete finalEnemy;
三、实战注意事项
- 单一职责:每个装饰器只负责一个功能,比如颜色装饰器只管颜色,AI装饰器只管AI,这样组合起来更灵活,也更容易维护。
- 内存管理:抽象装饰器的析构函数要负责删除被装饰的对象,这样删除最外层装饰器时,会递归删除所有内层的敌人实例,避免内存泄漏。
- 灵活扩展:如果后续需要添加新的敌人特性(比如飞行、隐身、发射子弹),只需要创建新的装饰器即可,不需要修改现有类,完美符合开闭原则。
- 方法转发:抽象装饰器默认转发所有方法,子类只需要覆盖需要修改的方法即可,减少重复代码。
内容的提问来源于stack exchange,提问作者JohnnyGat
相关产品推荐
相关产品推荐

