はじめに
え!!Flutterでゲーム開発を!?
というわけで作りました。
実は、簡単なゲームならFlutterでも作れます。その立役者が「Flame」というゲームエンジンです。
私は普段Flutterで業務アプリを作っていますが、ゲーム開発の経験はほぼありませんでした。そんな中、「ちょっとしたゲームを自分で作ってみたい」と思い立ち、Flutter製のゲームエンジンFlameを使って、シンプルなワンタップ2Dゲーム「Zigzag」を開発しました。
結果として、Flutterの知識だけで意外と簡単にゲームが完成。この記事では、Flameの基本やFlutterでのゲーム開発の流れ、実際に作ったアプリのポイントを紹介します。
なぜFlutterでゲームを作ろうと思ったか
- 普段使っているFlutterで完結したかった
- Unityなどの大規模なツールは学習コストが高いと感じた
- 既存のFlutterスキルを活かして、短期間で何か形にしたかった
Flutterでゲームを作るための選択肢
Flutter単体でも簡単なアニメーションやインタラクションは作れますが、ゲームらしい仕組み(ゲームループ、当たり判定、スプライト管理など)を実装するにはFlameというゲームエンジンが最適です。
Flameとは
- Flutter製の軽量2Dゲームエンジン
- Flutter/Dartの知識がそのまま活かせる
- テキストエディタとFlutter環境だけで始められる
- UI画面とゲーム画面を組み合わせられる
Flameの基本と開発の流れ
Flameでゲームを作る際に押さえておきたいポイントをまとめます。
1. Gameクラス
FlameGame
を継承するだけで、ゲームの基盤が完成。
class MyGame extends FlameGame {
@override
Futurevoid> onLoad() async {
// ゲーム開始時の処理
super.onLoad();
}
@override
void update(double dt) {
// 毎フレーム呼ばれる処理
super.update(dt);
}
}
これでゲームループが作成できます。onLoad()
で初期化処理、update()
で毎フレームの更新処理を実装。
2. Componentシステム
ゲーム内のすべてのオブジェクト(プレイヤー、敵、アイテムなど)は「Component」として扱われます。
class Player extends RectangleComponent {
@override
Futurevoid> onLoad() async {
size = Vector2(50, 50);
paint = Paint()..color = Colors.blue;
}
@override
void update(double dt) {
super.update(dt);
// プレイヤーの動きをここに書く
position.x += 100 * dt; // 右に移動
}
}
RectangleComponent
で四角いオブジェクト、SpriteComponent
で画像付きオブジェクトを作成可能。
ゲームにadd(Player())
することで画面に表示されます。
3. 衝突判定
Flameでは衝突判定も簡単に実装可能。
// ゲームクラスに HasCollisionDetection を追加
class MyGame extends FlameGame with HasCollisionDetection {
// ...
}
// 衝突判定したいComponentに CollisionCallbacks を追加
class Player extends RectangleComponent with CollisionCallbacks {
@override
Futurevoid> onLoad() async {
super.onLoad();
add(RectangleHitbox()); // 衝突判定の範囲を設定
}
@override
bool onCollisionStart(SetVector2> intersectionPoints, PositionComponent other) {
if (other is Enemy) {
// 敵との衝突処理
print('ゲームオーバー!');
}
return true;
}
}
HasCollisionDetection
とCollisionCallbacks
を追加し、onCollisionStart
で衝突時の処理を実装。
実際に作ったアプリの紹介
今回作成した「Zigzag」は、ワンタップで遊べるエンドレス2Dサバイバルゲームです。Flameの基本機能だけで、シンプルなハイパーカジュアルゲームを実現しました。
開発の進め方と工夫
タップ操作や時間経過の処理
class MyGame extends FlameGame with TapDetector {
@override
bool onTapDown(TapDownInfo info) {
print('タップされた位置: ${info.eventPosition.game}');
// プレイヤーの方向転換などの処理
return true;
}
}
時間経過での処理
class MyGame extends FlameGame {
double timer = 0;
@override
void update(double dt) {
super.update(dt);
timer += dt;
// 1秒ごとに敵を出現させる
if (timer >= 1.0) {
add(Enemy());
timer = 0;
}
}
}
Flutter UIとの統合
ゲーム画面にFlutterのウィジェットを重ねることが可能。
GameWidgetMyGame>.controlled(
gameFactory: MyGame.new,
overlayBuilderMap: {
'menu': (context, game) => MenuOverlay(),
'gameOver': (context, game) => GameOverOverlay(),
},
)
メニューやゲームオーバー画面は、通常のFlutterウィジェットで実装。
Flameでできること・できないこと
Flameが得意なこと
- 2Dゲーム全般:アクション、パズル、RPG、シューティングなど
- UI統合:複雑なメニューやダイアログ
- モバイル最適化:タッチ操作、センサー活用
- 軽量ゲーム:カジュアルゲーム、ハイパーカジュアルゲーム
Flameが苦手なこと
- 3Dゲーム:3D機能は限定的
- 大規模ゲーム:リッチな大規模ゲーム開発には不向き
- 高度な物理演算:複雑な物理シミュレーションは困難
パフォーマンス最適化のポイント
- オブジェクトプールの活用
- 不要なコンポーネントの削除
@override
void update(double dt) {
super.update(dt);
// 画面外のオブジェクトを削除
if (position.y > gameRef.size.y + 100) {
removeFromParent();
}
}
技術スタック
dependencies:
flutter: ^3.0.0
flame: ^1.18.0
shared_preferences: ^2.2.2
google_fonts: ^6.1.0
参考リソース
まとめ
FlutterとFlameを使えば、普段Flutterアプリを書いている人でも、手軽に2Dゲーム開発を始められます。Unityのような大規模な環境を用意しなくても、Dartの知識だけで十分にゲームが作れます。
「ゲーム開発は難しそう」と感じている方も、まずはFlameのサンプルを動かしてみるのがおすすめです。私自身、最初は不安でしたが、実際に手を動かしてみると意外と簡単に形になりました。
この記事が、Flutterエンジニアやゲーム開発に興味のある方の一歩目になれば幸いです。
「自分でも作れそう」と思ったら、ぜひFlameでゲーム開発に挑戦してみてください。
…実はこの「Zigzag」はゲーム作りの練習として作成したものです。今年中には、もともと考えていた本命の企画をきちんと形にしてリリースしたいと思っています。
Views: 0