Flutter精灵图处理插件spritexp的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter精灵图处理插件spritexp的使用

安装 💻

要开始使用SpritExp,您必须在您的机器上安装Flutter SDK。

pubspec.yaml文件中添加spritexp依赖:

dependencies:
  spritexp:

然后运行以下命令来安装它:

flutter packages get

使用它

SpritExp的基本语法结构如下所示:

{SPRITE COORDINATES AND SIZE}[ * MULTIPLIERS]

分解来看,精灵的坐标和大小由逗号分隔的数字表示,并接受几种格式:

// {Size} - 坐标默认为0,0
{16}
// {X 和 Y, 宽度和高度}
{16, 32}
// {X, Y, 宽度, 高度}
{0, 16, 32, 32}

乘数用于根据上述定义生成一系列精灵。例如,为了生成一个包含两个精灵的水平列表,可以使用以下示例:

{0, 16} * 2x

这将生成两个精灵,第一个从X0 Y0开始,尺寸为正方形16,第二个从X16 Y0开始,同样也是正方形16。

另一方面,下面的示例:

{0, 16} * 2y

将生成两个精灵,第一个从X0 Y0开始,尺寸为正方形16,第二个从X0 Y16开始,同样也是正方形16。

您还可以通过在表达式中添加xy来获取精灵网格:

{0, 16} * 2xy

默认情况下,SpritExp假定乘数是水平的,因此可以省略x,即{0, 16} * 2{0, 16} * 2x是相同的表达式。


示例代码

以下是完整的示例代码,展示了如何使用SpritExp插件来处理精灵图。

// ignore_for_file: public_member_api_docs

