动画精灵

动画精灵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);




本站内容来源于作者发布和网络转载,如有版权相关问题请及时与我们取得联系,我们将立即删除。

 关于作者
 热门教程
快速开始
这是一款精美的Flutter游戏引擎,轻松在Google的Flutter框架上开发游戏。 A Flutter 2D R
2024-08-05
剑道仙尊
82
游戏功能
游戏的功能开发: 坐标系 资源加载 碰撞检测 A* 寻路算法
2022-08-19
剑道仙尊
42
游戏控件
游戏中的一些常用控件: 摇杆 按钮
2022-08-19
剑道仙尊
45
渲染精灵
游戏中不可缺少的精灵,包括: 文本精灵 图像精灵 动画精灵 进度精灵 瓦片精灵
2022-08-19
剑道仙尊
46
核心框架
引擎中的结构比较简单,编写程序时首先创建场景,场景也是一个Widget,然后往场景中增加子Widget,可以添加2中类
2022-07-11
剑道仙尊
112
摇杆
DFJoyStick是完全用Flutter实现的Widget,默认是8方向的,可以设置背景图片和一些基本样式。 ///
2022-06-07
剑道仙尊
130
精灵
组成游戏世界里的元素我们称之为精灵。 引擎里为了方便开发,内置了一些常用的基础精灵,如文本精灵,图像精灵,动画精灵等。
2022-06-07
剑道仙尊
83
界面
我们把游戏的界面分成2个类型,一种是游戏里面的主角,怪物,建筑物这一类,我们称为精灵,另外一类是页面显示的按钮,弹出框
2022-06-07
剑道仙尊
38
基本概念
1、场景 一般我们把打开一个界面也叫做进入了一个场景,一般游戏里的场景有登录场景,游戏主界面场景,地图的切换我们也称作
2022-06-07
剑道仙尊
242
资源加载
通过DFAssetsLoader类进行资源的加载,支持加载图片和文本资源。首次加载后引擎会自动缓存该资源以提高效率。
2022-06-07
剑道仙尊
47