Flutter等距视图插件flame_isometric的使用

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

Flutter等距视图插件flame_isometric的使用

概述

flame_isometric 是一个用于在 Flutter 的游戏引擎 Flame 中渲染等距(Isometric)地图的插件。它生成渲染等距地图所需的矩阵,并支持多层和多个图块集(tileset)。

特性

  • 支持多层地图
  • 支持多个图块集
  • 可以轻松地从 Tiled Map Editor 导入地图数据

使用方法

导入 IsometricTileMapComponent

在 Flame 1.6.0 版本中,IsometricTileMapComponent 不直接支持从 Tiled Map Editor 导入地图数据,而是通过 tilesetImagematrix 来生成地图。你需要使用 package:tiled/tiled.dartpackage:flame/sprite.dart 来解析 TMX 数据并生成矩阵。

生成矩阵

final flameIsometric = await FlameIsometric.create(
  tileMap: 'tile_map.png',
  tmx: 'tiles/tile_map.tmx',
);

生成的矩阵按层存储在 flameIsometric 实例的 matrixList 中。

渲染地图

for (var i = 0; i < flameIsometric.layerLength; i++) {
  add(
    IsometricTileMapComponent(
      flameIsometric.tileset,
      flameIsometric.renderMatrixList[i],
      destTileSize: flameIsometric.srcTileSize,
      position: Vector2(gameSize.x / 2, flameIsometric.tileHeight.toDouble()),
    ),
  );
}

支持多个图块集

你也可以支持多个图块集:

final flameIsometric = await FlameIsometric.create(
  tileMap: ['tile_map.png', 'tile_map2.png'],
  tsxList: ['tiles/tile_map.tsx', 'tiles/tile_map2.tsx'],
  tmx: 'tiles/tile_map2.tmx',
);

使用 CustomIsometricTileMapComponent

为了更方便地渲染多层地图,可以使用 CustomIsometricTileMapComponent

for (var renderLayer in flameIsometric.renderLayerList) {
  add(
    CustomIsometricTileMapComponent(
      renderLayer.spriteSheet,
      renderLayer.matrix,
      destTileSize: flameIsometric.srcTileSize,
      position: Vector2(gameSize.x / 2, flameIsometric.tileHeight.toDouble()),
    ),
  );
}

注意事项

  • 不同大小的图块集可以显示,但绘制时的位置可能需要调整。
  • 目前,Flame 1.6.0 不支持矩形地图,因此在 Tiled Map Editor 中创建地图时,必须选择 “Isometric”(而不是 “Isometric (Staggered)”)。

创建参考

使用 Tiled Map Editor 创建等距地图

  1. 打开 Tiled Map Editor。
  2. 选择 “Isometric”(不是 “Isometric (Staggered)”)作为地图的方向。
  3. 选择合适的地图形状和图块集。

图层

  • Bottom 层:主要用于放置地板。
  • Middle 层:主要用于放置墙壁等。
  • Top 层:主要用于放置屋顶等。

示例代码

以下是一个完整的示例代码,展示了如何使用 flame_isometric 插件来渲染等距地图。

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

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const App());
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'IsometricMap Sample',
      home: MainGamePage(),
    );
  }
}

class MainGamePage extends StatefulWidget {
  const MainGamePage({Key? key}) : super(key: key);

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

class MainGameState extends State<MainGamePage> {
  MainGame game = MainGame();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          GameWidget(game: game),
        ],
      ),
    );
  }
}

