Android Flutter实现精灵图的使用详解

目录
  • 前言
  • 如何使用精灵图
    • 自定义实现加载
    • Flame加载精灵图

前言

在日常开发中遇到的图片展示一般是静态图和Gif图两种形式(静态和动态的不同)。与此同时当需要对图片做效果时让其动起来,常用方案是Gif图播放或者是帧动画(多种静态图轮询播放)。但在游戏开发中还有一种动图表现形式叫做Sprite图(雪碧图),其在前端开发中也是很常见。为什么需要使用精灵图,因为每张图片显示都需要去发起请求获取,若页面图片数量较多(一个页面有几十个小图)并发请求将是一个大数量级,可能会造成页面加载速度降低,精灵图其中一个特点就是减少服务器请求,一次性加载到所有图片。

如何使用精灵图

在游戏开发中精灵图会将一个人物所有动作放置在一张图片中,通过坐标定位选取其中一张图展示。根据精灵图配置信息来定位到不同图片再通过定时切换选取不同图片从而实现连贯动画效果。

自定义实现加载

自定义实习方式是对精灵图进行加载,因为每帧图片尺寸大小是一致的。

  • 每帧图片尺寸固定后就能确认每一帧图片在整张图片的定位位置,因此能够根据X-Y坐标来找到相应图片。
  • 创建定时器调整间隔时间计算出坐标位置切换需要展示图片。
  • 再结合Container+Positioned形式来实现采用偏移量方式显示哪张图片。
class SpriteWidget extends StatefulWidget {
  final Image image;
  final Size spriteSize;

  final Duration duration;

  SpriteWidget({
    Key key,
    @required this.image,
    @required this.spriteSize,
    @required this.duration,
  }) : super(key: key);

  @override
  _SpriteWidgetState createState() => _SpriteWidgetState();
}

class _SpriteWidgetState extends State<SpriteWidget> {
  Image get image => widget.image;

  Size get spriteSize => widget.spriteSize;

  Duration get duration => widget.duration;
  // 当前显示的图片位置
  int currentIndex = 0;
  int currentTimes = 0;

  int startIndex = 0;

  int endIndex = 1;
  int playTimes = 0;

  // 定时器用来更新精灵图加载
  Timer timer;

  @override
  void initState() {
    currentIndex = startIndex;
    timer = Timer.periodic(duration, (timer) {
      if (currentTimes <= playTimes) {
        setState(() {
          if (currentIndex >= endIndex) {
            if (playTimes != 0) currentTimes++;
            if (currentTimes < playTimes || playTimes == 0)
              currentIndex = startIndex;
            else
              currentIndex = endIndex;
          } else
            currentIndex++;
        });
      }
    });
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
    timer?.cancel();
  }

  @override
  Widget build(BuildContext context) {
    // 使用container+Positioned来限制图片显示区域
    return Container(
      width: spriteSize.width,
      height: spriteSize.height,
      child: Stack(
        children: [
          Positioned(
              left: -spriteSize.width * currentIndex,
              top: -spriteSize.height * currentIndex,
              child: image)
        ],
      ),
    );
  }
}

Flame加载精灵图

除了自定义方式实现精灵图加载外,Flutter官方还提供了Flame框架实现游戏内容制作帮助开发者更方便实现游戏相关功能开发。

首先在依赖库添加Flame库,此外bonfireFlame库的拓展封装了更多游戏开发相关功能接口。

  bonfire: ^2.0.0
  flame: ^1.0.0

实现角色资源加载类,bonfire中已经帮助开发者实现了Sprite功能只需要加载精灵图就能获取到精灵图加载能力。

abstract class BaseRole {
  // 速度
  double velocity;
  late Sprite sprite;

  BaseRole({
    this.velocity = 10,
  });

  dynamic load();

  void run();
}
class UserRole extends BaseRole {
  Vector2 offset = Vector2(0.0, 0.0);
  Vector2 size = Vector2(48.0, 48.0);

  @override
  void run() {
    double x = (48 + offset.x) % 192;
    double y = 0;
    offset = Vector2(x, y);
    sprite.srcPosition = offset;
    sprite.srcSize = size;
  }

  @override
  Future load() async {
    sprite = await Sprite.load(
      'user_role.png',
      srcPosition: offset,
      srcSize: size,
    );
    return sprite;
  }
}

bonfire游戏开发中还有SpriteComponent组件,开发者只需要继承它加载使用Sprite即可。

class UserRoleComponent extends SpriteComponent {
  late UserRole userRole;

  UserRoleComponent()
      : super(
          size: Vector2.all(100),
        );

  double minDt = 1 / 8; // 30 fps
  double dtOverflow = 0;

  @override
  Future<void>? onLoad() async {
    userRole = UserRole();
    sprite = await userRole.load();
    super.onLoad();
  }

  @override
  void update(double dt) {
    dtOverflow += dt;
    if (dtOverflow < minDt) {
      return;
    }
    userRole.run();
    dtOverflow = 0;
  }
}

