Flutter信号管理插件flame_signals的使用

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

Flutter信号管理插件flame_signals的使用

简介

flame_signals 提供了一种简单且类型安全的机制,用于在 FlameGame 中的组件之间传递带有或不带有数据负载的信号。

使用方法

1. 添加到游戏

要使用 flame_signals,首先需要在你的游戏类中添加 HasSignals 混入:

class SpaceGame extends FlameGame with HasSignals {
  // 游戏逻辑代码
}

该混入定义了一个 Stream 类型为 FlameSignal 的流,用于添加和广播信号。

2. 定义信号类

通过扩展 FlameSignal 基类来定义一个或多个信号对象。例如:

class MeteorDestroyedSignal extends FlameSignal {
  final Vector2 position;
  final double laserAngle;

  const MeteorDestroyedSignal({required this.position, required this.laserAngle});
}

class DecreaseMeteorCountSignal extends FlameSignal {}

3. 发送信号

任何组件都可以发送 FlameSignalSendSignalsFlameSignalListenable 混入都提供了一个 addSignal 方法来发送信号。例如:

class Meteor extends Component with SendSignals {
  // 组件逻辑代码

  void onHitByLaser() {
    addSignal(MeteorDestroyedSignal(
      position: position,
      laserAngle: laser.angle,
    ));
  }
}

4. 响应接收到的信号

需要响应游戏信号的组件可以使用 FlameSignalListenable 混入。信号处理器必须在组件的 onMount 生命周期方法中注册。这会创建一个对信号流的订阅。当组件从组件树中移除时,onRemove 生命周期方法会取消订阅。例如:

class MeteorManager extends Component with FlameSignalListenable {
  [@override](/user/override)
  void onMount() {
    super.onMount();
    onSignal<MeteorDestroyedSignal>((signal) {
      _generateNewMeteor();
      _updateMeteorCount();
    });
  }

  void _generateNewMeteor() {
    // 生成新的陨石逻辑
  }

  void _updateMeteorCount() {
    addSignal(DecreaseMeteorCountSignal());
  }
}

完整示例Demo

以下是一个完整的示例Demo,展示了如何在 FlameGame 中使用 flame_signals 插件。

main.dart

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

void main() {
  final game = ExampleGame();
  runApp(GameWidget(game: game));
}

example_game.dart

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flame/input.dart';
import 'package:flame/parallax.dart';
import 'package:flame_signals/flame_signals.dart';

class ExampleGame extends FlameGame with HasSignals {
  late MeteorManager meteorManager;

  [@override](/user/override)
  Future<void> onLoad() async {
    await super.onLoad();

    // 加载背景
    await loadParallaxBackground();

    // 添加陨石管理器
    meteorManager = MeteorManager();
    add(meteorManager);

    // 添加一些初始陨石
    for (int i = 0; i < 5; i++) {
      add(Meteor(Vector2(random.nextDouble() * size.x, random.nextDouble() * size.y)));
    }
  }

  Future<void> loadParallaxBackground() async {
    // 加载背景图层
    final parallaxComponent = ParallaxComponent(
      parallax: await gameRef.loadParallax([
        ParallaxImageData('background_layer_1.png'),
        ParallaxImageData('background_layer_2.png'),
      ], baseSpeed: Vector2(100, 0), repeat: ImageRepeat.repeatX),
    );
    add(parallaxComponent);
  }
}

class Meteor extends SpriteComponent with SendSignals {
  Meteor(Vector2 position) : super(position: position, size: Vector2(64, 64));

  [@override](/user/override)
  Future<void> onLoad() async {
    await super.onLoad();
    sprite = await gameRef.loadSprite('meteor.png');
  }

  [@override](/user/override)
  void update(double dt) {
    super.update(dt);
    // 移动陨石
    position += Vector2(-100 * dt, 0);
    if (position.x < -size.x) {
      position.x = gameRef.size.x + size.x;
    }
  }

  void onHitByLaser() {
    // 发送陨石被摧毁的信号
    addSignal(MeteorDestroyedSignal(
      position: position,
      laserAngle: 0.0, // 假设激光角度为0
    ));

    // 移除陨石
    removeFromParent();
  }
}

class MeteorManager extends Component with FlameSignalListenable {
  [@override](/user/override)
  void onMount() {
    super.onMount();
    // 注册信号处理器
    onSignal<MeteorDestroyedSignal>((signal) {
      _generateNewMeteor();
      _updateMeteorCount();
    });
  }

  void _generateNewMeteor() {
    // 生成新的陨石
    final newMeteor = Meteor(Vector2(random.nextDouble() * gameRef.size.x, random.nextDouble() * gameRef.size.y));
    gameRef.add(newMeteor);
  }

  void _updateMeteorCount() {
    // 发送减少陨石数量的信号
    addSignal(DecreaseMeteorCountSignal());
  }
}

class MeteorDestroyedSignal extends FlameSignal {
  final Vector2 position;
  final double laserAngle;

  const MeteorDestroyedSignal({required this.position, required this.laserAngle});
}

class DecreaseMeteorCountSignal extends FlameSignal {}

更多关于Flutter信号管理插件flame_signals的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter信号管理插件flame_signals的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用flame_signals插件来进行信号管理的示例代码。flame_signals是一个用于Flutter的事件和信号管理库,它可以帮助你更方便地在Flutter应用中处理各种事件。

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

dependencies:
  flutter:
    sdk: flutter
  flame_signals: ^x.y.z  # 替换为最新版本号

然后运行flutter pub get来获取依赖。

接下来,让我们创建一个简单的示例,展示如何使用flame_signals来管理信号。

示例代码

  1. 创建信号和监听器

首先,我们需要创建一个信号并添加监听器。在这个例子中,我们将创建一个简单的整数增加信号。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flame Signals Example'),
        ),
        body: SignalExample(),
      ),
    );
  }
}

class SignalExample extends StatefulWidget {
  @override
  _SignalExampleState createState() => _SignalExampleState();
}

class _SignalExampleState extends State<SignalExample> {
  // 创建一个信号
  final Signal<int> incrementSignal = Signal<int>();
  int counter = 0;

  @override
  void initState() {
    super.initState();
    
    // 添加一个监听器
    incrementSignal.listen((value) {
      setState(() {
        counter += value;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('Counter: $counter'),
        ElevatedButton(
          onPressed: () {
            // 触发信号,传递一个值
            incrementSignal.emit(1);
          },
          child: Text('Increment'),
        ),
      ],
    );
  }
}

在这个示例中,我们创建了一个Signal<int>类型的信号incrementSignal,并在initState方法中为其添加了一个监听器。当信号被触发时,监听器会更新counter变量的值,并通过setState方法刷新UI。

  1. 触发信号

在按钮的onPressed回调中,我们调用了incrementSignal.emit(1)来触发信号,并传递了一个整数值1

运行代码

将上述代码添加到你的Flutter项目中,并运行应用。你应该会看到一个显示计数器值的界面,以及一个按钮。每次点击按钮时,计数器值都会增加1。

这个示例展示了如何使用flame_signals库来管理信号和事件。你可以根据需要扩展这个示例,以处理更复杂的事件和信号。

回到顶部