(七)使用脚本控制动画

Animation 组件

Animation 组件提供了一些常用的动画控制函数,如果只是需要简单的控制动画,可以通过获取节点的 Animation 组件来做一些操作。

播放

var anim = this.getComponent(cc.Animation);

// 如果没有指定播放哪个动画,并且有设置 defaultClip 的话,则会播放 defaultClip 动画
anim.play();

// 指定播放 test 动画
anim.play('test');

// 指定从 1s 开始播放 test 动画
anim.play('test', 1);

// 使用 play 接口播放一个动画时,如果还有其他的动画正在播放,则会先停止其他动画
anim.play('test2');
Animation 对一个动画进行播放的时候会判断这个动画之前的播放状态来进行下一步操作。 如果动画处于:

停止 状态,则 Animation 会直接重新播放这个动画
暂停 状态,则 Animation 会恢复动画的播放,并从当前时间继续播放下去
播放 状态,则 Animation 会先停止这个动画,再重新播放动画
var anim = this.getComponent(cc.Animation);

// 播放第一个动画
anim.playAdditive('position-anim');

// 播放第二个动画
// 使用 playAdditive 播放动画时,不会停止其他动画的播放。如果还有其他动画正在播放,则同时会有多个动画进行播放
anim.playAdditive('rotation-anim');

Animation 是支持同时播放多个动画的,播放不同的动画并不会影响其他的动画的播放状态,这对于做一些复合动画比较有帮助。

暂停 恢复 停止

var anim = this.getComponent(cc.Animation);

anim.play('test');

// 指定暂停 test 动画
anim.pause('test');

// 暂停所有动画
// anim.pause();

// 指定恢复 test 动画
anim.resume('test');

// 恢复所有动画
// anim.resume();

// 指定停止 test 动画
anim.stop('test');

// 停止所有动画
// anim.stop();

暂停,恢复, 停止 几个函数的调用比较接近。

暂停 会暂时停止动画的播放,当 恢复 动画的时候,动画会继续从当前时间往下播放。 而 停止 则会终止动画的播放,再对这个动画进行播放的时候会重新从开始播放动画。

设置动画的当前时间

var anim = this.getComponent(cc.Animation);

anim.play('test');

// 设置 test 动画的当前播放时间为 1s
anim.setCurrentTime(1, 'test');

// 设置所有动画的当前播放时间为 1s
// anim.setCurrentTime(1);

你可以在任何时候对动画设置当前时间,但是动画不会立刻根据设置的时间进行状态的更改,需要在下一个动画的 update 中才会根据这个时间重新计算播放状态。

AnimationState

Animation 只提供了一些简单的控制函数,希望得到更多的动画信息和控制的话,需要使用到 AnimationState。

AnimationState 是什么?

如果说 AnimationClip 作为动画数据的承载,那么 AnimationState 则是 AnimationClip 在运行时的实例,它将动画数据解析为方便程序中做计算的数值。 Animation 在播放一个 AnimationClip 的时候,会将 AnimationClip 解析成 AnimationState。 Animation 的播放状态实际都是由 AnimationState 来计算的,包括动画是否循环,怎么循环,播放速度 等。

获取 AnimationState
var anim = this.getComponent(cc.Animation);
// play 会返回关联的 AnimationState
var animState = anim.play('test');

// 或是直接获取
var animState = anim.getAnimationState('test');
获取动画信息
var anim = this.getComponent(cc.Animation);
var animState = anim.play('test');

// 获取动画关联的clip
var clip = animState.clip;

// 获取动画的名字
var name = animState.name;

// 获取动画的播放速度
var speed = animState.speed;

// 获取动画的播放总时长
var duration = animState.duration;

// 获取动画的播放时间
var time = animState.time;

// 获取动画的重复次数
var repeatCount = animState.repeatCount;

// 获取动画的循环模式
var wrapMode = animState.wrapMode

// 获取动画是否正在播放
var playing = animState.isPlaying;

// 获取动画是否已经暂停
var paused = animState.isPaused;

// 获取动画的帧率
var frameRate = animState.frameRate;
设置动画播放速度
var anim = this.getComponent(cc.Animation);
var animState = anim.play('test');

// 使动画播放速度加速
animState.speed = 2;

// 使动画播放速度减速
animState.speed = 0.5;

speed 值越大速度越快,值越小则速度越慢

设置动画 循环模式 与 循环次数
var anim = this.getComponent(cc.Animation);
var animState = anim.play('test');

// 设置循环模式为 Normal
animState.wrapeMode = cc.WrapMode.Normal;

