Action动作基类,被 ActionManager 管理着。(cocos2dx 3.0 —- ActionManager

类图

Action类图

路径

1
2
2d/actions/ccaction.h
2d/actions/ccaction.cpp

源码分析

Action

先看看Action的声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class CC_DLL Action : public Ref, public Clonable
{
public:
static const int INVALID_TAG = -1;
virtual std::string description() const;

/* 返回拷贝动作 */
virtual Action* clone() const = 0;

/* 返回逆动作 */
virtual Action* reverse() const = 0;

/* 动作是否结束 */
virtual bool isDone() const;

/* 在动作开始前调用 */
/* 初始化 */
virtual void startWithTarget(Node *target);

/* 不要自己调用stop */
/* 把这破事交给ActionManger吧 */
virtual void stop();

/* 在ActionManager的update中每一帧调用 */
/* PS :原文注释中提示,如果你不知道自己在做什么,就不要重写step */
virtual void step(float dt);

/* 每一帧调用的函数 */
/* time的值是从 0 到 1 */
/* 0 表示开始 */
/* 0.5 表示执行一半 */
/* 1 表示结束 */
virtual void update(float time);

inline Node* getTarget() const { return _target; }
inline void setTarget(Node *target) { _target = target; }

inline Node* getOriginalTarget() const { return _originalTarget; }
/* 弱引用 ? */
inline void setOriginalTarget(Node *originalTarget) { _originalTarget = originalTarget; }

inline int getTag() const { return _tag; }
inline void setTag(int tag) { _tag = tag; }

protected:
Action();
virtual ~Action();

Node *_originalTarget;
/* 用startWithTarget设置 */
/* 当调用stop的时候置为null */
Node *_target;

/* 标识 */
int _tag;

private:
/* 禁用拷贝构造函数, 禁止重载等号运算符 */
CC_DISALLOW_COPY_AND_ASSIGN(Action);
};

其中 Clonable 只是一个接口,用于对象的拷贝,除此之外Action还禁用了拷贝构造函数重载等号运算符
对于一个Action的子类,你要实现实现以下方法:

  • virtual Action* clone() const = 0;
  • virtual Action* reverse() const = 0;
  • virtual bool isDone() const;
  • virtual void startWithTarget(Node *target);

FiniteTimeAction – 有限时间动作

FiniteTimeAction即ActionInstant和ActionIntavel的父类。

ActionInstant

  • duration = 0
  • 只调用一次

cocos2dx 3.0 —- ActionInstant

ActionInterval

  • duration >= 0
  • 可能调用多次

cocos2dx 3.0 —- ActionInterval


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class CC_DLL FiniteTimeAction : public Action
{
public:
inline float getDuration() const { return _duration; }
inline void setDuration(float duration) { _duration = duration; }

virtual FiniteTimeAction* reverse() const override = 0;
virtual FiniteTimeAction* clone() const override = 0;

protected:
FiniteTimeAction() : _duration(0) {}
virtual ~FiniteTimeAction(){}

/* 时长 */
float _duration;

private:
CC_DISALLOW_COPY_AND_ASSIGN(FiniteTimeAction);
};

然后就木有然后了。就定义了一个接口给瞬时动作延时动作用。

Speed – 变速动作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CC_DLL Speed : public Action
{
/* 此处略去 */

protected:
/* 在step中起关键作用 */
float _speed;

/* 保存目标动作 */
/* 强引用 */
ActionInterval *_innerAction;

private:
CC_DISALLOW_COPY_AND_ASSIGN(Speed);
};

step代码:

1
2
3
4
void Speed::step(float dt) 
{
_innerAction->step(dt * _speed);
}

最最关键的一点就在于此 — dt * _speed

Follow – 跟随动作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class CC_DLL Follow : public Action
{
public:
static Follow* create(Node *followedNode, const Rect& rect = Rect::ZERO);

inline bool isBoundarySet() const { return _boundarySet; }
/* 开启关闭边界 */
inline void setBoudarySet(bool value) { _boundarySet = value; }

virtual Follow* clone() const override;
virtual Follow* reverse() const override;
virtual void step(float dt) override;
virtual bool isDone() const override;
virtual void stop() override;

CC_CONSTRUCTOR_ACCESS:
/* 略去初始化函数,以及初始化列表 */

virtual ~Follow();

/* 跟随节点的引用计数会增加 */
bool initWithTarget(Node *followedNode, const Rect& rect = Rect::ZERO);

protected:
/* 跟随节点 */
Node *_followedNode;

/* 是否开启边界 */
bool _boundarySet;

/* 若边界大于整个屏幕,则不需要跟随动作了 */
bool _boundaryFullyCovered;

/* 快速访问屏幕尺寸 */
Point _halfScreenSize;
Point _fullScreenSize;

/* 边界 */
float _leftBoundary;
float _rightBoundary;
float _topBoundary;
float _bottomBoundary;
Rect _worldRect;

private:
CC_DISALLOW_COPY_AND_ASSIGN(Follow);
};

大致的流程是这样的:

  1. initWithTarget,传入跟随节点,修正自身位置(超出边界的情况)
  2. step 根据边界来计算出自身位置,并设置成计算后的位置。

总结

看看还是蛮简单=.. =