import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:file_selector/file_selector.dart';
import 'package:flame/flame.dart';
import 'package:flame/widgets.dart';
import 'package:flutter/material.dart';
import 'package:nes_ui/nes_ui.dart';
import 'package:spritexp/spritexp.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: flutterNesTheme(),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late final _expressionController = TextEditingController();

  bool _onError = false;
  ui.Image? _image;
  late Uint8List? _imageBytes;
  List<Sprite> _sprites = [];

  [@override](/user/override)
  void dispose() {
    _expressionController.dispose();
    super.dispose();
  }

  void _onChangeExpression() {
    if (_expressionController.text.isEmpty) {
      setState(() {
        _sprites = [];
      });
      return;
    }

    final expression = _expressionController.text;

    try {
      final spriteExp = SpritExp(expression: expression);

      setState(() {
        _onError = false;
      });

      if (_image == null) return;

      final sprites = spriteExp / _image!;
      setState(() {
        _sprites = sprites;
      });
    } catch (_) {
      setState(() {
        _onError = true;
      });
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            NesContainer(
              label: 'Expression',
              child: TextFormField(
                controller: _expressionController,
                onChanged: (_) => _onChangeExpression(),
                decoration: InputDecoration(
                  errorText: _onError ? '无效表达式' : null,
                ),
              ),
            ),
            const SizedBox(height: 16),
            if (_image == null)
              Expanded(
                child: NesContainer(
                  label: '未选择图像',
                  width: double.infinity,
                  child: Center(
                    child: NesButton(
                      type: NesButtonType.primary,
                      child: const Text('选择图像'),
                      onPressed: () async {
                        const typeGroup = XTypeGroup(
                          label: 'images',
                          extensions: ['jpg', 'png'],
                        );
                        final file = await openFile(
                          acceptedTypeGroups: [typeGroup],
                        );

                        if (file == null) return;

                        final bytes = await file.readAsBytes();
                        final image = await Flame.images.fetchOrGenerate(
                          file.path,
                          () => decodeImageFromList(bytes),
                        );

                        setState(() {
                          _image = image;
                          _imageBytes = bytes;
                        });

                        _onChangeExpression();
                      },
                    ),
                  ),
                ),
              )
            else
              Expanded(
                child: NesContainer(
                  width: double.infinity,
                  child: Padding(
                    padding: const EdgeInsets.all(16),
                    child: Row(
                      children: [
                        Expanded(
                          child: NesContainer(
                            label: '原始图像',
                            child: Image.memory(
                              _imageBytes!,
                              fit: BoxFit.contain,
                              filterQuality: FilterQuality.none,
                            ),
                          ),
                        ),
                        const SizedBox(width: 16),
                        Expanded(
                          child: NesContainer(
                            label: '精灵',
                            height: double.infinity,
                            child: Wrap(
                              children: [
                                for (final sprite in _sprites)
                                  Padding(
                                    padding: const EdgeInsets.all(8),
                                    child: SpriteWidget(sprite: sprite),
                                  ),
                              ],
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter精灵图处理插件spritexp的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter精灵图处理插件spritexp的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用spritex插件来处理精灵图(Sprite Sheets)的示例代码。spritex是一个用于生成和处理精灵图的Flutter插件,可以帮助你更有效地管理游戏中的图像资源。

首先,你需要确保在pubspec.yaml文件中添加了spritex依赖:

dependencies:
  flutter:
    sdk: flutter
  spritex: ^最新版本号  # 请替换为实际可用的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,假设你已经有一个精灵图文件(例如spritesheet.png)和一个JSON文件(例如spritesheet.json),这些文件描述了精灵图中各个图像的位置和尺寸。

以下是一个完整的Flutter应用示例,展示如何使用spritex插件加载和显示精灵图中的图像:

import 'package:flutter/material.dart';
import 'package:spritex/spritex.dart';
import 'dart:typed_data';
import 'dart:convert';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SpriteSheetDemo(),
    );
  }
}

class SpriteSheetDemo extends StatefulWidget {
  @override
  _SpriteSheetDemoState createState() => _SpriteSheetDemoState();
}

class _SpriteSheetDemoState extends State<SpriteSheetDemo> {
  late SpriteSheet spriteSheet;

  @override
  void initState() {
    super.initState();
    // 加载精灵图文件
    rootBundle.loadString('assets/spritesheet.json').then((jsonString) {
      final jsonData = jsonDecode(jsonString) as Map<String, dynamic>;
      
      // 加载精灵图图像
      rootBundle.load('assets/spritesheet.png').then((imageData) {
        Uint8List imageBytes = imageData.buffer.asUint8List();
        
        // 创建SpriteSheet实例
        spriteSheet = SpriteSheet(imageBytes, jsonData);
        
        // 通知UI更新
        setState(() {});
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SpriteSheet Demo'),
      ),
      body: Center(
        child: spriteSheet.frames.isNotEmpty
            ? Image.memory(
                spriteSheet.getFrame('frame_name').data, // 替换为实际的帧名称
                width: spriteSheet.getFrame('frame_name').width.toDouble(),
                height: spriteSheet.getFrame('frame_name').height.toDouble(),
                fit: BoxFit.cover,
              )
            : CircularProgressIndicator(), // 在加载完成前显示加载指示器
      ),
    );
  }
}

说明:

  1. 加载JSON文件

    • 使用rootBundle.loadString加载描述精灵图的JSON文件。
    • 解析JSON数据为Map<String, dynamic>类型。
  2. 加载精灵图图像

    • 使用rootBundle.load加载精灵图PNG文件。
    • 将加载的字节数据转换为Uint8List
  3. 创建SpriteSheet实例

    • 使用图像字节数据和JSON数据创建SpriteSheet实例。
  4. 获取并显示帧

    • 使用spriteSheet.getFrame('frame_name')获取特定帧的数据。
    • 使用Image.memory将帧数据显示为图像。
  5. UI更新

    • 使用setState方法在加载完成后更新UI。

请确保将spritesheet.pngspritesheet.json文件添加到你的Flutter项目的assets目录中,并在pubspec.yaml中声明它们:

flutter:
  assets:
    - assets/spritesheet.png
    - assets/spritesheet.json

以上代码展示了如何在Flutter中使用spritex插件处理精灵图,并显示精灵图中的某一帧。希望这个示例对你有帮助!

回到顶部