动画精灵DFSpriteAnimation,在游戏里动画精灵是用的最多的了,因为游戏里很多物件都是动态的,在2d游戏里动态的图像我们用序列帧实现。
Texturepacker是游戏开发中常用的开发工具,可以将零散的序列帧图片组合成一张整图,并用plist或者json记录每个序列帧小图的位置和尺寸。
动画精灵内有加载Texturepacker游戏资源的函数,如果你的数据格式和我使用的不一样可以参照源码进行修改实现。
下面我们看下这个解析是如何实现的:
首先我定义了一个Map,用于存放全部的动画帧,并且map的key是这个动画的名称:
/// 这个动画的全部帧
Map<String, List<DFImageSprite>> frames = HashMap<String, List<DFImageSprite>>();
下面是解析代码:
/// 将plist转换Json后读取精灵
/// {
/// "frames": {
/// "idle_00000.png":
/// {
/// "frame": "{{929,291},{76,110}}",
/// "offset": "{-19,24}",
/// "rotated": true
/// }
/// }
/// }
static Future load(String src, String plist) async {
DFSpriteAnimation spriteAnimation = DFSpriteAnimation(stepTime: 100, loop: true);
DFAnimation.sequence.forEach((element) {
spriteAnimation.frames[element] = [];
});
ui.Image image = await DFAssetsLoader.loadImage(src);
Map jsonMap = await DFAssetsLoader.loadJson(plist);
final jsonFrames = jsonMap['frames'] as Map;
jsonFrames.forEach((key, value) {
final map = value as Map;
bool rotated = false;
if (map['rotated'] != null) {
rotated = map['rotated'] as bool;
}
final frame = map['frame'] as String;
final offset = map['offset'] as String;
List frameText = frame.replaceAll("{{", "").replaceAll("},{", ",").replaceAll("}}", "").split(",");
List offsetText = offset.replaceAll("{", "").replaceAll("}", "").split(",");
DFRect frameRect = DFRect(double.parse(frameText[0]), double.parse(frameText[1]), double.parse(frameText[2]),
double.parse(frameText[3]));
DFOffset frameOffset = DFOffset(double.parse(offsetText[0]), double.parse(offsetText[1]));
/// 如果是旋转的参数也修改一下
if (rotated) {
frameRect = DFRect(double.parse(frameText[0]), double.parse(frameText[1]), double.parse(frameText[3]),
double.parse(frameText[2]));
frameOffset = DFOffset(double.parse(offsetText[1]), double.parse(offsetText[0]));
}
//print("frameSize:" + frameRect.toString());
//print("frameOffset:" + frameOffset.toString());
DFImageSprite sprite = DFImageSprite(
image,
offset: frameOffset,
rect: frameRect,
rotated: rotated,
scale: 0.6,
);
//idle_00000.png
String actionText = "idle_";
String action = DFAnimation.IDLE;
if (key.contains("idle_")) {
actionText = "idle_";
action = DFAnimation.IDLE;
} else if (key.contains("run_")) {
actionText = "run_";
action = DFAnimation.RUN;
} else if (key.contains("attack_")) {
actionText = "attack_";
action = DFAnimation.ATTACK;
} else if (key.contains("casting_")) {
actionText = "casting_";
action = DFAnimation.CASTING;
} else if (key.contains("dig_")) {
actionText = "dig_";
action = DFAnimation.DIG;
}
String keyNumber = key.replaceAll(actionText, "").replaceAll(".png", "");
if (keyNumber.startsWith("000")) {
spriteAnimation.frames[action + DFAnimation.UP]?.add(sprite);
}
if (keyNumber.startsWith("100")) {
spriteAnimation.frames[action + DFAnimation.UP_RIGHT]?.add(sprite);
spriteAnimation.frames[action + DFAnimation.UP_LEFT]?.add(sprite);
}
if (keyNumber.startsWith("200")) {
spriteAnimation.frames[action + DFAnimation.RIGHT]?.add(sprite);
spriteAnimation.frames[action + DFAnimation.LEFT]?.add(sprite);
}
if (keyNumber.startsWith("300")) {
spriteAnimation.frames[action + DFAnimation.DOWN_RIGHT]?.add(sprite);
spriteAnimation.frames[action + DFAnimation.DOWN_LEFT]?.add(sprite);
}
if (keyNumber.startsWith("400")) {
spriteAnimation.frames[action + DFAnimation.DOWN]?.add(sprite);
}
});
return spriteAnimation;
}
通过上面的解析数据的方法,我们将动画数据都整理好了,这是游戏中如果需要控制某个时刻显示哪个动画,就比较简单了,可以通过动画的名称进行播放了。
控制动画开始播放,代码如下:
///自动播放玩家第一个动画
this.play(action: DFAnimation.IDLE, direction: DFAnimation.DOWN);
本站内容来源于作者发布和网络转载,如有版权相关问题请及时与我们取得联系,我们将立即删除。