目录
图集动画·概述
1、游戏开发中,动画的运用基本无处不在,LayaAir 引擎提供了功能强大的的 laya.display.Animation 动画类,它可以使用多种动画资源生成游戏动画。
2、可以用 LayaAir IDE 创建时间轴动画的方式生成后缀名为 “.ani” 的动画资源,也可以用图集打包动画帧图片的方式,创建后缀名为 “.atlas” 的图集资源,然后赋给动画类去加载使用。
3、本文讲解图集动画时间轴动画后续会进行讲解,关于图集动画的图集制作,请参考《 LayaAir 图集动画1—图集制作》,本文对于图集制作不做累述。
4、动画图集资源像角色类动画因为帧数较多,一般是一套角色图一个资源,在命名上根据动作名称加帧序号命名。
5、LayaAir IDE 中的图集打包工具,会将每一个目录打包为一个图集吗,特效类动画因为每个特效帧数量不多可以多个特效组合成一张图集资源(放在一个目录内)。
Animation
Package | laya.display |
类 | public class Animation |
Inheritance | Animation |
1、laya.display.Animation 类是 Graphics 动画类,实现了基于 Graphics 的动画创建、播放、控制接口。
2、Animation 类使用了动画模版缓存池,以一定的内存开销来节省CPU开销,当相同的动画模版被多次使用时,相比于每次都创建新的动画模版,使用动画模版缓存池,只需创建一次,缓存之后多次复用,从而节省了动画模版创建的开销。
3、动画模版缓存池,以 key-value 键值对存储,key 可以自定义,也可以从指定的配置文件中读取,value 为对应的动画模版,是一个 Graphics 对象数组,每个 Graphics 对象对应一个帧图像,动画的播放实质就是定时切换 Graphics 对象。
4、使用 loadImages(...)、loadAtlas(...)、loadAnimation(...) 方法可以创建动画模版,使用 play() 可以播放指定动画
图集动画·运用
加载动画图集资源并播放
通过 laya.display.Animation 类的 loadAtlas() 方法加载角色的图集动画资源。
/**<p>根据指定的动画模版初始化当前动画序列帧。选择动画模版的过程如下:1. 动画模版缓存池中key为cacheName的动画模版;2. 如果不存在,则加载指定的图集并创建动画模版。</p>
* <p>注意:只有指定不为空的cacheName,才能将创建好的动画模版以此为key缓存到动画模版缓存池,否则不进行缓存。</p>
* <p>动画模版缓存池是以一定的内存开销来节省CPU开销,当相同的动画模版被多次使用时,相比于每次都创建新的动画模版,使用动画模版缓存池,只需创建一次,缓存之后多次复用,从而节省了动画模版创建的开销。</p>
* <p>因为返回值为Animation对象本身,所以可以使用如下语法:loadAtlas(...).loadAtlas(...).play(...);。</p>
* @param url 图集路径。需要创建动画模版时,会以此为数据源。
* @param loaded (可选)使用指定图集初始化动画完毕的回调。
* @param cacheName (可选)动画模板在动画模版缓存池中的key。如果此参数不为空,表示使用动画模版缓存池。如果动画模版缓存池中存在key为cacheName的动画模版,则使用此模版。否则,创建新的动画模版,如果cacheName不为空,则以cacheName为key缓存到动画模版缓存池中,如果cacheName为空,不进行缓存。
* @return 返回动画本身。
*/
loadAtlas(url: string, loaded?: Handler, cacheName?: string): Animation;
图集动画使用 loadAtlas() 方法加载后,需要使用 play() 方法才可以播放。
/**<p>开始播放动画。会在动画模版缓存池中查找key值为name的动画模版,存在则用此动画模版初始化当前序列帧, 如果不存在,则使用当前序列帧。</p>
* <p>play(...)方法被设计为在创建实例后的任何时候都可以被调用,调用后就处于播放状态,当相应的资源加载完毕、调用动画帧填充方法(set frames)或者将实例显示在舞台上时,会判断是否处于播放状态,如果是,则开始播放。</p>
* <p>配合wrapMode属性,可设置动画播放顺序类型。</p>
* @param start (可选,默认为0)指定动画播放开始的索引(int)或帧标签(String)。帧标签可以通过addLabel(...)和removeLabel(...)进行添加和删除。
* @param loop (可选,默认为true)是否循环播放。
* @param name (可选,默认为空)动画模板在动画模版缓存池中的key,也可认为是动画名称。如果name为空,则播放当前动画序列帧;如果不为空,则在动画模版缓存池中寻找key值为name的动画模版,如果存在则用此动画模版初始化当前序列帧并播放,如果不存在,则仍然播放当前动画序列帧;如果没有当前动画的帧数据,则不播放,但该实例仍然处于播放状态。
*/
play(start?: any, loop?: boolean, name?: string): void;
//初始化舞台
Laya.init(1334, 750,Laya.WebGL);
//设置舞台背景色
Laya.stage.bgColor = "#007ACC";
//创建猎豹、小女孩动画实例
let leopardAni = new Laya.Animation();
let girlAni = new Laya.Animation();
//设置精灵的位置
leopardAni.pos(100,50);
girlAni.pos(300,60);
//加载动画图集,加载成功后执行回调方法
//Handler 是事件处理器类,create 从对象池内创建一个Handler,默认会执行一次并立即回收
//制作好的图集文件 .atlas、.png 放入到 bin/res/atlas 目录下
leopardAni.loadAtlas("res/atlas/leopard.atlas",Laya.Handler.create(this,onLoaded));
function onLoaded(){
//添加到舞台
Laya.stage.addChild(leopardAni);
//设置播放间隔,单位毫秒,默认为 50。意思就是播放图集中的序列帧图像的间隔时间
leopardAni.interval = 100;
//播放动画
leopardAni.play();
}
//与上同理
girlAni.loadAtlas("res/atlas/girs.atlas",Laya.Handler.create(this,girlOnLoad));
function girlOnLoad(){
Laya.stage.addChild(girlAni);
girlAni.interval = 80;
girlAni.play();
}
需要动画图片资源的可以下载:https://download.csdn.net/download/wangmx1993328/10852378
createFrames创建模板播放图集中指定动画
1、如果图集中是独立的序列帧动画,直接使用 play() 方法就可以播放,但将多个动画打包到一个图集里时,如果要播放指定的动画,那就需要通过创建动画模板来实现。
2、使用 LayaAir 打包工具将上面的 猎豹与小姑娘打包到一个图集中,如下所示为 leo_girl,显然这样混合在一起之后,如果在 loadAtlas 之后直接 play 显然是不行的,而是应该播放其中指定的动画(指定的图片集合)
2、Animation.createFrames() 方法创建动画模板来实现播放图集中指定的动画。
/** <p>创建动画模板,多个动画可共享同一份动画模板,而不必每次都创建一份新的,从而节省创建Graphics集合的开销。</p>
* @param url 图集路径或者图片路径数组。如果是图集路径,需要相应图集已经被预加载,如果没有预加载,会导致创建失败。
* @param name 动画模板在动画模版缓存池中的key。如果不为空,则以此为key缓存动画模板,否则不缓存。
* @return 动画模板。
*/
static createFrames(url: any, name: string): Array<any>;
//初始化舞台
Laya.init(1334, 750,Laya.WebGL);
//设置舞台背景色
Laya.stage.bgColor = "#A61F2C";
//创建猎豹、小女孩动画实例
let leopardAni = new Laya.Animation();
let girlAni = new Laya.Animation();
//设置精灵的位置
leopardAni.pos(100,50);
girlAni.pos(300,60);
//加载动画图集,加载成功后执行回调方法
//Handler 是事件处理器类,create 从对象池内创建一个Handler,默认会执行一次并立即回收
//制作好的图集文件 .atlas、.png 放入到 bin/res/atlas 目录下
leopardAni.loadAtlas("res/atlas/leo_girl.atlas",Laya.Handler.create(this,onLoaded));
function onLoaded(){
//添加到舞台
Laya.stage.addChild(leopardAni);
//设置播放间隔,单位毫秒,默认为 50。意思就是播放图集中的序列帧图像的间隔时间
leopardAni.interval = 100;
//获取图集中指定的动画序列帧
let leoArr = createAniUrls("leo_girl/Leopard",8);
//创建动画模板.这是一个静态方法.以 ani_leoArr 的名称缓存到动画模版缓存池中
//第一个参数可以是图集路径或者图片路径数组,注意数组元素必须是 .atlas或者.json文件中prefix的值加上序列帧图片的值
Laya.Animation.createFrames(leoArr,"ani_leoArr");
//播放动画,第三个参数不为空时,则从动画模版缓存池中寻找key值为name的动画模版序列帧进行播放,当不存在 ani_leoArr 时,则仍然播放当前序列帧 leopardAni
leopardAni.play(0,true,"ani_leoArr");
}
//与上同理
girlAni.loadAtlas("res/atlas/girs.atlas",Laya.Handler.create(this,girlOnLoad));
function girlOnLoad(){
Laya.stage.addChild(girlAni);
girlAni.interval = 80;
let girlArr = createAniUrls("leo_girl/girl_0",6);
Laya.Animation.createFrames(girlArr,"ani_girlArr");
girlAni.play(0,true,"ani_girlArr");
}
//根据路径与长度值生成一个 url 数组
//约定图集后缀名为 .png ,图集中的图片序号从 1 开始
//url:如 leo_girl/girl_0 后面的的部分 x.png 会自动补全
//length:表示创建的个数
function createAniUrls(url,length){
let urls = [];
for(let i=0;i<length;i++){
urls.push(url+(i+1)+".png");
}
console.log(urls);
return urls;
}
3、尽管把每一组动作单独打包成图集,也可以直接播放。但是对于动作较少的动画资源去单独打成图集,会增加资源加载量以及增加游戏性能的消耗。所以将帧数不多的多组动画打包到一个图集中,然后分别调用是推荐的方式。
loadImages直接播放图集中指定动画
1、除了用静态方法 createFrames() 创建动画模板外,还可以用 loadImages() 方法来实现播放图集中指定的序列帧。
/**<p>根据指定的动画模版初始化当前动画序列帧。选择动画模版的过程如下:1. 动画模版缓存池中key为cacheName的动画模版;2. 如果不存在,则加载指定的图片集合并创建动画模版。注意:只有指定不为空的cacheName,才能将创建好的动画模版以此为key缓存到动画模版缓存池,否则不进行缓存。</p>
* <p>动画模版缓存池是以一定的内存开销来节省CPU开销,当相同的动画模版被多次使用时,相比于每次都创建新的动画模版,使用动画模版缓存池,只需创建一次,缓存之后多次复用,从而节省了动画模版创建的开销。</p>
* <p>因为返回值为Animation对象本身,所以可以使用如下语法:loadImages(...).loadImages(...).play(...);。</p>
* @param urls 图片路径集合。需要创建动画模版时,会以此为数据源。参数形如:[url1,url2,url3,...]。
* @param cacheName (可选,默认为空)动画模板在动画模版缓存池中的key。如果此参数不为空,表示使用动画模版缓存池。如果动画模版缓存池中存在key为cacheName的动画模版,则使用此模版。否则,创建新的动画模版,如果cacheName不为空,则以cacheName为key缓存到动画模版缓存池中,如果cacheName为空,不进行缓存。
* @return 返回Animation对象本身。
*/
loadImages(urls: Array<any>, cacheName?: string): Animation;
2、由于 loadImages() 创建动画模板,urls 接收的是图片地址集合,所以需要先使用 Laya.loader.load() 将图集文件先加载完成,或者仍然使用 loadAtlas 加载图集资源。
//初始化舞台
Laya.init(1334, 750,Laya.WebGL);
//设置舞台背景色
Laya.stage.bgColor = "#57AEFD";
//创建猎豹、小女孩动画实例
let leopardAni = new Laya.Animation();
let girlAni = new Laya.Animation();
//设置精灵的位置
leopardAni.pos(100,50);
girlAni.pos(300,60);
//加载动画图集,加载成功后执行回调方法 ———— 使用 Laya.loader.load 或者 Animation 的 loadAtlas 方法都可以
//Handler 是事件处理器类,create 从对象池内创建一个Handler,默认会执行一次并立即回收
//制作好的图集文件 .atlas、.png 放入到 bin/res/atlas 目录下
Laya.loader.load("res/atlas/leo_girl.atlas",Laya.Handler.create(this,onLoaded));
function onLoaded(){
//添加到舞台
Laya.stage.addChild(leopardAni);
//设置播放间隔,单位毫秒,默认为 50。意思就是播放图集中的序列帧图像的间隔时间
leopardAni.interval = 100;
//获取图集中指定的动画序列帧
let leoArr = createAniUrls("leo_girl/Leopard",8);
//根据指定的动画模版初始化当前动画序列帧,这里没指定第二个参数时,表示不缓存动画模板
leopardAni.loadImages(leoArr);
//播放动画,第三个参数不为空时,则从动画模版缓存池中寻找key值为name的动画模版序列帧进行播放,当不存在 ani_leoArr 时,则仍然播放当前序列帧 leopardAni
leopardAni.play();
}
//加载动画图集,加载成功后执行回调方法 ———— 使用 Laya.loader.load 或者 Animation 的 loadAtlas 方法都可
girlAni.loadAtlas("res/atlas/girs.atlas",Laya.Handler.create(this,girlOnLoad));
function girlOnLoad(){
Laya.stage.addChild(girlAni);
girlAni.interval = 80;
let girlArr = createAniUrls("leo_girl/girl_0",6);
//根据指定的动画模版初始化当前动画序列帧,这里指定第二个参数时,表示缓存动画模板
girlAni.loadImages(girlArr,"ani_girl");
//播放动画,第三个参数不为空时,表示从动画模版缓存池中寻找key值为name的动画模版序列帧进行播放,当不存在时,则仍然播放当前序列帧
girlAni.play(0,true,"ani_girl");
}
//根据路径与长度值生成一个 url 数组
//约定图集后缀名为 .png ,图集中的图片序号从 1 开始
//url:如 leo_girl/girl_0 后面的的部分 x.png 会自动补全
//length:表示创建的个数
function createAniUrls(url,length){
let urls = [];
for(let i=0;i<length;i++){
urls.push(url+(i+1)+".png");
}
console.log(urls);
return urls;
}
3、当被多次使用的时候,使用动画模板可以节省CPU的开销,但是,如果只是偶尔或一次使用,那就不要使用动画模板,因为节省CPU开销是以牺牲一定的内存开销为代价。
动画播放基类:
https://layaair.ldc.layabox.com/api/?category=Core&class=laya.display.AnimationPlayerBase
动画类:
https://layaair.ldc.layabox.com/api/?category=Core&class=laya.display.Animation