使用Promise/Deffered模式优化coco2d html5中的游戏动画!

问题:


在使用cocos2d html编写一系列的战斗动画时经常遇到一个精灵动作完成时需要继续播放另一个精灵动作 如下:


//动作1
actionSetp1: function() {
        ...
var move = cc.MoveTo.create(1, cc.p(100,100));
  //移动完后执行,actionStep2函数
var call = cc.CallFunc.create(this.onSetp2, this); 
var seq = cc.Sequence.create([move, call]);
this._sprite1.runAction(seq );
}


//动作2actionSetp1:
function() {
....
var scale= cc.ScaleTo.create(1, 1.5);
//移动完后执行,actionStep3函数
var call = cc.CallFunc.create(this.onSetp3, this); 
var seq = cc.Sequence.create([scale, call]); 
this._sprite2.runAction(seq );
}


//动作3
actionSetp3: function() {
....
//没有后继动作了,没有用cc.CallFunc
var move= cc.MoveTo.create(1, cc.p(100,100));
this._sprite.runAction(seq );
}






使用cc.CallFunc可以很好的解决这个问题. 但是当动作序列比较多超过7个后,感觉就有些力不从心了, 
每个动作函数需要知道自己接下来的动作,无疑增加了代码之间的耦合度. 


解决方法:
        这两天周未正好看了一下《深入浅出 node.js》一书中讲到在node中解决异步编程的问题使用Promise/Deffered模式解决异步函数深度嵌套的问题.
一下子就联想到自己在cocos2d html中游戏动画的问题.  于是将代码使用Deffer重构一下(下面代码使用了q.js 库 使用 npm install q 安装 )效果不错:


playAction: function() {

//这里需要将当前this对象传入
//动作按actionSetp1, actionSetp2, actionSetp3 顺序执行
this.actionSetp1(this)
.then(this.actionSetp2)
.then(this.actionSetp3);
}


//动作1
actionSetp1: function(self) { 
...
//使用q.js创建defer对象
var defer = Q.defer();
var move = cc.MoveTo.create(1, cc.p(100,100));
var call = cc.CallFunc.create(function() {
//执行defer.resolve()函数, 表示当前动作已经完成
//不需要知道下一个动作函数是什么
defer.resolve(self); 
}, self); 

var seq = cc.Sequence.create([move, call]);
self._sprite1.runAction(seq ); 
return defer .promise; //这里返回promise, 用于形成promise.then的调用链}

//动作2
actionSetp1: function(self) {
....
var defer = Q.defer(); //创建defervar 
var scale= cc.ScaleTo.create(1, 1.5); 
var call = cc.CallFunc.create(function() {
defer.resolve(self); 
}, self);
var seq = cc.Sequence.create([scale, call]);
self._sprite2.runAction(seq );

//这里返回promise, 用于形成promise.then的调用链
return defer .promise; 
}


//动作3
actionSetp3: function(self) {
....
//同上
var defer = Q.defer();            
var move= cc.MoveTo.create(1, cc.p(100,100));  
  var call = cc.CallFunc.create(function() {
defer.resolve(self);                    
}, self); 
    self._sprite.runAction(seq );

//这里返回promise, 用于形成promise.then的调用链
return defer .promise;
}






上面代码运行起来和之前版本完全一样, 咋一看代码还多一些. 但是后面这个版本中的每一个动作函数不需要关心动画链,
只关注自己需要完成的动作.


我们复制两行动作, 动作链如下:
  this.actionSetp1(this)                    
       .then(this.actionSetp2)          
  .then(this.actionSetp3);  //复制
  .then(this.actionSetp2);  //复制
       .then(this.actionSetp3);


我们修改一下,添加新动作, 动作链如下:
  this.actionSetp1(this)                    
       .then(this.actionSetp2)          
  .then(this.actionSetp3); 
  .then(this.actionSetp4);  //新增
       .then(this.actionSetp5);  //新增






相信大家已经明白其中的好处了吧!


---------------------------------------------------------------
注意:
      1. 在cocos2d html中使用q.js 是没有问题的, 但在jsb中使用q.js时会提示 setTimeout没有定义, 我是这样解决的:
mySetTimeout = function(callback, interval) {
    var director = cc.Director.getInstance();
    director.getScheduler().scheduleCallbackForTarget(director, callback, 0, 1, interval, false);
};


var setTimeout = setTimeout || mySetTimeout ;




    这里是使用cocos2d中的schedule来模拟的setTimeout函数


     2. 还有在   this.actionSetp1(this) .then(...).then(...)  由then调用链回调的函数this上下文并不是你当前类对象
        所以这里每一个 defer.resolve(self); 使用self将当前类对象向下传递.   

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值