源代码下载http://www.oschina.net/code/snippet_2288842_48335
Action
对象就像它看起来的一样, 让 Node
执行一个对属性的变化. Action
对象允许及时地转化Node
属性。继承自 Node
的对都可以在上面执行 Action
对象。 举个例子, 你可以移动在一个段时间内把Sprite
一个从一个坐标移动到另一个坐标。
MoveTo
和 MoveBy
动作的例子:
// 在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的当前状态。
让我们看一个具体的例子:
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);
基本动作通常是完成一个目标的单一动作。 让我们看看几个例子:
在一段时间内移动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);
在2秒内顺时针旋转一个 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); // 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);
在2秒内放大3倍 Node
然后再在2秒内x轴缩小为0.5,y轴缩小为0.3。
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);
淡入一个 Node
.
它从0到255修改透明度. 这一动作的反向是淡出。
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);
改变一个Node的RGB从当前颜色到一个自定义的着色。
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
可以让你的 Sprite
对象做简单的原始动画。这只是在动画期间每隔一段时间替换显示帧。让我们细想下这个例子吧。
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是指定加速度的动画,以使动画平滑。 请记住无论是何种速度,ease动作总是在相同的时间开始和结束。Ease 动作是一个在你的游戏里伪造一个物理现象的好方法。或许你需要一些模拟的物理但是又不想增加开锁并增加几个非常基本的动力。 另一个很好的例子是动画菜单和按钮。
下面画片展示了常见的Easing函数:
Cocos2d-js支持Easing比上图提供的更多。它们也很容易实现。让我们来看看一个特定的用例吧。我们让一个Sprite
对象从屏幕的顶端掉下来并反弹。
// 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是按顺序来执行一系列 Action
对象。这可以是任意数量的 Action
对象、 Functions 甚至是其他的 Sequence
。函数?是的! Cocos2d-js有一个 CallFunc
对象, 它允许你创建一个 function() 并传递给你正要执行的Sequence
。除了Cocos2d-js规定的stock Action
对象,这允许你增加自己的功能到你的Sequence
对象中。下面就是当Sequence
执行时的样子:
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 除了所有动作都在同一时间执行外和 Sequence
非常类似。你可以使用任意数量的Action
对象甚至是其他的Spawn
对象!
Spawn
产生的结果和连续执行多个runAction()
语句是相同的。但是,Spawn
的好处是可以把它放进一个Sequence
里来帮助实现用其他方式不能实现的特定效果。结合Spawn
和Sequence
是一个非常强大的特性。
给出的例子:
// 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:
// running the above Actions with Spawn. var mySpawn = cc.spawn(moveBy1, fadeTo1); mySprite1.runAction(mySpawn);
以及连续的 runAction() 语句:
// running the above Actions with consecutive runAction() statements. mySprite2.runAction(moveBy2); mySprite2.runAction(fadeTo2);
两个将会产生相同的结果。 然而,你可以在Sequence
使用Spawn
。这个流程图展示它看起来的样子:
// 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中原始Sequence
或Spawn
的内容。使用上面的Spawn
例子来产生反向动作是很简单的。
// reverse a sequence, spawn or action mySprite.runAction(mySpawn.reverse());
大多数 Action
和 Sequence
对象都是可逆的。
它使用起来很简单,但是让我们来确认下我们看见发生了什么。给出的例子:
// 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
-2x
sequence
等待2秒
sequence
向右移动 mySprite
-500, 在2秒内, mySprite
的新坐标是 (50, 56)
你可以看到reverse()
使用起来很简单,但它的内在逻辑没那么简单。 Cocos2d-js 做了大部分艰巨的任务!
参考:http://cocos2d-x.org/wiki/Actions