[CocosCreator]封装可续播帧动画

        欢迎喜欢或者从事CocosCreator开发的小伙伴请加入我的大家庭CocosCreator游戏开发Q群:26855530 

        在CocosCreator的官方文档中,提供播放帧动画的组件是Animation,在一般的情况下是可以满足大部分的游戏需求的.但是有时,在播放动画的时候,比如人物的行走的动作时,一旦方向改变,或者动作改动,该组件便会重第1帧执行你指定的动作,这个并不符合我们的需求.

        我们的需求是:当前播放到第n帧时,切换下个动作应该从第n+1帧续播.

        于是乎就有了今天这篇博客.在浏览官方的源码之后,再结合我自身的需求,我自己写了一个组件,代码如下:

import DynamicAssetManager from "../manager/DynamicAssetManager";

const {ccclass} = cc._decorator;
/**
 * 可续播帧动画组件
 */
@ccclass
export default class FrameAnimation extends cc.Component {
    @property(cc.Node)
    frameNode: cc.Node = null;
    private _onPlay: Function;
    private _onFinish: Function;

    //增加对象池引用
    reuse() {
        this.frameNode.getComponent(cc.Sprite).spriteFrame = null;
        this.frameNode.getComponent(cc.Animation).stop();
    }

    unuse() {
        this.frameNode.getComponent(cc.Sprite).spriteFrame = null;
        this.frameNode.getComponent(cc.Animation).stop();
        DynamicAssetManager.pullAsset(this.node, this.constructor.name);
    }

    //增加开始动画和结束动画的函数回调
    onEnable() {
        let animation = this.frameNode.getComponent(cc.Animation);
        animation.on("play", this.onEvent, this);
        animation.on("finished", this.onEvent, this);
    }

    /**
     * 入口函数
     * @param value 动画帧集路径
     * @param speed 动画播放速度
     * @param onPlay 开始播放回调函数
     * @param onFinish 结束播放回调函数
     */
    public showEffect(value: string, speed: number, onPlay?: Function, onFinish?: Function) {
        if (!this.frameNode.active) {
            SysLog.error("showEffect:????????????????????????");
            return;
        }

        if (onPlay && "function" == typeof (onPlay)) {
            this._onPlay = onPlay;
        }

        if (onFinish && "function" == typeof (onFinish)) {
            this._onFinish = onFinish;
        }

        
        this.playAni(this.frameNode, value, speed);
    }

    private playAni(node: cc.Node, url: string, speed: number) {
        if (!node) {
            SysLog.debug("必须有结点才能播放动画", url);
            return;
        }
        if (!url || url.length < 1) {
            let sprite = node.getComponent(cc.Sprite);
            sprite.spriteFrame = null;
            let ani = node.getComponent(cc.Animation);
            ani.stop();
            return;
        }
        DynamicAssetManager.load(this.node, url, cc.SpriteAtlas, (atlas: cc.SpriteAtlas) => {
            this.playOfAtlas(node, atlas, url, speed);
        });
    }

    // 通过纹理图集播放动画
    private playOfAtlas(node: cc.Node, atlas: cc.SpriteAtlas, url: string, speed?: number) {
        let frames: cc.SpriteFrame[] = atlas.getSpriteFrames();
        let clip: cc.AnimationClip = cc.AnimationClip.createWithSpriteFrames(frames, 12);
        clip.name = url;
        clip.wrapMode = cc.WrapMode.Normal;
        let sprite = node.getComponent(cc.Sprite);
        sprite.spriteFrame = frames[0];
        sprite.sizeMode = cc.Sprite.SizeMode.RAW;
        sprite.trim = false;
        let ani: cc.Animation = node.getComponent(cc.Animation);
        let index = ani.getClips().indexOf(clip);
        if (index == -1) {
            ani.addClip(clip);
        }
        let state: cc.AnimationState = ani.play(clip.name);
        state.speed = speed > 0 ? speed : 1;
    }


    onEvent(type: string, state: cc.AnimationState) {
        // SysLog.debug(`11111111type:${type},state:${state}`)
        if ("play" == type && this._onPlay) {
            this._onPlay(state);
        }
        if ("finished" == type && this._onFinish) {
            this._onFinish();
        }
    }

    onDisable() {
        this._onPlay = this._onFinish = null;
        let animation = this.frameNode.getComponent(cc.Animation);
        animation.off("play", this.onEvent, this);
        animation.off("finished", this.onEvent, this);
    }

    onDestroy(): void {
        DynamicAssetManager.pullAsset(this.node, this.constructor.name);
    }
}

嗯......想了一下也没有需要说明的,注释都很清晰使用也非常方便,哪里要播动画挂哪里,

 非常好用~

       Tips:二次修改之后,把该代码插件化,只要直接调用入口函数即可,另外也增加了动画事件的监听,考虑常用的只监听开始和结束事件,稍微优化了代码的结构....最后,感谢大家支持!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值