唯杰地图 logo唯杰地图
VJMAP
EN

精灵动画实体

vjmap3d/references/entity/spriteAnimatorEntity.md 7.4 KB199 行
原文

SpriteAnimatorEntity 是由 实体Entity 和 SpriteAnimatorModule 模块组合而成的新的实体。

SpriteAnimatorEntity = Entity + SpriteAnimatorModule

常用方法

SpriteAnimatorEntity 是由 实体Entity 派生而来。具体 Entity 的所有属性和方法。同时也具有SpriteAnimatorModule 的相关方法。通过 spriteAnimator 对象 可访问相关方法

方法 描述
spriteAnimator 获取精灵动画对象
pauseAnimation 暂停动画
playAnimation 运行动画
setFrameName 设置动画帧名称(切换动画)。⚠️ 仅对 JSON Hash 格式有效;资源加载完成前调用是空操作

支持格式

动画格式支持动画图像集(将所有动画图像放至一张图片上) 和 精灵图(Sprite Sheet)格式(它描述了一个包含多帧图像的动画序列,每帧图像在一个较大的图像中的位置和大小。这种格式广泛用于2D游戏开发和其他图形应用中)。

各格式的必填项:

  • 动画图像集(只给 textureImageURL):必须传 numberOfFrames,且所有帧须横向排成一行、图片宽度能被帧数整除,否则帧列表为空、不播放。
  • JSON Array(frames 是数组,如 TexturePacker 的 "JSON (Array)"):按数组顺序整体播放,无需 animationNames,frameName/setFrameName 无作用。
  • JSON Hash(frames 是以帧名为 key 的对象):必须传 animationNames(按"帧名包含该字符串"分组成多段动画),并用 frameName 指定初始播放哪一段;缺 animationNames 时加载阶段抛错、实体始终不显示。

精灵图(Sprite Sheet)格式创建工具 texturepacker

使用示例

创建SpriteAnimatorEntity

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true,  } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let spriteAnimatorEnt = new vjmap3d.SpriteAnimatorEntity({
    startFrame: 0,
    autoPlay: true,
    loop: true,
    numberOfFrames: 16,
    textureImageURL: env.assetsPath + "sprites/alien.png",
    asSprite: true
  })
spriteAnimatorEnt.position.set(-2, 0, 2);
spriteAnimatorEnt.addTo(app);

加载精灵图(Sprite Sheet)格式动画

let spriteAnimatorEnt = new vjmap3d.SpriteAnimatorEntity({
    startFrame: 0,
    fps: 40,
    autoPlay: true,
    loop: true,
    textureImageURL:  env.assetsPath + "sprites/flame.png",
    textureDataURL:  env.assetsPath + "sprites/flame.json",
    asSprite:  true
 })
spriteAnimatorEnt.position.set(2, 0, 2);
spriteAnimatorEnt.addTo(app);

动画控制

pauseAnimation 暂停动画

playAnimation 运行动画

setFrameName 设置动画帧名称——只对 JSON Hash 格式(构造时传了 animationNames)有效;对上面的图像集/JSON Array 实体调用无效果。在资源加载完成(模块 isLoaded)之前调用会被直接忽略,应在加载完成后(如用户点击时)再调用。

// JSON Hash 格式:帧名里含 'idle' / 'celebration' 的帧各成一段动画
const animNames = ['idle', 'celebration'];
let boyEnt = new vjmap3d.SpriteAnimatorEntity({
    frameName: 'idle',          // 初始播放的动画段
    animationNames: animNames,  // JSON Hash 必填
    fps: 24,
    autoPlay: true,
    loop: true,
    textureImageURL: env.assetsPath + "sprites/boy_hash.png",
    textureDataURL: env.assetsPath + "sprites/boy_hash.json",
    asSprite: true
});
boyEnt.addTo(app);
// 须在加载完成后调用(构造后立即调用会被忽略),例如放在按钮回调里切换动画段
const switchAnim = () => boyEnt.setFrameName('celebration');

事件交互

spriteAnimatorEnt.add(vjmap3d.EventModule, {
    hoverSelect: true,
    clickCallback: (ent, isClick) => {
        if (!isClick) return
        app.logInfo("您点击我了")
    }
});

示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    stat: { show: true, left: "0" },
    scene: {
        gridHelper: { visible: true,  } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let spriteAnimatorEnt = new vjmap3d.SpriteAnimatorEntity({
    startFrame: 0,
    autoPlay: true,
    loop: true,
    numberOfFrames: 16,
    textureImageURL: env.assetsPath + "sprites/alien.png",
    asSprite: true
  })
spriteAnimatorEnt.position.set(-2, 0, 2);
spriteAnimatorEnt.addTo(app);
spriteAnimatorEnt.add(vjmap3d.EventModule, {
    hoverSelect: true,
    clickCallback: (ent, isClick) => {
        if (!isClick) return
        app.logInfo("您点击我了")
    }
});
// fire
let entFire = new vjmap3d.SpriteAnimatorEntity({
    startFrame: 0,
    fps: 40,
    autoPlay: true,
    loop: true,
    textureImageURL:  env.assetsPath + "sprites/flame.png",
    textureDataURL:  env.assetsPath + "sprites/flame.json",
    asSprite:  true
 })
entFire.position.set(0, 0, -5);
entFire.addTo(app);
//
const animNames = ['idle', 'celebration']
let entBoy = new vjmap3d.SpriteAnimatorEntity({
    frameName: 'idle',
    fps: 24,
    animationNames: animNames,
    autoPlay: true,
    loop: true,
    textureImageURL: env.assetsPath + "sprites/boy_hash.png",
    textureDataURL: env.assetsPath + "sprites/boy_hash.json",
    asSprite: true,
})
entBoy.position.set(2, 0, 2);
entBoy.scale.set(3, 3, 3)
entBoy.addTo(app)
//
let aniIndex = 0;
const ui = await app.getConfigPane({ title: "设置", style: { width: "250px", overflow: "hidden"}});
let cfg = [
    {
        type: 'button',
        label: '切换动画',
        value: ()=> {
            let name = animNames[++aniIndex % 2];
            entBoy.setFrameName(name)
        }
    },
    {
        type: 'button',
        label: '停止动画',
        value: ()=> {
            entBoy.pauseAnimation()
        }
    },
    {
        type: 'button',
        label: '开始动画',
        value: ()=> {
            entBoy.playAnimation()
        }
    },
]
cfg.forEach(c => ui.appendChild(c));