在游戏中,资源的获取或者奖励的获得,都会有一个简单的动画,以提高用户体验。
引擎cocos creator 语言JavaScript
1.在资源点开始要做个简单的出现的动画,之后停顿很短时间,让玩家有感觉。
2.停顿完成后飞升到顶部资源栏此资源处。
3.到达顶部资源处后,此资源显示出做出接受飞升上来的资源的动画。
使用贝塞尔曲线,延时
设飞升起点为A,停顿点为B,重点为C
1.在资源栏资源处添加一个动画。
2.资源在A点时,做第一段贝赛尔曲线运动到B点,距离不能太远,用时不能太长。
3.资源到达B点时,设计一个延时再做下一段动画,延时时间不能太长影响体验。
4.在延时后做第二段贝塞尔曲线运动到达C点。
5.到达C点时,飞升上来的资源消失,大概同时播放资源栏资源处的动画。
1.此处用3个金币来做飞升动作。id用来标识是哪个资源(此处为金币),initPos为起始坐标,targetPos为终点坐标。最后发出事件。
for (var i = 0; i < 3; i++) {
var ev = new cc.Event.EventCustom('onPickRes', true);
ev.setUserData({
resID: tb.TID_RESOURCE_MONEY,
initPos: kf.getLocationInRoot(this.flyGoldNode),
targetPos: {x: 0, y : 0}
});
this.node.dispatchEvent(ev);
}
2.这里为收到1事件的处理,首先如果是这个资源,进行初始设置。flyResItemName为动画的那个类(它作为组件的);targetPos为重新设置的终点位置;this.flyGoldNode为挂载飞升上去后资源栏那个资源动画的节点;this.titleBar是其他隐藏掉的东西;this.flyGoldAnimation为飞升上去后资源栏那个资源的动画(动画前0.5s啥都不做,未来和飞升动作匹配);script代表贝赛尔曲线那个类(3就是那个类)。
if(resID === tb.TID_RESOURCE_MONEY) {
flyResItemName = "flyResGold";
targetPos = kf.getLocationInRoot(this.flyGoldNode);
this.flyGoldNode.active = true;
this.titleBar.getComponent("titleBar").setGoldIcon(false);
this.flyGoldAnimation.play( );
}
if(!flyResItemName) return;
var instance = this.preloadLogic.getPrefabEx(flyResItemName);
var script = instance.getComponent(flyResItemName);
script.init(initPos, targetPos);
this.node.addChild(instance);
script.fly();
3.飞升-停顿-飞升动画的实现
init函数主要是初始化。
cc.Class({
extends: cc.Component,
properties: {
},
// use this for initialization
onLoad: function () {
this.preloadLogic = kf.require("logic.preload");
},
init: function (initPos, targetPos) {
this.actionState = null;
this.initPos = initPos;
this.targetPos = targetPos;
},
fly: function () {
this.node.setPosition(this.initPos);
this.node.stopAllActions();
var bezier = [cc.p(this.initPos.x + Math.random()*20, this.initPos.y + Math.random()*20), cc.p(this.initPos.x + Math.random()*40, this.initPos.y + Math.random()*40), cc.p(this.initPos.x+ Math.random()*80, this.initPos.y + Math.random()*50)];
var action = cc.bezierTo(0.5, bezier);
var nextBezier = [cc.p(this.node.x + Math.random()*200 - 100, this.node.y + 200), cc.p(this.node.x + Math.random()*200 - 100, this.node.y + 350), this.targetPos];
var nextAction = cc.bezierTo(0.5, nextBezier);
this.actionState = this.node.runAction(cc.sequence(action, cc.sequence(cc.delayTime(0.05), nextAction)));
},
update: function () {
if(this.actionState && this.actionState.isDone()){
this.preloadLogic.putInPool(this.node.name, this.node);
this.actionState = null;
}
}
});
4.对象池中对象管理。
getPrefabEx:size判断对象池中是否有空闲对象。如果没有空闲对象,也就是对象池中备用对象不够时,我们就用 cc.instantiate 重新创建。
preloadLogic.getPrefabEx = function (name) {
var prefab = undefined;
if(this.isPool(name)){
var pool = this[name+'Pool'];
if (pool.size() > 0) {
prefab = pool.get();
this.reRegisterEvent(prefab,name);
} else {
prefab = cc.instantiate(this[name+'Prefab']);
}
}
return prefab;
};
preloadLogic.putInPool = function (name, prefab) {
var pool = this[name+'Pool'];
if(pool){
var js = prefab.getComponent(name);
if (js && js.unregisterEvent) {
js.unregisterEvent();
js.registerHandler = [];
}
pool.put(prefab);
}
};
preloadLogic.isPool = function (name) {
return this[name + "Pool"] && this[name + "Prefab"];
};
preloadLogic.reRegisterEvent = function(node,name){
var jsComp = node.getComponent(name);
if (jsComp && jsComp.registerEvent && jsComp._isOnLoadCalled !== 0)
jsComp.registerEvent();
};
在过程中有几次设计问题,在资源栏资源那个动画处,本来动画没有前0.5s啥不做这个设计,也想用延时来做,但是在delay之后,动画play却没有调用,这是个疑惑点,研究下。
加油!