我的火焰游戏概念是,玩家移动,当玩家撞到星星物体时,会出现一个包含问题的弹出Flutter 窗口,当用户关闭它时,游戏状态和玩家位置将恢复.我该怎么做呢?

我try 了Navigator.Push,但它不起作用,它显示没有可用的上下文:(

我还try 了一种不同的方法,那就是覆盖,但Star类不能访问覆盖属性,我在游戏主类"PlayerWithBG"中编写了一个方法,但调用它会引发异常……

这是Star类内部的代码

import 'package:flame/collisions.dart';
import 'package:flame/components.dart';
import 'package:flame/sprite.dart';
import 'package:flutter/material.dart';
import 'package:khalooq/Game/PlayerWithBG.dart';
import '../Questions/firstLevelQuestions.dart';
import 'helpers/directions.dart';

class Star extends SpriteAnimationComponent
    with HasGameRef, CollisionCallbacks {
  Star(Vector2 position)
      : super(size: Vector2.all(50), position: position, anchor: Anchor.center);

  final gameObject = PlayerWithBG();

  late final SpriteAnimation _rotateAnimation;
  final double _animationSpeed = .3;
  Direction direction = Direction.right;

  @override
  Future<void> onLoad() async {
    super.onLoad();
    await _loadAnimations().then((_) => {animation = _rotateAnimation});
    add(CircleHitbox());
  }

  Future<void> _loadAnimations() async {
    final spriteSheet = SpriteSheet.fromColumnsAndRows(
        image: await gameRef.images.load('stars1.png'), columns: 10, rows: 1);

    _rotateAnimation = spriteSheet.createAnimation(
        row: 0, stepTime: _animationSpeed, from: 0, to: 4);
  }

  @override
  void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
    super.onCollision(intersectionPoints, other);
    // gameObject.showQuestion();
    // calling the showQuestion() method throws an exception in the method
    /*
     * Exception has occurred.
      _AssertionError ('package:flame/src/game/overlay_manager.dart': Failed assertion: line 51 pos 7: '_builders.containsKey(name)': Trying to add an unknown overlay "Question")
     */

    removeFromParent();
    //This is what I want to do--------------------------------------------------
    // Navigator.push(
    //     context, MaterialPageRoute(builder: (context) => firstLevelQuestion()));
  }
}

这是主游戏类"PlayerWithBG"中的代码

import 'dart:ui';

import 'package:flame/game.dart';
import 'package:flame/input.dart';
import 'package:flutter/services.dart';
import 'Player.dart';
import 'GameBG.dart';
import 'package:flutter/material.dart';

import 'Star.dart';
import 'helpers/directions.dart';

class PlayerWithBG extends FlameGame
    with KeyboardEvents, HasCollisionDetection, TapDetector {
  Player _player = Player();
  GameBG _gameBG = GameBG();

  @override
  Future<void> onLoad() async {
    super.onLoad();
    await add(_gameBG);
    double bgWidth = _gameBG.size.x;
    double bghight = _gameBG.size.y;
    await add(_player);
    _player.position = Vector2(bgWidth * 0.05, bghight * 0.95);
    camera.followComponent(_player,
        worldBounds: Rect.fromLTRB(0, 0, _gameBG.size.x, _gameBG.size.y));
    //--------------------------------------------------------------------------------------
    //Stars are the elements that should open the question when the player collides with them
    add(Star(Vector2(bgWidth * 0.10, bghight * 0.95)));
    add(Star(Vector2(bgWidth * 0.30, bghight * 0.95)));
  }

  void showQuestion() {
    if (overlays.isActive('Question')) {
      overlays.remove('Question');
      resumeEngine();
    } else {
      overlays.add('Question');
      pauseEngine();
    }
  }

  onArrowKeyChanged(Direction direction) {
    _player.direction = direction;
  }
}

在这里,我使用临时覆盖容器调用游戏小部件

          GameWidget(
            game: game..paused = false,
            //here is the overlayer to render the question--------------------
            overlayBuilderMap: {
              'Question': (BuildContext context, PlayerWithBG game) {
                return Center(
                  child: Container(
                    width: 100,
                    height: 100,
                    color: Colors.orange,
                    child: Center(child: Text('This is a question')),
                  ),
                );
              },
            },
            //-----------------------------------------------------------------
          ),

推荐答案

您可以通过几种不同的方式完成此操作:

1.Use the overlays system

就像您try 的那样,但是要访问覆盖,您可以使用这样一个事实,即您的组件上有HasGameRef个Mixin,这使您可以访问gameRef变量,从而访问gameRef.overlays.add/remove.

你可以阅读更多关于这here人的内容.

2. Use the 100

这项技术稍微先进一些,但如果你有很多不同的屏幕和场景,它绝对值得一试.

示例:

final router = RouterComponent(
  routes: {
    'ok-dialog': OverlayRoute(
      (context, game) {
        return Center(
          child: DecoratedContainer(...),
        );
      },
    ),  // OverlayRoute
    'confirm-dialog': OverlayRoute.existing(),
  },
);

router.pushNamed('ok-dialog);

关于这here人,你可以读到更多的东西.

3. Use the normal Flutter navigation

最后一种,也是最不符合人体工程学的方法,是使用Ffltter的内置导航(或另一个导航套装). 当您拥有HasGameRef Mixin时,您可以使用与访问overlays相同的方式获取上下文:

gameRef.buildContext;

根据导航方式的不同,在创建GameWidget时可能需要使用GameWidget.controlled构造函数.

Flutter相关问答推荐

Flutter bloc -如何使用BlocBuilder?

创建多个具有适当填充和对齐的按钮的最佳方法

Flutter 文件拾取器Android SingleInstance模式它返回的文件路径为空

如何在Date Time类中只显示日期?

如何从文本比例因子迁移到文本比例因子

从future 列表到流列表Flutter Firebase

创建仅定义导出的文件是否有意义?

Flutter:如何设置 PersistentFooterButtons 背景?

Flutter居中的SizedBox无法居中

在允许屏幕 Select 和点击的同时保持通用对话框显示

Flutter: pie_chart 插件动画滚动问题

像图像一样Flutter 自定义标签

Elevated 和 Outlined 按钮之间的动画

通过一个具体的例子理解Flutter约束的本质

java.lang.IncompatibleClassChangeError:找到接口 com.google.android.gms.location.SettingsClient,

如何将 List 转换为 String []?

如何将金钱格式化为数以百万计的Flutter 动?

无法将参数类型Future Function(String?)分配给参数类型void Function(NotificationResponse)?

如何在屏幕按钮中排列 row() (我想在按钮中放置屏幕导航图标)

Android Studio 模拟器屏幕闪烁