// 设置循环模式为 Loop
animState.wrapeMode = cc.WrapMode.Loop;

// 设置动画循环次数为2次
animState.repeatCount = 2;

// 设置动画循环次数为无限次
animState.repeatCount = Infinity;

AnimationState 允许动态设置循环模式,目前提供了多种循环模式,这些循环模式可以从 cc.WrapMode 中获取到。 如果动画的循环类型为 Loop 类型的话,需要与 repeatCount 配合使用才能达到效果。 默认在解析动画剪辑的时候,如果动画循环类型为:

  • Loop 类型,repeatCount 将被设置为 Infinity, 即无限循环
  • Normal 类型,repeatCount 将被设置为 1

动画事件

在动画编辑器里支持可视化编辑帧事件 (如何编辑请参考 这里 ),在脚本里书写动画事件的回调也非常简单。 动画事件的回调其实就是一个普通的函数,在动画编辑器里添加的帧事件会映射到动画根节点的组件上。

实例:

假设在动画的结尾添加了一个帧事件,如下图:


此处输入图片的描述
此处输入图片的描述

那么在脚本中可以这么写:

cc.Class({
    extends: cc.Component,

    onAnimCompleted: function (num, string) {
        console.log('onAnimCompleted: param1[%s], param2[%s]', num, string);
    }
});

将上面的组件加到动画的 根节点 上,当动画播放到结尾时,动画系统会自动调用脚本中的 onAnimCompleted 函数。 动画系统会搜索动画根节点中的所有组件,如果组件中有实现动画事件中指定的函数的话,就会对它进行调用,并传入事件中填的参数。

注册动画回调

除了动画编辑器中的帧事件提供了回调外,动画系统还提供了动态注册回调事件的方式。
目前支持的回调事件有:

play : 开始播放时
stop : 停止播放时
pause : 暂停播放时
resume : 恢复播放时
lastframe : 假如动画循环次数大于 1,当动画播放到最后一帧时
finished : 动画播放完成时

当在 cc.Animation 注册了一个回调函数后,它会在播放一个动画时,对相应的 cc.AnimationState 注册这个回调,在 cc.AnimationState 停止播放时,对 cc.AnimationState 取消注册这个回调。

cc.AnimationState 其实才是动画回调的发送方,如果希望对单个 cc.AnimationState 注册回调的话,那么可以获取到这个 cc.AnimationState 再单独对它进行注册。

实例

var animation = this.node.getComponent(cc.Animation);

// 注册
animation.on('play',      this.onPlay,        this);
animation.on('stop',      this.onStop,        this);
animation.on('lastframe', this.onLastFrame,   this);
animation.on('finished',  this.onFinished,    this);
animation.on('pause',     this.onPause,       this);
animation.on('resume',    this.onResume,      this);

// 取消注册
animation.off('play',      this.onPlay,        this);
animation.off('stop',      this.onStop,        this);
animation.off('lastframe', this.onLastFrame,   this);
animation.off('finished',  this.onFinished,    this);
animation.off('pause',     this.onPause,       this);
animation.off('resume',    this.onResume,      this);

// 对单个 cc.AnimationState 注册回调
var anim1 = animation.getAnimationState('anim1');
anim1.on('lastframe',    this.onLastFrame,      this);

动态创建 Animation Clip

    var animation = this.node.getComponent(cc.Animation);
    // frames 这是一个 SpriteFrame 的数组.
    var clip = cc.AnimationClip.createWithSpriteFrames(frames, 17);
    clip.name = "anim_run";
    clip.warpMode = cc.WarpMode.Loop;

    // 添加帧事件
    clip.events.push({
        frame: 1,               // 准确的时间,以秒为单位。这里表示将在动画播放到 1s 时触发事件
        func: "frameEvent",     // 回调函数名称
        params: [1, "hello"]    // 回调参数
    });

    animation.addClip(clip);
    animation.play('anim_run');
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,431评论 25 707
  • 曾经做过一个很美的梦,从小我就很喜欢看电视剧中的故事,喜欢里面的人物,情节,表演,我从小最大的梦想就是长大之...
    萌萌哒小梳子阅读 500评论 0 1
  • 总有一些人减肥速度会快一些,有的人拼命减肥,体重却降的特别慢! 那么,哪些人减肥快,哪些人减肥慢?你属于哪一类呢?...
    伟国阅读 543评论 1 0
  • 一地斑驳月光白骨苍苍 照凉世间繁华,照凉世间迷离 都说烟火温暖 清波归棹 那时,天真,温润时光 目光清澈,枯萎满地...
    才女式微阅读 682评论 25 22