# Extra2D 动作系统重构规格文档 ## 一、概述 本文档描述了 Extra2D 动作系统的重构方案,参考 Cocos2d-x 的动作系统设计模式,实现一个更加完善、易用、功能丰富的动作系统。 ## 二、现有系统分析 ### 2.1 当前类层次结构 ``` Action (基类) ├── IntervalAction (有限时间动作基类) │ ├── MoveBy/MoveTo │ ├── ScaleBy/ScaleTo │ ├── RotateBy/RotateTo │ ├── FadeIn/FadeOut/FadeTo │ ├── Sequence │ ├── Spawn │ ├── Delay │ └── Loop └── InstantAction (瞬时动作基类) └── CallFunc ``` ### 2.2 与 Cocos2d-x 的差异 | 特性 | Extra2D 当前 | Cocos2d-x | 差异说明 | |------|-------------|-----------|---------| | 类层次 | Action -> IntervalAction/InstantAction | Action -> FiniteTimeAction -> ActionInterval/ActionInstant | 缺少 FiniteTimeAction 中间层 | | 动作管理 | Node 内部管理 | ActionManager 单例集中管理 | 缺少集中式管理 | | 缓动动作 | EaseAction 静态方法 | ActionEase 类系(装饰器模式) | 不够灵活,无法组合 | | 速度控制 | Action::speed_ 成员 | Speed 动作包装器 | 缺少动态速度控制 | | 跟随动作 | 无 | Follow 类 | 缺失 | | 跳跃动作 | 无 | JumpBy/JumpTo | 缺失 | | 贝塞尔动作 | 无 | BezierBy/BezierTo | 缺失 | | 闪烁动作 | 无 | Blink | 缺失 | | 色调动作 | 无 | TintBy/TintTo | 缺失 | | 重复动作 | Loop | Repeat/RepeatForever | 命名和功能差异 | | 反向动作 | reverse() 方法 | reverse() 方法 | 相同 | | 克隆动作 | clone() 方法 | clone() 方法 | 相同 | ## 三、重构目标 ### 3.1 核心目标 1. **完善类层次结构** - 添加 FiniteTimeAction 中间层 2. **集中式动作管理** - 实现 ActionManager 单例 3. **装饰器模式缓动** - 实现 ActionEase 类系 4. **丰富动作类型** - 添加跳跃、贝塞尔、闪烁、色调等动作 5. **统一API风格** - 与 Cocos2d-x API 保持一致 ### 3.2 设计原则 1. **组合优于继承** - 使用装饰器模式实现缓动和速度控制 2. **单一职责** - ActionManager 只负责动作调度 3. **开放封闭** - 易于扩展新动作类型 4. **接口隔离** - 不同类型动作提供不同接口 ## 四、新类层次结构 ``` Action (基类) ├── FiniteTimeAction (有限时间动作基类) │ ├── ActionInterval (时间间隔动作) │ │ ├── MoveBy/MoveTo │ │ ├── MoveBy3D/MoveTo3D (新增) │ │ ├── JumpBy/JumpTo (新增) │ │ ├── BezierBy/BezierTo (新增) │ │ ├── ScaleBy/ScaleTo │ │ ├── RotateBy/RotateTo │ │ ├── FadeIn/FadeOut/FadeTo │ │ ├── Blink (新增) │ │ ├── TintBy/TintTo (新增) │ │ ├── Sequence │ │ ├── Spawn │ │ ├── DelayTime │ │ ├── Repeat (重命名自 Loop) │ │ ├── RepeatForever (新增) │ │ ├── ReverseTime (新增) │ │ └── ActionEase (缓动动作基类,新增) │ │ ├── EaseIn/EaseOut/EaseInOut │ │ ├── EaseSineIn/EaseSineOut/EaseSineInOut │ │ ├── EaseExponentialIn/EaseExponentialOut/EaseExponentialInOut │ │ ├── EaseBounceIn/EaseBounceOut/EaseBounceInOut │ │ ├── EaseElasticIn/EaseElasticOut/EaseElasticInOut │ │ ├── EaseBackIn/EaseBackOut/EaseBackInOut │ │ └── EaseBezier (新增) │ └── ActionInstant (瞬时动作) │ ├── CallFunc │ ├── CallFuncN (新增) │ ├── Place (新增) │ ├── FlipX/FlipY (新增) │ ├── Show/Hide (新增) │ ├── ToggleVisibility (新增) │ └── RemoveSelf (新增) ├── Speed (速度控制动作,新增) ├── Follow (跟随动作,新增) └── TargetedAction (目标动作,新增) ``` ## 五、核心类设计 ### 5.1 Action 基类 ```cpp class Action { public: virtual ~Action() = default; // 核心接口 virtual bool isDone() const; virtual void startWithTarget(Node* target); virtual void stop(); virtual void step(float dt); virtual void update(float time); // 克隆和反向 virtual Action* clone() const = 0; virtual Action* reverse() const = 0; // 属性访问 Node* getTarget() const; Node* getOriginalTarget() const; int getTag() const; void setTag(int tag); unsigned int getFlags() const; void setFlags(unsigned int flags); protected: Node* target_ = nullptr; Node* originalTarget_ = nullptr; int tag_ = -1; unsigned int flags_ = 0; }; ``` ### 5.2 FiniteTimeAction 中间层 ```cpp class FiniteTimeAction : public Action { public: float getDuration() const { return duration_; } void setDuration(float duration) { duration_ = duration; } virtual FiniteTimeAction* clone() const = 0; virtual FiniteTimeAction* reverse() const = 0; protected: float duration_ = 0.0f; }; ``` ### 5.3 ActionInterval 时间间隔动作 ```cpp class ActionInterval : public FiniteTimeAction { public: float getElapsed() const { return elapsed_; } bool isDone() const override; void startWithTarget(Node* target) override; void step(float dt) override; void setAmplitudeRate(float amp) { amplitudeRate_ = amp; } float getAmplitudeRate() const { return amplitudeRate_; } protected: float elapsed_ = 0.0f; bool firstTick_ = true; float amplitudeRate_ = 1.0f; EaseFunction easeFunc_ = nullptr; // 内置缓动函数 }; ``` ### 5.4 ActionInstant 瞬时动作 ```cpp class ActionInstant : public FiniteTimeAction { public: bool isDone() const override { return true; } void step(float dt) override; protected: bool done_ = false; }; ``` ### 5.5 ActionManager 动作管理器 ```cpp class ActionManager { public: static ActionManager* getInstance(); // 动作管理 void addAction(Action* action, Node* target, bool paused = false); void removeAction(Action* action); void removeActionByTag(int tag, Node* target); void removeAllActionsFromTarget(Node* target); void removeAllActions(); // 查询 Action* getActionByTag(int tag, Node* target); size_t getActionCount(Node* target) const; // 暂停/恢复 void pauseTarget(Node* target); void resumeTarget(Node* target); bool isPaused(Node* target) const; // 更新(每帧调用) void update(float dt); private: struct ActionElement { std::vector actions; Node* target; bool paused; int actionIndex; Action* currentAction; bool currentActionSalvaged; }; std::unordered_map targets_; static ActionManager* instance_; }; ``` ### 5.6 ActionEase 缓动动作基类 ```cpp class ActionEase : public ActionInterval { public: static ActionEase* create(ActionInterval* action); ActionInterval* getInnerAction() const { return innerAction_; } void startWithTarget(Node* target) override; void stop() override; void update(float time) override; Action* reverse() const override; Action* clone() const override; protected: ActionInterval* innerAction_ = nullptr; }; ``` ### 5.7 Speed 速度控制动作 ```cpp class Speed : public Action { public: static Speed* create(ActionInterval* action, float speed); float getSpeed() const { return speed_; } void setSpeed(float speed) { speed_ = speed; } void startWithTarget(Node* target) override; void stop() override; void step(float dt) override; bool isDone() const override; Action* reverse() const override; Action* clone() const override; protected: ActionInterval* innerAction_ = nullptr; float speed_ = 1.0f; }; ``` ## 六、新增动作类型 ### 6.1 JumpBy/JumpTo 跳跃动作 ```cpp class JumpBy : public ActionInterval { public: static JumpBy* create(float duration, const Vec2& position, float height, int jumps); protected: Vec2 startPosition_; Vec2 delta_; float height_; int jumps_; }; class JumpTo : public JumpBy { // 继承实现,目标位置版本 }; ``` ### 6.2 BezierBy/BezierTo 贝塞尔动作 ```cpp struct BezierConfig { Vec2 controlPoint1; Vec2 controlPoint2; Vec2 endPosition; }; class BezierBy : public ActionInterval { public: static BezierBy* create(float duration, const BezierConfig& config); protected: BezierConfig config_; Vec2 startPosition_; }; ``` ### 6.3 Blink 闪烁动作 ```cpp class Blink : public ActionInterval { public: static Blink* create(float duration, int times); protected: int times_; int currentTimes_; bool originalVisible_; }; ``` ### 6.4 TintBy/TintTo 色调动作 ```cpp class TintTo : public ActionInterval { public: static TintTo* create(float duration, uint8_t red, uint8_t green, uint8_t blue); protected: Color3B startColor_; Color3B endColor_; Color3B deltaColor_; }; ``` ### 6.5 Follow 跟随动作 ```cpp class Follow : public Action { public: static Follow* create(Node* followedNode, const Rect& boundary = Rect::ZERO); bool isDone() const override; void step(float dt) override; protected: Node* followedNode_ = nullptr; Rect boundary_; bool boundarySet_ = false; }; ``` ### 6.6 瞬时动作扩展 ```cpp // 放置到指定位置 class Place : public ActionInstant { public: static Place* create(const Vec2& position); }; // X/Y轴翻转 class FlipX : public ActionInstant { public: static FlipX* create(bool flipX); }; class FlipY : public ActionInstant { public: static FlipY* create(bool flipY); }; // 显示/隐藏 class Show : public ActionInstant { public: static Show* create(); }; class Hide : public ActionInstant { public: static Hide* create(); }; // 切换可见性 class ToggleVisibility : public ActionInstant { public: static ToggleVisibility* create(); }; // 移除自身 class RemoveSelf : public ActionInstant { public: static RemoveSelf* create(); }; // 带Node参数的回调 class CallFuncN : public ActionInstant { public: static CallFuncN* create(const std::function& func); }; ``` ## 七、缓动动作完整实现 ### 7.1 通用缓动包装器 ```cpp // 通用缓动包装器 class EaseCustom : public ActionEase { public: static EaseCustom* create(ActionInterval* action, EaseFunction easeFunc); }; // 指数缓动 class EaseExponentialIn : public ActionEase { /* ... */ }; class EaseExponentialOut : public ActionEase { /* ... */ }; class EaseExponentialInOut : public ActionEase { /* ... */ }; // 正弦缓动 class EaseSineIn : public ActionEase { /* ... */ }; class EaseSineOut : public ActionEase { /* ... */ }; class EaseSineInOut : public ActionEase { /* ... */ }; // 弹性缓动 class EaseElasticIn : public ActionEase { public: static EaseElasticIn* create(ActionInterval* action, float period = 0.3f); }; class EaseElasticOut : public ActionEase { /* ... */ }; class EaseElasticInOut : public ActionEase { /* ... */ }; // 弹跳缓动 class EaseBounceIn : public ActionEase { /* ... */ }; class EaseBounceOut : public ActionEase { /* ... */ }; class EaseBounceInOut : public ActionEase { /* ... */ }; // 回震缓动 class EaseBackIn : public ActionEase { /* ... */ }; class EaseBackOut : public ActionEase { /* ... */ }; class EaseBackInOut : public ActionEase { /* ... */ }; // 贝塞尔缓动(自定义曲线) class EaseBezier : public ActionEase { public: static EaseBezier* create(ActionInterval* action); void setBezierParamer(float p0, float p1, float p2, float p3); }; ``` ## 八、Node 类接口更新 ### 8.1 动作相关接口 ```cpp class Node { public: // 运行动作 Action* runAction(Action* action); // 停止动作 void stopAllActions(); void stopAction(Action* action); void stopActionByTag(int tag); void stopActionsByFlags(unsigned int flags); // 获取动作 Action* getActionByTag(int tag); size_t getNumberOfRunningActions() const; // 暂停/恢复所有动作 void pauseAllActions(); void resumeAllActions(); // 检查是否有动作在运行 bool isRunningActions() const; }; ``` ## 九、使用示例 ### 9.1 基本动作 ```cpp // 移动 auto moveTo = MoveTo::create(2.0f, Vec2(100, 100)); sprite->runAction(moveTo); // 跳跃 auto jump = JumpBy::create(2.0f, Vec2(200, 0), 100, 3); sprite->runAction(jump); // 贝塞尔曲线 BezierConfig bezier; bezier.controlPoint1 = Vec2(100, 200); bezier.controlPoint2 = Vec2(200, 100); bezier.endPosition = Vec2(300, 150); auto bezierAction = BezierTo::create(3.0f, bezier); sprite->runAction(bezierAction); ``` ### 9.2 组合动作 ```cpp // 序列动作 auto seq = Sequence::create( MoveTo::create(1.0f, Vec2(100, 100)), DelayTime::create(0.5f), FadeOut::create(1.0f), CallFunc::create([](){ log("Done!"); }), nullptr ); sprite->runAction(seq); // 并行动作 auto spawn = Spawn::create( MoveTo::create(2.0f, Vec2(200, 200)), RotateBy::create(2.0f, 360), FadeIn::create(2.0f), nullptr ); sprite->runAction(spawn); // 重复动作 auto repeat = Repeat::create(MoveBy::create(1.0f, Vec2(50, 0)), 5); sprite->runAction(repeat); // 永久重复 auto repeatForever = RepeatForever::create( Sequence::create( MoveBy::create(1.0f, Vec2(100, 0)), MoveBy::create(1.0f, Vec2(-100, 0)), nullptr ) ); sprite->runAction(repeatForever); ``` ### 9.3 缓动动作 ```cpp // 使用缓动包装器 auto move = MoveTo::create(3.0f, Vec2(500, 300)); auto easeMove = EaseElasticOut::create(move, 0.5f); sprite->runAction(easeMove); // 指数缓动 auto jump = JumpBy::create(2.0f, Vec2(200, 0), 100, 1); auto easeJump = EaseExponentialOut::create(jump); sprite->runAction(easeJump); // 弹跳缓动 auto scale = ScaleTo::create(1.0f, 2.0f); auto bounceScale = EaseBounceOut::create(scale); sprite->runAction(bounceScale); ``` ### 9.4 速度控制 ```cpp // 慢动作回放 auto action = MoveTo::create(5.0f, Vec2(500, 300)); auto speed = Speed::create(action, 0.5f); // 半速 sprite->runAction(speed); // 动态调整速度 speed->setSpeed(2.0f); // 2倍速 ``` ### 9.5 跟随动作 ```cpp // 相机跟随玩家 auto follow = Follow::create(player, Rect(0, 0, 2000, 2000)); camera->runAction(follow); ``` ## 十、文件结构 ``` Extra2D/include/extra2d/action/ ├── action.h # Action 基类 ├── finite_time_action.h # FiniteTimeAction 中间层 ├── action_interval.h # ActionInterval 及其子类 ├── action_instant.h # ActionInstant 及其子类 ├── action_ease.h # 缓动动作类系 ├── action_manager.h # ActionManager ├── ease_functions.h # 缓动函数 └── action_factory.h # 动作工厂(可选) Extra2D/src/action/ ├── action.cpp ├── finite_time_action.cpp ├── action_interval.cpp ├── action_instant.cpp ├── action_ease.cpp ├── action_manager.cpp └── ease_functions.cpp ``` ## 十一、实现优先级 ### 第一阶段(核心重构) 1. Action 基类重构 2. FiniteTimeAction 中间层 3. ActionInterval 重构 4. ActionInstant 重构 5. ActionManager 实现 ### 第二阶段(新增动作) 1. JumpBy/JumpTo 2. BezierBy/BezierTo 3. Blink 4. TintBy/TintTo 5. Follow 6. Speed ### 第三阶段(缓动系统) 1. ActionEase 基类 2. 各类缓动包装器 3. EaseCustom 自定义缓动 ### 第四阶段(瞬时动作扩展) 1. Place 2. FlipX/FlipY 3. Show/Hide 4. ToggleVisibility 5. RemoveSelf 6. CallFuncN ## 十二、兼容性考虑 ### 12.1 API 变更 - 动作创建方式改为 `create()` 静态工厂方法 - `Loop` 重命名为 `Repeat` - `Delay` 重命名为 `DelayTime` - 动作管理由 `ActionManager` 集中处理 ### 12.2 迁移指南 ```cpp // 旧写法 auto action = std::make_shared(2.0f, Vec2(100, 100)); sprite->runAction(action); // 新写法(推荐) auto action = MoveTo::create(2.0f, Vec2(100, 100)); sprite->runAction(action); // 旧写法(缓动) auto action = EaseAction::create(MoveTo::create(2.0f, Vec2(100, 100)), easeInQuad); // 新写法(缓动) auto action = EaseQuadIn::create(MoveTo::create(2.0f, Vec2(100, 100))); ``` ## 十三、性能优化 1. **对象池集成** - 动作对象使用对象池管理 2. **批量更新** - ActionManager 统一调度减少调用开销 3. **延迟删除** - 动作完成时标记删除,统一清理 4. **缓存友好** - 连续存储同一类型动作 ## 十四、测试计划 1. 单元测试:每个动作类型的独立测试 2. 集成测试:组合动作测试 3. 性能测试:大量动作并发测试 4. 内存测试:动作对象生命周期测试