Cocos2d-X与游戏开发Cocos Creator

Cocos Creator封装自己的帧动画组件播放动画

2020-08-20  本文已影响0人  Thomas游戏圈

前言

在Cocos Creator游戏开发的过程中我们进行需要使用动画效果,虽然可以通过动画编辑器编辑动画效果,但是有时候用户想更灵活的控制帧动画的效果,就需要自己封装帧动画组件。

一、 帧动画播放组件

1: creator播放帧动画需要通过动画编辑器去制作;

2: 为了方便控制和使用加入帧动画代码播放组件;

3: 属性设置:

     sprite_frames: 帧动画所用到的所有的帧;

     duration: 每帧的时间间隔;

     loop: 是否循环播放;

     play_onload: 是否加载组件的时候播放;

4: 接口设置:

     play_once(end_func); // 播放结束后的回掉函数;

     play_loop(); // 循环播放;

二、 帧动画播放原理

1: 对的时间播放显示对的图片:

假设以三帧动画为例,时间间隔就是duration,

[图片上传失败...(image-172f06-1597889249322)]

三、 自己封装帧动画组件

const {ccclass, property} = cc._decorator;

@*ccclass*

export default class FrameAnim extends *cc*.*Component* {

    @property({type: [cc.*SpriteFrame*], tooltip:"帧动画图片数组"})

spriteFrames : *Array*<*cc*.*SpriteFrame*> = [];

    @property({tooltip:"每一帧的时长"})

duration : *number* = 0.1;

    @property({tooltip:"是否循环播放"})

    loop : *boolean* = false;

    @property({tooltip:"是否在加载的时候就开始播放"})

playOnload : *boolean* = false;

    // 播放完后的回调函数

    private endFunc : *any* = null;

    // 动画播放需要的精灵组件

    private sprite : *cc*.*Sprite*;

    // 动画播放的状态,正在播放还是停止

    private isPlaying : *boolean* = false;

    // 记录已经播放的时间

private playTime : *number* = 0;

    onLoad () {

        // 获取当前动画组件挂载的节点上的Sprite组件,如果没有则添加

        *this*.sprite = *this*.node.getComponent(cc.Sprite);

        if(!*this*.sprite){

            *this*.sprite = *this*.node.addComponent(cc.Sprite);

        }

        // 判断是否是预加载播放

        if(*this*.playOnload){

            if(*this*.loop){

                *this*.playLoop();        // 循环播放

            }else{

                *this*.playOnce(null);    // 只播放一次

            }

        }

}

    public playLoop() : *void* {

        *this*.initFrame(true, null);

}   

    public playOnce(*endf* : *any*) : *void* {

        *this*.initFrame(false, endf);

}

    private initFrame(*loop*:*boolean*, *endf* : *any*) : *void*{

        if(*this*.spriteFrames.length <= 0){

            return;

        }

        *this*.isPlaying = true;

        *this*.playTime = 0;

        *this*.sprite.spriteFrame = *this*.spriteFrames[0];

        *this*.loop = loop;

        *this*.endFunc = endf;

}

start () {

}

    update (*dt*) {

        if(!*this*.isPlaying){

            return;

        }

        // 累计时间,通过时间计算应该取哪一张图片展示

        *this*.playTime += dt;

        let index : *number* = Math.floor(*this*.playTime / *this*.duration);

        if(*this*.loop){  // 循环播放

            if(index >= *this*.spriteFrames.length){

                index -= *this*.spriteFrames.length;

                *this*.playTime -= (*this*.duration * *this*.spriteFrames.length);

            }

            *this*.sprite.spriteFrame = *this*.spriteFrames[index];

        }else{          // 播放一次

            if(index >= *this*.spriteFrames.length){

                *this*.isPlaying = false;

                // 如果有回调函数的处理,则调用回调函数

                if(*this*.endFunc){

                    *this*.endFunc();

                }

            }else{

                *this*.sprite.spriteFrame = *this*.spriteFrames[index];

            }

        }

    }

}

四、 测试封装的帧动画组件

勾选PlayOnLoad和去掉的区别,勾选Loop和去掉的区别,可以发现预加载和循环播放。

如何在代码中控制?

新建GameMgr.ts挂载到Canvas节点上。

import FrameAnim from "./FrameAnim";

const {ccclass, property} = cc._decorator;

@*ccclass*

export default class GameMgr extends *cc*.*Component* {

    @property({type: [*FrameAnim*], tooltip:"帧动画数组"})

    anim : *Array*<*FrameAnim*> = [];

// onLoad () {}

    endPlay(){

        *console*.log("动画播放完毕!!");

    }

    start () {

        //this.anim[0].playOnce(this.endPlay);

        //this.anim[1].playOnce(this.endPlay);

        //this.anim[0].playOnce(null);

        //this.anim[1].playOnce(null);

        //this.anim[0].playLoop();

        //this.anim[1].playLoop();

        if(*this*.anim.length > 1){

            *this*.anim[1].duration = 0.5;

            *this*.anim[1].playOnce(*this*.endPlay);

        }

        if(*this*.anim.length > 0){

            *this*.anim[0].playLoop();

        }

    }

}

上一篇 下一篇

猜你喜欢

热点阅读