Action
对象就像它看起来的一样, 让 Node
执行一个对属性的变化. Action
对象允许及时地转化Node
属性。继承自 Node
的对都可以在上面执行 Action
对象。 举个例子, 你可以移动在一个段时间内把Sprite
一个从一个坐标移动到另一个坐标。
MoveTo
和 MoveBy
动作的例子:
1
2
3
4
5
6
7
|
// 在2秒内移动精灵到坐标50,10
var
moveTo = cc.moveTo(2,cc.p(50, 10));
mySprite1.runAction(moveTo);
// 在2秒内向右移动20个点
var
moveBy = cc.moveBy(2, cc.p(20,0));
mySprite2.runAction(moveBy);
|
By和To有什么区别呢?
你将会注意到每一个 Action
都有一个 By
和 To
版本.。为什么呢?他们有不同的实现方式。 By是相对于
Node的当前状态。
To
action 是绝对的, 这意味着不用考虑 Node的当前状态。
让我们看一个具体的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
var
mySprite =
new
cc.Sprite(res.node_png);
mySprite.setPosition(cc.p(200, 256));
this
.addChild(mySprite);
var
showPosition = cc.callFunc(
function
() {
cc.log(
"("
+
this
.getPositionX()+
","
+
this
.getPositionY()+
")"
);
}, mySprite);
cc.log(
"("
+ mySprite.getPositionX() +
","
+ mySprite.getPositionY() +
")"
);
// MoveBy - 让我们2秒内在x坐标上移动精灵200像素
// MoveBy 是相对的 - x = 200 + 200 ,在移动后是400
var
moveBy = cc.moveBy(2, cc.p(200, 0));
// MoveTo - 让我们2秒内移动精灵到(300,256)
// MoveTo 是绝对 - 不管现在在什么位置,精灵都将移动到(200,256)
var
moveTo = cc.moveTo(2, cc.p(300, mySprite.getPositionY()));
var
seq = cc.sequence(moveBy,showPosition, moveTo, showPosition);
mySprite.runAction(seq);
|
基本动作以及如何让它们执行起来
基本动作通常是完成一个目标的单一动作。 让我们看看几个例子:
Move
在一段时间内移动Node
的坐标。
var mySprite1 = new cc.Sprite(res.node_png); mySprite1.setPosition(cc.p(winSize.width / 4 , winSize.height / 4)); this.addChild(mySprite1); var mySprite2 = new cc.Sprite(res.node_png); mySprite2.setPosition(cc.p(winSize.width / 4 , winSize.height / 4 * 3)); this.addChild(mySprite2); // 在2秒内移动精灵到指定位置 var moveTo = cc.moveTo(2, cc.p(50, 0)); mySprite1.runAction(moveTo); // 在2秒内向右移动精灵50像素 var moveBy = cc.moveBy(2, cc.p(50, 0)); mySprite2.runAction(moveBy);
Rotate
在2秒内顺时针旋转一个 Node
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var
mySprite1 =
new
cc.Sprite(res.node_png);
mySprite1.setPosition(cc.p(winSize.width / 4 , winSize.height / 4));
this
.addChild(mySprite1);
var
mySprite2 =
new
cc.Sprite(res.node_png);
mySprite2.setPosition(cc.p(winSize.width / 4 , winSize.height / 4 * 3));
this
.addChild(mySprite2);
// Rotates a Node to the specific angle over 2 seconds
var
rotateTo = cc.rotateTo(2.0 , 40.0);
mySprite1.runAction(rotateTo);
// Rotates a Node clockwise by 40 degree over 2 seconds
var
rotateBy = cc.rotateBy(2.0, 40.0);
mySprite2.runAction(rotateBy);
|
Scale
在2秒内放大3倍 Node
然后再在2秒内x轴缩小为0.5,y轴缩小为0.3。
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
|
var
mySprite1 =
new
cc.Sprite(res.node_png);
mySprite1.setPosition(cc.p(winSize.width / 4 , winSize.height / 4));
this
.addChild(mySprite1);
var
mySprite2 =
new
cc.Sprite(res.node_png);
mySprite2.setPosition(cc.p(winSize.width / 4 , winSize.height / 4 * 3));
this
.addChild(mySprite2);
// Scale uniformly by 3x over 2 seconds
var
scaleBy1 = cc.scaleBy(2.0, 3.0);
// Scale X by 0.5 and Y by 0.3 over 2 seconds
var
scaleBy2 = cc.scaleBy(2.0, 0.5, 0.3);
var
scaleBySeq1 = cc.sequence(scaleBy1, scaleBy2);
mySprite1.runAction(scaleBySeq1);
// Scale to uniformly to 3x over 2 seconds
var
scaleTo1 = cc.scaleTo(2.0, 3.0);
// Scale X to 0.5 and Y to 0.3 over 2 seconds
var
scaleTo2 = cc.scaleTo(2.0, 0.5, 0.3);
var
scaleBySeq2 = cc.sequence(scaleTo1, scaleTo2);
mySprite2.runAction(scaleBySeq2);
|
Fade In/Out
淡入一个 Node
.
它从0到255修改透明度. 这一动作的反向是淡出。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var
mySprite =
new
cc.Sprite(res.node_png);
mySprite.setPosition(winSize.width / 2 , winSize.height / 2 );
this
.addChild(mySprite);
// fades in the sprite in 1 seconds
var
fadeIn = cc.fadeIn(1);
// fades out the sprite in 2 seconds
var
fadeOut = cc.fadeOut(2);
//连续动作
var
seq = cc.sequence(fadeOut, fadeIn);
mySprite.runAction(seq);
|
Tint
改变一个Node的RGB从当前颜色到一个自定义的着色。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
var
mySprite =
new
cc.Sprite(res.node_png);
mySprite.setPosition(winSize.width / 2 , winSize.height / 2 );
this
.addChild(mySprite);
//等待两秒
var
sleep = cc.delayTime(2);
var
showlog1 = cc.callFunc(
function
(){
cc.log(
"tintTo end"
);
});
var
showlog2 = cc.callFunc(
function
(){
cc.log(
"tintBy start"
);
},mySprite);
// Tints a node to the specified RGB values
var
tintTo = cc.tintTo(2.0, 120.0, 232.0, 254.0);
// Tints a node BY the delta of the specified RGB values.
var
tintBy = cc.tintBy(2, 120, 232, 254);
//连续动作
var
seq = cc.sequence(tintTo, showlog1, sleep, showlog2, tintBy);
mySprite.runAction(seq);
|
Animate
使用Animate
可以让你的 Sprite
对象做简单的原始动画。这只是在动画期间每隔一段时间替换显示帧。让我们细想下这个例子吧。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
cc.spriteFrameCache.addSpriteFrames(res.running_plist);
var
mySprite =
new
cc.Sprite(res.runner_png);
mySprite.setPosition(winSize.width / 2 , winSize.height / 2 );
this
.addChild(mySprite);
// now lets animate the sprite we moved
var
SpriteFrame = [];
for
(
var
i = 0; i < 8 ; i++ ){
var
str =
"runner"
+ i +
".png"
;
var
frame = cc.spriteFrameCache.getSpriteFrame(str);
SpriteFrame.push(frame);
}
// create the animation out of the frames
var
animation =
new
cc.Animation(SpriteFrame, 0.1);
var
animate = cc.animate(animation);
// run it and repeat it forever
mySprite.runAction(cc.repeatForever(animate));
|
很难在文本描述动画,所以请运行这个动作的示例代码来查看效果。
Easing
Easing是指定加速度的动画,以使动画平滑。 请记住无论是何种速度,ease动作总是在相同的时间开始和结束。Ease 动作是一个在你的游戏里伪造一个物理现象的好方法。或许你需要一些模拟的物理但是又不想增加开锁并增加几个非常基本的动力。 另一个很好的例子是动画菜单和按钮。
下面画片展示了常见的Easing函数:
Cocos2d-js支持Easing比上图提供的更多。它们也很容易实现。让我们来看看一个特定的用例吧。我们让一个Sprite
对象从屏幕的顶端掉下来并反弹。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// create a sprite
var
mySprite =
new
cc.Sprite(res.node_png);
mySprite.setPosition(winSize.width / 2, winSize.height - mySprite.getContentSize().height / 2);
this
.addChild(mySprite);
// create a MoveBy Action to where we want the sprite to drop from.
var
move = cc.moveBy(2, cc.p(0, - mySprite.getPositionY() + mySprite.getContentSize().height / 2 ));
var
move_back = move.reverse();
// create a BounceIn Ease Action
var
move_ease_in = move.easing(cc.easeIn(2));
var
move_ease_in_back = move_back.easing(cc.easeOut(2));
// create a delay that is run in between sequence events
var
delay =cc.delayTime(0.25);
// create the sequence of actions, in the order we want to run them
var
seq1 = cc.sequence(move_ease_in, delay, move_ease_in_back, delay);
// run the sequence and repeat forever.
mySprite.runAction(cc.repeatForever(seq1));
|
请运行这个动作的示例代码来查看效果。
Sequences以及如何来运行他们
Sequences是按顺序来执行一系列 Action
对象。这可以是任意数量的 Action
对象、 Functions 甚至是其他的 Sequence
。函数?是的! Cocos2d-js有一个 CallFunc
对象, 它允许你创建一个 function() 并传递给你正要执行的Sequence
。除了Cocos2d-js规定的stock Action
对象,这允许你增加自己的功能到你的Sequence
对象中。下面就是当Sequence
执行时的样子:
一个 sequence的例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
var
mySprite =
new
cc.Sprite(res.node_png);
mySprite.setPosition(winSize.width / 2, winSize.height / 2);
this
.addChild(mySprite);
// create a few actions.
var
jump = cc.jumpBy(0.5, cc.p(0, 0), 100, 1);
var
rotate = cc.rotateTo(2, 10);
// create a few callbacks
var
callbackJump = cc.callFunc(
function
(){
cc.log(
"Jumped!"
);
});
var
callbackRotate = cc.callFunc(
function
(){
cc.log(
"Rotated!"
);
});
// create a sequence with the actions and callbacks
var
seq = cc.sequence(jump, callbackJump, rotate, callbackRotate);
// run it
mySprite.runAction(seq);
|
所以这个 Sequence
动作做了什么?
它将按顺序执行以下操作:
Jump
-> callbackJump
-> Rotate
-> callbackRotate
请运行这个动作的示例代码来查看效果。
Spawn
Spawn 除了所有动作都在同一时间执行外和 Sequence
非常类似。你可以使用任意数量的Action
对象甚至是其他的Spawn
对象!
Spawn
产生的结果和连续执行多个runAction()
语句是相同的。但是,Spawn
的好处是可以把它放进一个Sequence
里来帮助实现用其他方式不能实现的特定效果。结合Spawn
和Sequence
是一个非常强大的特性。
给出的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// create 2 actions and run a Spawn on a Sprite
var
mySprite1 =
new
cc.Sprite(res.node_png);
mySprite1.setPosition(winSize.width / 4, winSize.height * 3 / 4);
this
.addChild(mySprite1);
var
moveBy1 = cc.moveBy(10, cc.p(400,100));
var
fadeTo1 = cc.fadeTo(2, 120);
var
mySprite2 =
new
cc.Sprite(res.node_png);
mySprite2.setPosition(winSize.width / 4, winSize.height * 2 / 4);
this
.addChild(mySprite2);
var
moveBy2 = cc.moveBy(10, cc.p(400,100));
var
fadeTo2 = cc.fadeTo(2, 120);
|
使用一个Spawn:
1
2
3
|
// running the above Actions with Spawn.
var
mySpawn = cc.spawn(moveBy1, fadeTo1);
mySprite1.runAction(mySpawn);
|
以及连续的 runAction() 语句:
1
2
3
|
// running the above Actions with consecutive runAction() statements.
mySprite2.runAction(moveBy2);
mySprite2.runAction(fadeTo2);
|
两个将会产生相同的结果。 然而,你可以在Sequence
使用Spawn
。这个流程图展示它看起来的样子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// create a Sprite
var
mySprite3 =
new
cc.Sprite(res.node_png);
mySprite3.setPosition(winSize.width / 4, winSize.height * 1 / 4);
this
.addChild(mySprite3);
// create a few Actions
var
moveBy3 = cc.moveBy(10, cc.p(200,30));
var
fadeTo3 = cc.fadeTo(2., 120);
var
scaleBy3 = cc.scaleBy(2, 3);
// create a Spawn to use
var
mySpawn3 = cc.spawn(scaleBy3, fadeTo3);
// tie everything together in a sequence
var
seq3 = cc.sequence(moveBy3, mySpawn3, moveBy3);
// run it
mySprite3.runAction(seq3);
|
请运行这个动作的示例代码来查看效果。
Reverse
Reverse就像它看起来那样执行。如果你运行一系列动作,你可以调用reverse()
来用相反的方向来执行它。然而不仅仅是简单地在相反运行。它实际上也操作在reverse中原始Sequence
或Spawn
的内容。使用上面的Spawn
例子来产生反向动作是很简单的。
1
2
|
// reverse a sequence, spawn or action
mySprite.runAction(mySpawn.reverse());
|
大多数 Action
和 Sequence
对象都是可逆的。
它使用起来很简单,但是让我们来确认下我们看见发生了什么。给出的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// create a Sprite
var
mySprite =
new
cc.Sprite(res.node_png);
mySprite.setPosition(50, 56);
this
.addChild(mySprite);
// create a few Actions
var
moveBy = cc.moveBy(2, cc.p(500,0));
var
scaleBy = cc.scaleBy(2, 2);
var
delay = cc.delayTime(2);
// create a sequence
var
delaySequence = cc.sequence(delay, delay.clone(), delay.clone(), delay.clone());
var
sequence = cc.sequence(moveBy, delay, scaleBy, delaySequence);
// run it
mySprite.runAction(sequence.repeatForever());
// reverse it
mySprite.runAction(sequence.reverse().repeatForever());
|
什么正在发生 ?我们列出的步骤的列表可能是有益于理解的:
mySprite
被创建mySprite
的坐标设置成 (50, 56)sequence
开始执行sequence
移动mySprite
向右 500, 用时2秒,mySprite
的新坐标是 (550, 56)sequence
等待2秒sequence
在2秒内放大mySprite
2倍sequence
等待另外6秒 (注意我们运行另一个序列来完成这一任务)我们在sequence上执行
reverse
, 所以我们运行了每个动作的倒退sequence
等待6秒sequence
在2秒内放大mySprite
-2xsequence
等待2秒sequence
向右移动mySprite
-500, 在2秒内,mySprite
的新坐标是 (50, 56)
你可以看到reverse()
使用起来很简单,但它的内在逻辑没那么简单。 Cocos2d-js 做了大部分艰巨的任务!