娘のためにFlutterでゲームを作ってみた with Nuxt.js
昔作ったUnityのゲームアプリ、なぜか娘が楽しそうに遊んでいて、
Flutterでリメイクしてみよ!と思い立ち、無事リリースできたので、
構成とかをまとめてみました(*´ω`*)
どんなゲーム?
鯖(サバ)の中から鮪(マグロ)を探す
かわいいお気軽タッチゲーム🐟
実際のプレイ画面はこんな感じに
せっかくリメイクするので、
「親子で一緒にたのしめるシンプルなゲーム」
にしたいな〜とおもい、子供でもできるシンプルなルールで、
大人も楽しめる難易度になるようがんばってます!
システム構成
全体の構成はこんな感じ
- Flutter(アプリ)
- Nuxt.js(LPサイト)
- unjs/nitro(OGP生成など)
- Firebase(Auth/Firestore)
- Cloudflare R2(OGP保存)
- TypeSpec(Dart/TS間でのモデル共通化)
- Cloud Run + Firebase Hosting
使い慣れてるNuxt.js+Firebase+GCPに、
Flutter+Cloudflare R2を追加した感じ
アプリ本体
Flutterで利用したライブラリはこんな感じ
- riverpod/flutter_hooks/go_router/freezed
- BGM/効果音: audioplayers
- 広告: google_mobile_ads(AdMob)
- アプリ内課金: purchases_flutter(RevenueCat)
- トースト通知: toastification
- シェア機能: share_plus
- アニメーション: lottie(ハイスコア時)
Casual Games Toolkit
使い慣れたもの+公式のCasual Games Toolkitに
記載されているパッケージから選定。
いくつかのゲームのテンプレートも用意されているので、それも参考になった
Flameは利用しない
Flutterでゲームを作るときは、FlameやBonfireなどの、
ゲームエンジンを使うものがでてくるけど、シンプルなタッチーゲームなので
- 重力などの物理演算や衝突判定
- 広いマップや移動できるカメラ
- パラパラ漫画みたいなスプライト
などは不要なのでゲームエンジンは使わない形に。
ただリッチな機能が満載なので、ドキュメントを軽く見るのもいいかも。
チュートリアルもいくつか用意されてる。
参考にしたSuper Dash
よく参考にしていたのは公式のアプリ
アプリ自体やソースも公開されてる
- Super Dashの記事
- Super Dashのリポジトリ
- Super Dashのアプリ
riverpod/go_routerではなけど、
メニュー画面や効果音などの扱い方など、
ゲームのプレイ画面以外のところも参考になった
実際につくってみて
Super DashのソースとFlameのドキュメントを読んで、
この内容ならゲームエンジンなくてもよさそうと判断した感じ
実際には思ってたよりもスルスル動いてくれて、
RepaintBoundaryを使ったり、Wigetを適切に分離するので十分いけたので、
これでちょっとしたものなら結構作れるのでよかった(*´ω`*)
LPサイト/APIサーバ
LPサイトは事前予約などの告知や
利用規約の配置場所としてNuxt.jsで用意
APIサーバはシェア時の画像生成したかったので、
Cloud Run上にunjs/nitroで立ててる感じ
生成した画像の保存場所には、お安いと噂の
Cloudflare R2にしてみたけど、簡単に使えてよかった
シェアされてるステージですぐ遊べるように、
Deep Linkにも対応したので、Nuxt.jsはSSRにしてる。
Nuxt.jsの中身もunjs/nitroなので、
serverMiddlewareも共通化も楽ちん
Nuxt2系のときより書きやすくなっててかなりよかった(*´ω`*)
Dart/TypeScript間でのモデル共通化
FlutterもAPIサーバもFirestoreを参照するけど、
両方のモデルを管理するのはめんどくさい。。ので、
- TypeSpecで定義
- tspでコンパイルして、openapi.yamlを生成
- openapi-typescript-codegenでTypeScript版を生成
- swagger_parserでDart版を生成
という感じにして、OpenAPI定義起点で共通化してる。
これでFirestoreのスキーマを変えたときに、
片方反映漏れするとかがだいぶ減ってよかった(*´ω`*)
多言語対応
多言語対応もちゃんとしなきゃなと、英語だけ対応
翻訳とかメッセージ管理はめんどくさいのでこんな感じに
- スプレッドシートで管理&GOOGLETRANSLATE関数で翻訳
- SSSAPIでJSON化
- Nuxtは、JSONをそのままnuxt-i18nに
- Flutterは、分割してflutter_localizationsに
{
"ja": {
"appName": "マグロ探し",
"labelRankingTermMyscore": "マイスコア",
"labelRankingTermOnline": "オンライン",
"labelRankingTermToday": "本日",
"labelRankingTermWeekly": "週間",
"labelRankingTermMonthly": "月間",
"labelRankingTermAll": "総合"
},
"en": {
"appName": "MAGURO Finding",
"labelRankingTermMyscore": "My Score",
"labelRankingTermOnline": "Online",
"labelRankingTermToday": "Today",
"labelRankingTermWeekly": "Weekly",
"labelRankingTermMonthly": "Monthly",
"labelRankingTermAll": "ALL"
}
}
JSONのダウンロードから分割までは、
シェルスクリプトにしておけば、
半自動で管理できるのでだいぶ楽ちんに(*´ω`*)
Flutterでゲーム、結構いい
はじめてのライブラリも多かったので、時間がかかったけど、
慣れてしまえば、かなりいいかも。
公式のドキュメントにもサンプルが増えているし、
動画やShowcaseもあるので、参考にできるものも増えてきてる。
描画性能も上がっていたりするので、
よりサクサクプレイできるのがつくれるかも!
よかったらぜひダウンロードしてみて、
遊んでみてください〜(*´ω`*)
Flutter側で試行錯誤した話もこちらにまとめてるのでよかったら!!
Discussion