はじめに
皆様、こんにちは。『ねむりのガチャ』アプリ開発記の第7回です。
前回は、フロントエンドとデータベース(D1)を安全に繋ぐAPIを構築し、睡眠ポイントが確実に保存される仕組みを完成させました。ここまでの作業で、アプリとしての基礎的な「骨格」はすべて整ったことになります。
今回はいよいよ、このアプリの最大のコンセプトであり、ユーザーのモチベーションを爆発させる「お楽しみ要素」——そう、「ガチャシステム」の実装に入ります。貯まった睡眠ポイントを消費してランダムなアイテムを獲得し、図鑑を埋めていく処理の流れを詳しく解説します。
ガチャロジックの設計:ランダム性とワクワク感
「ガチャを回す」という行為の裏側には、確率(ランダム性)を制御するロジックが存在します。
今回はMVP(最小限の実行可能な製品)として、まずは数種類のオリジナル睡眠アイテム(「ふかふかの枕」「星空のアイマスク」「癒やしのハーブティー」など)をデータとして定義しました。
ガチャのボタンが押されたとき、プログラム内部では JavaScript の Math.random() 関数を使用して乱数を生成し、あらかじめ設定した確率に基づいて排出されるアイテムを決定します。
このとき、単に文字だけで「〇〇が出ました」と表示するのではなく、Reactの状態管理(ステート)を活用して、画面上でカプセルが揺れたり、光の演出が入ったりするような「タメ」の時間を数秒間作りました。このわずかな演出があるかないかで、ユーザーの「何が出るかな?」というワクワク感は劇的に変わります。
バックエンドへの安全なデータ保存
アイテムが決定したら、その結果をデータベースに保存する必要があります。ここで前回構築したAPI(/api/user)が再び大活躍します。
ガチャを1回引くごとに、フロントエンドからバックエンドに対して以下のような通信(更新リクエスト)を行います。
現在の所持ポイントから、ガチャの消費ポイント分(例:100ポイント)をマイナスする。
データベースの ownedItemIds(所持アイテム一覧)の配列に、新しく引いたアイテムのIDを追加する。
バックエンド(Cloudflare Pages Functions)は、FirebaseのIDトークンでユーザー本人であることを確認した上で、Cloudflare D1に対して UPDATE のSQL文を発行し、データを書き換えます。ポイントの消費とアイテムの付与を同時に行うことで、データの不整合(ポイントだけ減ってアイテムがもらえなかった、など)を防いでいます。
コレクション(図鑑)機能の実装
ガチャで手に入れたアイテムは、画面下部の「コレクション」エリアに一覧表示されるように実装しました。
Reactの map() メソッドを使用し、データベースから読み込んだ ownedItemIds の配列データをループ処理して、アイテムのアイコンを画面に並べていきます。未取得のアイテムはシルエット(グレーアウト)表示にしておくことで、「全部集めたい!」というユーザーのコンプリート欲を刺激するUIに仕上げました。毎日の睡眠が、そのままコレクションを豊かにする喜びに直結する瞬間です。
まとめ
今回は、アプリのコア体験である「ガチャシステム」の実装と、ポイント消費・アイテム獲得のデータフローについてお話ししました。
ゲーミフィケーションの要素が組み込まれたことで、ただの記録ツールだったアプリが、立派な「遊べるサービス」へと進化しました。しかし、機能が増えれば増えるほど、予期せぬ不具合(バグ)も顔を出してきます。
次回【第8回】は、開発終盤で直面した「Reactのステート管理の罠」や、別プロジェクトでの知見である「見えないキャッシュとの戦い」など、リアルなデバッグの苦労話をお届けします。
【編集後記】
ガチャの実装中、テストのために自分で大量の睡眠ポイントを付与して無限にガチャを回し続けていたのですが、自分で作った確率ロジックにもかかわらず「レアアイテムが全然出ない!」とムキになってしまいました(笑)。
確率のバランス調整は非常に奥が深く、厳しすぎるとユーザーの心が折れ、甘すぎるとすぐに飽きられてしまいます。このあたりの「ゲームバランスの調整」は、エンジニアリングとはまた違った面白さと難しさがありました。コレクションが埋まっていく画面を見ると、やはり達成感がありますね!