class MainGame extends FlameGame with HasGameRef {
  @override
  Future<void> onLoad() async {
    super.onLoad();
    final gameSize = gameRef.size;

    // 单个图块集
    // final flameIsometric = await FlameIsometric.create(
    //     tileMap: 'tile_map.png', tmx: 'tiles/tile_map.tmx');
    //
    // for (var i = 0; i < flameIsometric.layerLength; i++) {
    //   add(
    //     IsometricTileMapComponent(
    //       flameIsometric.tileset,
    //       flameIsometric.renderMatrixList[i],
    //       destTileSize: flameIsometric.srcTileSize,
    //       position: Vector2(gameSize.x / 2, flameIsometric.tileHeight.toDouble()),
    //     ),
    //   );
    // }

    // 多个图块集
    final flameIsometric = await FlameIsometric.create(
      tileMap: ['tile_map.png', 'tile_map2.png'],
      tsxList: ['tiles/tile_map.tsx', 'tiles/tile_map2.tsx'],
      tmx: 'tiles/tile_map2.tmx',
    );

    for (var renderLayer in flameIsometric.renderLayerList) {
      add(
        CustomIsometricTileMapComponent(
          renderLayer.spriteSheet,
          renderLayer.matrix,
          destTileSize: flameIsometric.srcTileSize,
          position: Vector2(gameSize.x / 2, flameIsometric.tileHeight.toDouble()),
        ),
      );
    }
  }
}

贡献者

版权持有者

作者


更多关于Flutter等距视图插件flame_isometric的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter等距视图插件flame_isometric的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter中使用flame_isometric插件来实现等距视图效果的代码案例。flame_isometric是一个基于flame游戏引擎的插件,用于创建等距投影(Isometric Projection)的游戏视图。

首先,确保你的Flutter项目已经添加了flameflame_isometric依赖。在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  flame: ^1.0.0  # 请使用最新版本号
  flame_isometric: ^0.x.x  # 请使用最新版本号,注意替换x为实际版本号

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

接下来,我们编写一个简单的示例,展示如何使用flame_isometric来创建等距视图。

main.dart

import 'package:flutter/material.dart';
import 'package:flame/flame.dart';
import 'package:flame_isometric/flame_isometric.dart';
import 'package:flutter/services.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Flame.images.loadAll([
    'tile.png',  // 假设你有一个名为tile.png的瓦片图像
  ]);
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Isometric View with flame_isometric'),
        ),
        body: IsometricGameWidget(),
      ),
    );
  }
}

class IsometricGameWidget extends StatefulWidget {
  @override
  _IsometricGameWidgetState createState() => _IsometricGameWidgetState();
}

class _IsometricGameWidgetState extends State<IsometricGameWidget> {
  late IsometricTileMap _tileMap;

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

  void _createTileMap() {
    // 定义瓦片大小
    final tileSize = Vector2(64.0, 32.0);

    // 定义地图层
    final layers = [
      IsometricTileLayerData.fromTileGrid(
        tiles: [
          // 这里填入你的瓦片ID,假设每个瓦片都是0(即使用相同的瓦片图像)
          for (int y = 0; y < 10; y++) ...[
            for (int x = 0; x < 10; x++) 0,
          ],
          tileSize: tileSize,
        ),
      ],
    );

    // 创建地图
    _tileMap = IsometricTileMap(
      layers: layers,
      tilesetImage: 'tile.png',  // 瓦片图像路径
      tileWidth: tileSize.x,
      tileHeight: tileSize.y,
    );
  }

  @override
  Widget build(BuildContext context) {
    return IsometricCamera(
      tileMap: _tileMap,
      cameraSize: Vector2(800, 600),  // 相机视图大小
      cameraPosition: Vector2(0, 0),  // 相机初始位置
      child: IsometricGameRenderBox(
        tileMap: _tileMap,
      ),
    );
  }
}

资源准备

确保你在项目的assets文件夹中有一个名为tile.png的瓦片图像。同时,在pubspec.yaml文件中添加该资源:

flutter:
  assets:
    - assets/tile.png  # 确保路径正确

解释

  1. 依赖加载:在main.dart中,我们确保Flutter和Flame库已初始化,并加载了瓦片图像。
  2. IsometricGameWidget:这是一个StatefulWidget,用于包含等距视图游戏逻辑。
  3. _createTileMap:此方法创建了一个等距瓦片地图。我们定义了瓦片大小、瓦片网格数据以及瓦片图像。
  4. IsometricCamera:这是一个Widget,用于控制相机的视图。你可以调整cameraSizecameraPosition来更改视图大小和位置。
  5. IsometricGameRenderBox:这是一个RenderBox,用于渲染等距瓦片地图。

这个示例展示了如何使用flame_isometric插件来创建一个简单的等距视图。你可以根据需要进一步扩展和自定义,例如添加交互、动画等。

回到顶部