到此这篇关于Android Flutter实现精灵图的使用详解的文章就介绍到这了,更多相关Android Flutter精灵图内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android精灵动画用法实例

    本文实例讲述了Android精灵动画用法.分享给大家供大家参考.具体如下: ElaineAnimated.java文件如下: package net.obviam.walking.model; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; public class ElaineAnimated

  • Android Flutter实现精灵图的使用详解

    目录 前言 如何使用精灵图 自定义实现加载 Flame加载精灵图 前言 在日常开发中遇到的图片展示一般是静态图和Gif图两种形式(静态和动态的不同).与此同时当需要对图片做效果时让其动起来,常用方案是Gif图播放或者是帧动画(多种静态图轮询播放).但在游戏开发中还有一种动图表现形式叫做Sprite图(雪碧图),其在前端开发中也是很常见.为什么需要使用精灵图,因为每张图片显示都需要去发起请求获取,若页面图片数量较多(一个页面有几十个小图)并发请求将是一个大数量级,可能会造成页面加载速度降低,精灵图

  • Android Flutter实现3D动画效果示例详解

    目录 前言 AnimatedWidget 简介 3D 旋转动画的实现 总结 前言 上一篇我们介绍了 Animation 和 AnimationController 的使用,这是最基本的动画构建类.但是,如果我们想构建一个可复用的动画组件,通过外部参数来控制其动画效果的时候,上一篇的方法就不太合适了.在 Flutter 中提供了 AnimatedWidget 组件用于构建可复用的动画组件.本篇我们用 AnimatedWidget 来实现组件的3D 旋转效果,如下图所示. AnimatedWidge

  • Android Flutter表格组件Table的使用详解

    目录 Table.TabRow.TabCell 小结 之前开发中用到的表格,本篇文章主要介绍如何在页面中使用表格做一个记录. Table组件不同于其它Flex布局,它是直接继承的RenderObjectWidget的.相当于是一个独立的组件,区别与其他系列组件. Table.TabRow.TabCell 惯例,先看下Table相关的构造方法: Table({ Key? key, this.children = const <TableRow>[],//行列表 表示多少行 this.column

  • Android Flutter利用CustomPaint绘制基本图形详解

    目录 绘制矩形 绘制圆形 绘制椭圆 绘制任意形状 绘制弧形 总结 上一篇我们介绍了 CustomPaint 的基本概念和使用,可以看到 CustomPaint 其实和 前端的 Canvas基本上是一样的,实际上前端 Canvas 支持的绘制方法 CustomPaint 都支持,毕竟 CustomPaint 其实也是基于 Canvas 实现的.本篇我们来介绍 CustomPaint 基本图形的绘制. 绘制矩形 绘制矩形比较简单,方法定义如下: void drawRect(Rect rect, Pa

  • Android Flutter绘制扇形图详解

    目录 简介 CustomPaint介绍 CustomPainter介绍 paint介绍 shouldRepaint介绍 示例 使用CustomPaint 自定义Painter 绘制 触摸事件处理 动画实现 简介 在开发过程中通常会遇到一些不规则的UI,比如不规则的线条,多边形,统计图表等等,用那些通用组件通过组合的方式无法进行实现,这就需要我们自己进行绘制.可以通过使用CuntomPaint组件并结合画笔CustomPainter去进行手动绘制各种图形. CustomPaint介绍 Custom

  • Android 自定义imageview实现图片缩放实例详解

    Android 自定义imageview实现图片缩放实例详解 觉得这个自定义的imageview很好用 性能不错  所以拿出来分享给大家  因为不会做gif图  所以项目效果 就不好贴出来了  把代码贴出来 1.项目结构图 2.Compat.class package com.suo.image; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.view.View; pu

  • Android 带logo的二维码详解及实例

    Android 带logo的二维码详解及实例 好久没有写博客了,快元旦了公司的事情也不是很多,刚好和朋友一起出去玩玩,朋友是搞PHP的说到了每天在公司都是搞些什么二维码和微信支付的相关东西,因为上班的时间不忙,所以随便来搞下. 二维码(Quick Response Code),又称二维条码,它是用特定的几何图形按一定规律在平面(二维方向)上分布的黑白相间的图形,是所有信息数据的一把钥匙.在现代商业活动中,如果一个产品是不能通过二维码来进行访问什么的,显然是不成功的.用的比较多的生成二维码的jar

  • Android Studio 修改应用包名实例详解

    Android Studio 修改应用包名实例详解 我们平时新建项目有些朋友可能当时就是随意写的一个包名,然后在项目过程中, 又感觉这个包名不太好,所以就要对包名进行修改,根据我们正常的修改方式,是这样的. 在种情况是只能修改最外层的那个名称, 如果我们现在是需要修改中间的某一个,这里就行不通了. 那么我们来看一下如何修改成你最终要的包名. 操作图如下: 看到没有,我们只需要在setting里面,把 compact empty middle packages 这个选项去掉,这样,我们的包的层次结

  • Android OkHttp的简单使用和封装详解

    Android OkHttp的简单使用和封装详解 1,昨天把okHttp仔细的看了一下,以前都是调用同事封装好了的网络框架,直接使用很容易,但自己封装却不是那么简单,还好,今天就来自我救赎一把,就和大家写写从最基础的OKHttp的简单get.post的使用,再到它的封装. 2,OkHttp的简单使用 首先我们创建一个工程,并在布局文件中添加三个控件,TextView(用于展示获取到json后的信息).Button(点击开始请求网络).ProgressBar(网络加载提示框) ①简单的异步Get请

  • Android几种多渠道打包的步骤详解

    1.什么是多渠道打包 在不同的应用市场可能有不同的统计需求,需要为每个应用市场发布一个安装包,这里就引出了Android的多渠道打包.在安装包中添加不同的标识,以此区分各个渠道,方便统计app在市场的各种. 2.几种打包方式 友盟 UMeng Android Studio自带 美团 Walle 3.开始使用 3.1 友盟UMeng 第一步:在AndroidManifest中添加 <meta-data android:name="UMENG_CHANNEL" android:val

随机推荐