Flutter体验 Day 27-flame SpriteComponent

flame SpriteComponent

看着团队挑战的成员写了一篇 从零开始的8-bit迷宫探险!Swift SpriteKit 游戏开发实战,那我们今天就来挑战看看怎麽在 flutter 上开发游戏好了。

flame 介绍

这是一套在 Flutter 上的 2D 游戏引擎。

目前稳定版本是 0.29.4,不过预发布版本已来到 flame 1.0.0-releasecandidate.14,两边的语法写法不大相同,研究前请注意一下。

在官网上文件尚不完整,建议参考awesome-flame上的教学文章。

套件设定

pubspec.yaml 加入套件设定

dependencies:
  ...
  flame: ^1.0.0-releasecandidate.14
  ...

游戏开发

想起以前在研究 Cocos Creator 时的 星星 游戏,想说试着用 flame 来开发看看,我们从 cocos-creator GitHub 上可以取得图片素材。

游戏相关设定

import 'package:flutter/material.dart';
import 'package:flame/flame.dart';
import 'package:flame/game.dart';

void main() async {
  // 确认 Flutter 已刚成初始化绑定动作
  WidgetsFlutterBinding.ensureInitialized();

  // 设定全屏以及横向显示
  Flame.device.fullScreen();
  Flame.device.setLandscape();

  runApp(const StarsApp());
}

目前 1.0.0 的语法,需使用 GameWidget 带入 game 参数。

class StarsApp extends StatelessWidget {
  const StarsApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Stars',
      theme: ThemeData.dark(),
      home: Scaffold(body: GameWidget(game: StarGame())),
    );
  }
}
import 'package:flame/game.dart';

class StarGame extends FlameGame {
  // 取得 App 画面宽高
  final double screenWidth = MediaQueryData.fromWindow(window).size.width;
  final double screenHeight = MediaQueryData.fromWindow(window).size.height;

  @override
  Future<void> onLoad() async {
      // TODO
  }
}

图片设定

与 Flutter 在使用图片方式一样,在 pubspec.yamlassets 定义图片来源。

flutter:
  uses-material-design: true
  assets:
    - assets/images/

StarGame 属性定义会使用到的图片设定

  static const _assetsImages = [
    'purple_moster.png',
    'background.jpg',
    'ground.png',
    'star.png'
  ];

使用 FlameGameimages 戴入

  Future<void> onLoad() async {
    await images.loadAll(_assetsImages);
  }

SpriteComponent

我们使用 SpriteComponent 定义 Sprite 内容,这个 Component 提供 sizeposition 参数可对应画面上的设定。

class SpriteComponent extends PositionComponent with HasPaint {
  /// The [sprite] to be rendered by this component.
  Sprite? sprite;

  /// Creates a component with an empty sprite which can be set later
  SpriteComponent({
    Vector2? position,
    Vector2? size,
    int? priority,
    this.sprite,
    Paint? paint,
  }) : super(
          position: position,
          size: size ?? sprite?.srcSize,
          priority: priority,
        ) {
    if (paint != null) {
      this.paint = paint;
    }
  }
  • 背景精灵元件设定

使用 SpriteComponent 来设定背景图片,从 size 指定元件的宽高

import 'package:flame/components.dart';
import 'star_game.dart';

class Background extends SpriteComponent {
  Background(StarGame _game)
      : super(
          sprite: Sprite(
            _game.images.fromCache('background.jpg'),
          ),
          size: Vector2(_game.screenWidth, _game.screenHeight),
        );
}

使用 addComponent 新增至画面上

  Future<void> onLoad() async {
    await images.loadAll(_assetsImages);
    final background = Background(this);
    add(background);
  }
  • 地面精灵元件设定
import 'package:flame/components.dart';
import 'star_game.dart';

class Ground extends SpriteComponent {
  final double _height = 100;
  final StarGame _game;
  Ground(this._game)
      : super(sprite: Sprite(_game.images.fromCache('ground.png'))) {
    size = Vector2(_game.screenWidth, _height);
    position = Vector2(0, _game.screenHeight - _height);
  }
}
  • 怪兽精灵元件设定
import 'package:flame/components.dart';
import 'star_game.dart';

class Moster extends SpriteComponent with Hitbox, Collidable {
  late final StarGame _game;
   Moster(this._game)
      : super(
          sprite: Sprite(_game.images.fromCache('purple_moster.png')),
          size: Vector2(64, 64),
        ) {
    x = 200;
    y = _originY = _game.screenHeight - _game.ground.height - height / 2;
    anchor = Anchor.center;
  }

今日成果

flame_start

程序码


<<:  Kotlin Android 第30天,从 0 到 ML - 总结

>>:  Day 21 -SQL 函数 MIN()和MAX()!

Day 45 (Node.js)

1.版本 https://nodejs.org/en/ 下载LTS (长期稳定版本) 用10以上版本...

PHP 一些概念

汇入 require: 可汇入多次, 如果出现错误, 会出现提醒, 并停止代码运行 include:...

Day6 - 2D渲染环境基础篇 II [同场加映 - 非零缠绕与奇偶规则] - 成为Canvas Ninja ~ 理解2D渲染的精髓

路径绘制常令人感到疑惑的点 - 非零缠绕与奇偶规则 初学路径绘制的时候,大部分人应该会发现一种让人疑...

序言 - UI/UX 与 网页设计一路走来

大家好,我是 WEN ,目前在科技公司担任 UIUX 设计师。这次铁人赛的目标,是在30天之内来挑战...

从零开始学游戏设计:游戏中的背景音乐

这是 Roblox 从零开始系列,游戏环境章节的第五个单元,今天你将学会如何在游戏内播放背景音乐 【...