🐢

ウミガメのスープを1人で遊べるアプリを作りました

2024/11/11に公開

1人でウミガメのスープを遊べるiOSアプリを作りました。

https://apps.apple.com/jp/app/1人でウミガメのスープ/id6544801645

アプリの概要

「ウミガメのスープ」は以下のようなゲームです。

出題者が問題を出し、他の人は「はい」または「いいえ」で答えられる質問を出す。質問者は、出題者が考えているストーリー、あるいは物を推測して語る。それがすべての謎を説明できたとき、このパズルは解けたことになる。

Wikipedia - シチュエーションパズルより引用)

通常は複数人でプレイするゲームですが、このアプリでは出題者をChatGPTに担当してもらうことで1人でウミガメのスープを遊ぶことができます。

問題は今のところ15問で遊びたい問題を選択してプレイできます。
(良い問題が思いついたら追加する予定です)

アプリ開発のきっかけ

2024年4月から業務でモバイルアプリ開発をすることになりました。

自分はWebアプリの開発経験しかなく業務時間だけのコミットでは足りないと感じたため、しばらくは個人開発の時間をモバイルアプリ開発に充てようと思い立ち6月くらいから少しずつ作り始めました。

元々ウミガメのスープというゲーム自体が好きだったことに加えて、ChatGPTに問題を入力して1人で遊んだことがあり「いつかアプリとして作れそうだな」と目星をつけていたためテーマはすぐに決まりました。

ウミガメのスープのアプリは既にストアにもいくつかありましたが、

  • 1人で遊べないものが多い
  • 解答を見ても納得感がない問題が多い
  • 問題と解答が文章だけでUIが寂しい

という改善点があり、もっと良いアプリを作ってやるぞという気持ちでそのままGOしました。

技術スタック

今回は業務で使用する技術を先回りして勉強することが目的であったため、基本的に業務で採用されたものをそのまま採用しています。

Flutter

業務で使用しているのがFlutterであるため、Flutterを採用しました。

DartはGoogleがJavaScriptの代替言語として開発したという経緯があるようで書きっぷりが非常に似ており、Dart特有の構文を勉強する前でもコードを眺めると何をしているかは概ね理解することができました。

Dartの公式ドキュメントにもJavaScript開発者向けに「ここは同じだけどここは違うよ!」を説明するページが用意されており、両言語で多くの概念が共通すると述べられています。
https://dart.dev/resources/coming-from/js-to-dart

また、FlutterのWidgetを並べてUIを構築していくスタイルはReactでコンポーネントライブラリを使用している感覚に似ていると感じました。Flutterはクラスベースなので思想こそ違うのですが、コンポーネント(ウィジェット)の分割・状態管理・責務の設計はReactの考え方を流用できるところがあると自分は感じました。

ちなみにFlutterなのにAndroidでリリースしていないのは、実機確認に使えるAndroidの端末を持っていないためです...

Riverpod

RiverpodはFlutter/Dart用のリアクティブキャッシュフレームワークであると述べられています。

https://riverpod.dev/ja/docs/introduction/why_riverpod

非同期データの取得結果を自動的にproviderにキャッシュし、データの変更を監視して必要なときだけUIを更新する仕組みを使いやすいAPIで提供してくれます。

非常に便利なライブラリでしたが最初から入れてしまったのは良くなかったと感じています。

そもそも学習目的の個人開発だったのでまずはネイティブのAPIで書いてみて、riverpodがないとどう苦しいのかを理解してから導入しても良かったなと思いました。

freezed

Dartのデータクラス生成ライブラリです。

https://pub.dev/packages/freezed

RiverpodではAPIから取得するデータのモデルを定義する必要があり、このモデルによってAPIのレスポンスをDartクラスインスタンスに変換します。

クラス定義で面倒なコンストラクタやcopyWithの定義をコード生成で楽にしてくれます。
(TypeScriptでの開発に比べてDartはコード生成で頑張る場面が多いように感じます)

Fastlane

iOSの証明書管理・β版/ストアリリースを自動化するためのツールです。

https://fastlane.tools/

業務では各チームメンバが証明書を管理しなくて良くなるfastlane matchが魅力的で採用しました。

今回は小規模な個人開発でCIも組んでいないためmatchは使用しませんでしたが、fastlaneのアクションに任せたおかげでXCodeの設定をいじる機会が減ったことやTestFlight/AppStoreへの審査提出とリリースをCLIからの操作で完結させられるのは不慣れな自分にとっては非常に役立ちました。

TestFlight

AppStoreにリリースする前にβ版リリースを行うためのツールです。

https://developer.apple.com/jp/testflight/

TestFlightではパブリックリンクというリンクを発行し、ストアを介さずにアプリを配布することができます。
今回はこのパブリックリンクを友人に配布してβ版を遊んでもらいました。

ストアに出してからバグが見つかると消すことができない低レビューがついてしまうため、ストアに出さずにフィードバックを得るために有用です。インストールしたβ版アプリ使用中にはスクリーンショットを撮ることで発生したバグを画像付きで報告できる機能など、フィードバックを得るための機能も追加されています。

工夫したところ

β版リリースを行って遊べるものになっているか確かめた

AppStoreにリリースを行う前にTestFlightによるβ版リリースを行いました。

今回は不特定多数のテストユーザーを募るのではなく、ウミガメのスープのルールを知っている友人にSNSでばら撒きインストールして遊んでもらう形式を取りました。
使いづらい点やバグを見つけて指摘してもらうのが目的でしたが、「すごい」と言ってもらえてモチベーションが上がり、早くストアリリースしたくなったのが一番良い効果でした。

