前のページはこちら
Flameにはゲームウィジェット上に既存のウィジェットを載せる事が可能で、かつ、ゲームとの連携も出来ます。
Contents
簡単なウィジェットを載せてみる
ウィジェットの作成
簡単なStatelessWidgetでボタンを新しく作ってみます。GenerationButton.dartという名前でコードは下記となります。
import 'package:flutter/material.dart';
import 'your_game.dart';
class GenerationButton extends StatelessWidget {
const GenerationButton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
onPressed: () {},
child: const Text('Start'),
),
);
}
}
GameWidgetのパラメータにoverlayBuilderMapを追加
main.dartで呼んでいたGameWidgetのパラメーターにoverlayBuilderMapを追加します。「startButton」というKeyを定義し、そのkyeに対するウィジェットを登録しています。
登録時の第2引数にYourGame型のyourGameを定義しています。最後に先ほど作ったGenerationButtonを記述しています。
body: GameWidget(
game: yourGame,
overlayBuilderMap: {
'startButton': (context, YourGame yourGame) => GenerationButton(),
},
),ゲーム側で起動させる
your_game.dartでウィジェットを起動させます。onLoadだと上手く動かない時があったので、今回はonLoadが完了した後に呼ばれるonMountに記載します。overlays.addで先ほど定義したKeyを呼び出せば、ゲーム上にウィジェット(今回はスタートボタン)が出現します。
@override
Future<void> onMount() async {
overlays.add('startButton');
}
ゲームとの連携
ゲーム内の関数を実行したり、ゲーム内の値を参照したりと、ゲーム内との連携も可能です。コードを書き換えます。
your_game.dartに関数追加
your_gameに円をランダムで生成する関数を追加します。updateの方はまるっと消してしまいます。
void makeCirecle() {
//半径、X、Yのランダム値生成
var randomRadius = Random().nextInt(50) as double;
var randomX = Random().nextInt(300) as double;
var randomY = Random().nextInt(300) as double;
//CircleManを生成する。もうadd関数の中で生成しちゃう。
add(CircleMan(randomRadius, Vector2(randomX, randomY)));
}GenerationButton.dart書き換え
GenerationButtonを下記に書き換えます。今回はStatefulWidgetです。
import 'package:flutter/material.dart';
import 'circle_man.dart';
import 'your_game.dart';
class GenerationButton extends StatefulWidget {
const GenerationButton({Key? key, required this.yourGame}) : super(key: key);
final YourGame yourGame;
@override
_GenerationButtonState createState() => _GenerationButtonState();
}
class _GenerationButtonState extends State<GenerationButton> {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('生成された円の数は' +
widget.yourGame.children.query<CircleMan>().length.toString()),
ElevatedButton(
onPressed: () {
widget.yourGame.makeCirecle();
setState(() {});
},
child: const Text('Start'),
),
],
),
);
}
}解説
const GenerationButton({Key? key, required this.yourGame}) : super(key: key);
final YourGame yourGame;yourGame自体を保持します。
children: [
Text('生成された円の数は' +
widget.yourGame.children.query<CircleMan>().length.toString()),
ElevatedButton(
onPressed: () {
widget.yourGame.makeCirecle();
setState(() {});
},
child: const Text('Start'),
),
],テキストとボタンを出しています。
テキストの方は保持したyourGameを使って、以前使ったchildren.queryが使えます。lengthで取得したCircleManの数が取得できます。それをTextで出しています。
ボタンの方では先ほどyour_gameで定義したmakeCirecleを実行しています。
GameWidgetのパラメータも追加
GenerationButtonがyourGameを受け取るので、GameWidget側で渡す必要があります。下記のコードはGenerationButtonの引数としてyourGameを渡しています。
body: GameWidget(
game: yourGame,
overlayBuilderMap: {
'startButton': (context, YourGame yourGame) => GenerationButton(
yourGame: yourGame,
),
},
),実行

Startボタンを押す度に円が出来ていきます。また、カウントも増えていくのが確認出来ます。
ウィジェットの消去
最後に、ボタンの消去をしてみます。your_game.dartのmakeCirecleを変更します。
void makeCirecle() {
//半径、X、Yのランダム値生成
var randomRadius = Random().nextInt(50) as double;
var randomX = Random().nextInt(300) as double;
var randomY = Random().nextInt(300) as double;
//CircleManを生成する。もうadd関数の中で生成しちゃう。
add(CircleMan(randomRadius, Vector2(randomX, randomY)));
if (children.query<CircleMan>().length > 50) {
overlays.remove('startButton');
}
}追加したif文は、生成されたCircleManの数が50を越えたら、overlays.removeでウィジェットを消去するという意味になります。これで実行すると、50を越えるとボタンが消えます。
次のページはこちら