使用贝塞尔曲线设计飞升动画

在游戏中,资源的获取或者奖励的获得,都会有一个简单的动画,以提高用户体验。

引擎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函数主要是初始化。
  fly函数实现了两个贝赛尔曲线(bezier和nextBezier),进行Bezier后调delayTime延时0.05作为停顿效果,再进行nextBezier。
  update主要用于资源的管理,更新(比如飞到位后根据this.actionState动作的状态消失)。
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 重新创建。
  putInPool:将节点放进对象池,这个方法会同时调用节点的 removeFromParent。
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却没有调用,这是个疑惑点,研究下。
  加油!

你可能感兴趣的:(游戏开发,贝塞尔曲线,资源飞升动作,游戏开发)