反面、実際にインストールまでしてくれた人数は想定より少なかったです。パブリックリンクを掲載して「このリンクを踏めば遊べるよ」という旨の告知をしたのですが、TestFlightのインストール => TestFlight経由でβ版アプリのインストールが開発者ではない人には一般的ではないことから、もう少し丁寧な説明が必要だったかなと思いました。

最低限の機能でリリースした

大体の機能ができてきたところで飽きて頓挫する匂いがしてきた ユーザーのリアクションを見てから必要な機能を見極めたかったため「好きな問題を選択して」「問題を解くことができる」という最低限の機能ができた段階でリリースを行いました。

本当は実装してから出そうかなと思ってたが辞めた機能がたくさんありますが、全部作ろうとしてリリースまで辿り着かないよりはマシかな...というところでいろんな機能を切りました(今では実装されているものもあります)。

  • 遊び方のページを作る
  • 質問や解答するためにライフを消費させることで無限に質問できなくさせる
  • 解答済の問題を記録するようにする
  • 5問以上遊んでくれたユーザーにレビュー依頼を行う

マネタイズ

有料のOpenAI APIを使用するため、無料でプレイできるようにしてしまうと遊んでもらうほど赤字になってしまいます。

マネタイズとしては👇が考えられるでしょうか。

  • アプリ自体を有料にする
  • 広告収入
  • 広告オフや追加で遊べる問題などの追加要素を実装する

当初はβ版リリースを遊んでもらった結果を鑑みて有料アプリにしないと採算が取れないと考えていたのですが、幸運なことにアプリの開発途中にGPT4o-miniが登場しました。

https://openai.com/ja-JP/api/pricing/

GPT4oが$2.50/1M入力トークンに対してGPT4o-miniは$0.150/1M入力トークンと10分の1以下の価格で利用することができます。
1問遊ぶための問題文と解答分のペアをスクリプトとして入力しても0.0375円くらいで、これならたまに出るリワード広告だけでも十分にペイできそうな金額になりました。

もちろんGPT4oの方が解答の精度は高いのですが、お金稼ぎが目的のアプリではない + 有料で少し回答の精度が高いよりは無料で遊べる方が多くの人に遊んでもらえそうというところでGPT4o-miniの採用を決めました。

使用しているSDKは4o-miniに対応していませんでしたが「使わせてよ」とPRを出したらすぐにマージしてくれました、ありがたい!
https://github.com/redevrx/chat_gpt_sdk/pull/119

苦労したところ

モバイルアプリ特有の概念の多さ

サポートするデバイス・サポートするOS・サポートする画面の向きなどWebアプリとは少し違った考えること、またXCodeのどこをいじればその設定を変更できるのかなど逐一調べるのに少し時間がかかりました。

XCodeの設定を変えたことでリリースされるアプリの動作が具体的にどう変わっているかを即座に判断できないのも困ったポイントです。
例えばスマホ版だけ作ろうとしていたため「Supported Destinations」でiPhoneだけを対象にした(iPadではインストールできなくなるはず)と思っていたのですが、リリースしてみると同僚から「iPadだと表示めちゃくちゃ崩れますよ」と教えてもらってiPadでもインストールできるようになっていることに気付く...などという問題も起きました。

また修正したい箇所が出た時に修正 => ビルド => 審査 => リリースという流れを踏まないといけないのはやはり少し面倒で、バグを埋め込んでしまった際には早く審査してくれと祈ることしかできませんでした。

審査は昔よりは早くなっているそうですが、初回は2日ほど・アップデートは1日ほど時間がかかるようでした。また、土日は審査が全く進まないのでAppleの人も休んでいるようです。

オリジナルの問題を考えること

問題を作るのは想像以上に大変で、当初は50問実装するつもりでしたが縮小に縮小を重ねて15問での初回リリースになりました...。

出題者ができるなら問題も考えられるだろう、とChatGPTと壁打ちして問題を作ろうとしたのですがなかなかうまく行きませんでした。


3連クソ問題

また、今回のアプリでは問題と解答にドット絵風の画像をつけてビジュアル的にも楽しめるようにしようと思いました。DALL·E3で画像を作っていたのですが、画像生成についてはコンテキストを保持することができないようです。
どういうことかというと1つ前の画像が惜しい感じでも「この画像のこの部分をこうして!」という注文はできず、入力したプロンプトに応じて新たに画像を生成してくれるのです。

問題と他の問題の画像、または問題と解答の画像の雰囲気が違いすぎても違和感があるため平仄を合わせるため少しずつプロンプトを変えながらリトライしました。

まとめ

今までWeb専業でしたが今回はFlutterでスマホアプリを作ってみました。

今後もWebアプリ制作と同じ勢いでコミットするかはさておき、今後何か作りたくなった時にスマホアプリという選択肢が自分の中にできたのがとても大きい気がします。

また普段業務で作っているアプリはドメイン上リアルの友達に見せづらく、今回自分が作ったものをリアルの友達に見せてすごいと言ってもらえたのが想像以上に嬉しかったです。AppStoreに掲載するための文言を考えたりアプリの審査を受けたりと慣れない作業が多かったですが、自分が作ったアプリを友達が端末にインストールしてくれるのはなかなか感動ものです。

この記事を読んだみなさんも、インストールして遊んでくれると嬉しいです!

PrAha

Discussion