Flutter Spine动画渲染插件spine_core的使用

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

Flutter Spine动画渲染插件spine_core的使用

spine_core 运行时提供了使用 Dart 加载和操作 Spine 骨骼动画数据的功能。它不执行渲染,但可以扩展以使其他基于 Dart 的项目支持 Spine 动画。

Spine License

此 Spine 运行时仅可用于个人或内部使用,通常用于在购买前评估 Spine。如果您希望将 Spine 运行时集成到您的应用程序中,分发包含 Spine 运行时的软件,或修改 Spine 运行时,则需要有效的 Spine 许可证。请参阅《Spine Runtimes 软件许可》以获取详细信息。

Spine 运行时旨在与从 Spine 导出的数据一起使用。通过购买 Spine,第 2 节 的《Spine 软件许可》授予创建和分发 Spine 运行时衍生作品的权利。


如何使用 spine_core 插件

以下是一个完整的示例,展示如何在 Flutter 中使用 spine_core 插件来加载和播放 Spine 动画。

首先,确保你已经在 pubspec.yaml 文件中添加了 spine_core 依赖:

dependencies:
  flutter:
    sdk: flutter
  spine_core: ^0.1.0

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

接下来,我们将创建一个简单的 Flutter 应用程序,该应用程序加载并播放 Spine 动画。

示例代码

import 'package:flutter/material.dart';
import 'package:spine_core/spine_core.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Spine Animation Example'),
        ),
        body: Center(
          child: SpineAnimationWidget(),
        ),
      ),
    );
  }
}

class SpineAnimationWidget extends StatefulWidget {
  [@override](/user/override)
  _SpineAnimationWidgetState createState() => _SpineAnimationWidgetState();
}

class _SpineAnimationWidgetState extends State<SpineAnimationWidget> {
  SkeletonData _skeletonData;
  Skeleton _skeleton;
  TrackEntry _trackEntry;

  [@override](/user/override)
  void initState() {
    super.initState();
    // 加载 Spine 数据文件
    loadSkeletonData();
  }

  Future<void> loadSkeletonData() async {
    final bytes = await rootBundle.load('assets/skeleton.json');
    final skeletonData = SkeletonJson(AtlasRegionLoader(bytes.buffer.asByteData()));
    final atlas = await loadAtlas('assets/atlas.atlas');
    _skeletonData = skeletonData.readSkeletonData(atlas);
    setState(() {
      _skeleton = Skeleton(_skeletonData);
      _skeleton.updateWorldTransform();
      _trackEntry = _skeleton.data.findAnimation('walk').createTrackEntry(_skeleton);
      _trackEntry.setLoop(true);
      _skeleton.setSkinByName('default');
      _skeleton.setSlotsToSetupPose();
      _skeleton.updateWorldTransform();
      _skeleton.setAnimation(0, _trackEntry);
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      width: 300,
      height: 300,
      child: CustomPaint(
        painter: SpinePainter(_skeleton),
      ),
    );
  }
}

class SpinePainter extends CustomPainter {
  final Skeleton _skeleton;

  SpinePainter(this._skeleton);

  [@override](/user/override)
  void paint(Canvas canvas, Size size) {
    final batch = Batch();
    final renderer = SkeletonRenderer(batch);
    renderer.draw(canvas, _skeleton);
  }

  [@override](/user/override)
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

更多关于Flutter Spine动画渲染插件spine_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Spine动画渲染插件spine_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用spine_core插件来渲染Spine动画的示例代码。spine_core插件允许你在Flutter应用中加载和渲染Spine动画。

步骤1:添加依赖

首先,你需要在你的pubspec.yaml文件中添加spine_core依赖:

dependencies:
  flutter:
    sdk: flutter
  spine_core: ^最新版本号  # 请确保使用最新版本

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

步骤2:导入必要的包

在你的Dart文件中,导入spine_core包:

import 'package:spine_core/spine_core.dart';

步骤3:加载和渲染Spine动画

以下是一个完整的示例,演示如何在Flutter中加载和渲染Spine动画:

import 'package:flutter/material.dart';
import 'package:spine_core/spine_core.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Spine Animation Example'),
        ),
        body: Center(
          child: SpineAnimationWidget(),
        ),
      ),
    );
  }
}

class SpineAnimationWidget extends StatefulWidget {
  @override
  _SpineAnimationWidgetState createState() => _SpineAnimationWidgetState();
}

class _SpineAnimationWidgetState extends State<SpineAnimationWidget> with SingleTickerProviderStateMixin {
  late SpineRuntime runtime;
  late SpineAnimationState animationState;
  late SpineSkeleton skeleton;

  @override
  void initState() {
    super.initState();

    // 加载Spine动画资源(这里假设你的.atlas和.json文件已经放在assets目录下)
    loadSpineAnimation();

    // 启动动画更新
    _startAnimation();
  }

  void loadSpineAnimation() async {
    // 加载Atlas和Skeleton JSON文件
    final atlasTexture = await AtlasTexture.load('assets/your_spine_atlas.atlas');
    final skeletonJson = await SkeletonJson.load('assets/your_spine_skeleton.json');

    // 创建SpineRuntime实例
    runtime = SpineRuntime(atlasTexture);

    // 解析Skeleton JSON并创建Skeleton对象
    skeleton = SkeletonJson.readSkeletonData(runtime, skeletonJson)!.createSkeleton(atlasTexture);

    // 创建动画状态
    animationState = AnimationState(skeleton.data);
    animationState.setAnimation(0, 'animation_name', true); // 替换'animation_name'为你的动画名称

    // 将Skeleton和AnimationState设置给runtime
    runtime.setAnimationState(animationState);
    runtime.setSkeleton(skeleton);
  }

  void _startAnimation() {
    // 每帧更新动画
    TickerFuture.periodic(this, (delta) {
      // 更新动画时间
      animationState.update(delta);

      // 触发UI重建
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    // 渲染Skeleton到Canvas
    return CustomPaint(
      painter: SpinePainter(runtime, skeleton),
      size: Size(300, 300), // 根据需要调整大小
    );
  }

  @override
  void dispose() {
    // 停止动画更新
    TickerFuture.cancel(this);
    super.dispose();
  }
}

class SpinePainter extends CustomPainter {
  final SpineRuntime runtime;
  final SpineSkeleton skeleton;

  SpinePainter(this.runtime, this.skeleton);

  @override
  void paint(Canvas canvas, Size size) {
    // 设置绘制参数
    final paint = Paint();
    paint.color = Colors.white;

    // 获取骨架的边界框
    final bounds = skeleton.bounds;
    final x = (size.width - bounds.width) / 2;
    final y = (size.height - bounds.height) / 2;

    // 绘制骨架
    runtime.drawSkeleton(canvas, paint, skeleton, x, y);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true; // 每帧都重绘
  }
}

注意事项

  1. 资源文件:确保你的.atlas.json文件已经放在assets目录下,并在pubspec.yaml中声明它们:

    flutter:
      assets:
        - assets/your_spine_atlas.atlas
        - assets/your_spine_skeleton.json
    
  2. 动画名称:在animationState.setAnimation方法中,确保传递正确的动画名称。

  3. 性能setState在每次动画更新时都会调用,可能会导致性能问题。在实际应用中,你可能需要优化这部分逻辑,比如使用RepaintBoundary来减少不必要的重绘。

通过上述代码,你应该能够在Flutter应用中成功加载和渲染Spine动画。如果你有任何其他问题或需要进一步的帮助,请随时告诉我!

回到顶部