ChatGPTで作ったブラウザゲームにランキング追加|Supabase設定を詳しく解説

前回、ChatGPT WorkとCodexを使って、45秒で遊べるブラウザゲーム「玉ねぎ劇場」を作りました。

最初は「AIでゲームまで作れるんだ!」というだけでも十分楽しかったのですが、何度か遊んでいると、だんだん欲が出てきます。

「自分の最高得点だけじゃなく、ほかの人のスコアも見られたら面白そう」

そこで今回は、オンラインランキング機能を追加してみました。

ランキングの保存先として使ったのが、データベースなどを利用できる外部サービスのSupabaseです。

正直なところ、最初は「データベース? Supabase? 難しそう……」と思いました。

ところが、今回もChatGPT Workに画面を見せながらサポートしてもらい、言われたとおりに一つずつ設定していくと、ちゃんとランキングまで動かすことができました。

Workすごい……!

さらに、ランキングで競えるようになると、今度は「プレイヤーによって運の差が大きすぎない方がいいよね」という問題も出てきます。

そこでランキング追加とあわせて、ゲーム性や公平性についてもいくつか調整しました。

この記事では、Supabaseのアカウント作成からランキング用データベースの設定、ゲームとの接続、公開までの流れを、実際にやってみた経験をもとに紹介します。

前回作ったゲームを少しずつ育てていく過程も含めて、「AIと一緒ならこんなこともできるんだ」という一例として楽しんでもらえればと嬉しいです♪

ランキング付きのゲームはこちら→ https://demo.ai-blog-labo.com/onion-theater/

前回のゲームを作成した記事はこちらです。

この記事でわかること

  • ChatGPTで作ったブラウザゲームにオンラインランキングを付ける流れ
  • Supabaseのアカウントとプロジェクトを作成する方法
  • ランキング用テーブルを作る考え方
  • RLSなど、公開前に確認したいSupabaseの設定
  • ゲームとSupabaseを接続する方法
  • ランキング追加にあわせて改良したゲーム内容
  • 完成したゲームをサーバーへ公開する流れ

それでは詳しく見ていきましょう。


目次

前回作った「玉ねぎ劇場」をランキング対応にアップデート

前回作ったのは、「玉ねぎ劇場」という45秒のミニゲームです。

舞台の上をオニヨンヌというキャラクターが左右に移動し、上から落ちてくる玉ねぎを拾います。

現在のゲームでは、

  • 45秒間プレイ
  • つなげるとコンボ
  • 拍手が起きたらお辞儀
  • PC・スマホ両対応

というルールになっています。

実際の公開版でも、45秒の制限時間、お辞儀操作、PC・スマホ両対応を確認できます。

前回の記事では、ChatGPTでゲームのルールを相談し、Codexで制作、何度も遊びながら修正していくところまで紹介しました。

今回はその続きです。

ゲーム自体ができると、次に欲しくなったのがランキングでした。

自己ベストだけならブラウザの端末内に記録する方法でも実現できます。

ただ、

「みんなの最高得点を表示したい」

となると、各プレイヤーのスコアを共通の場所へ保存する必要があります。

そこでChatGPT Workに相談したところ、今回はSupabaseを使う方法で進めることになりました。


ランキングの保存先にSupabaseを使うことに

Supabaseは、PostgreSQLをベースとしたデータベースをはじめ、認証、ストレージ、APIなどを利用できるサービスです。

今回必要なのは、その中でも主にデータベースとAPIです。

ゲーム終了後に、

  1. プレイヤーが名前を入力する
  2. 名前とスコアをSupabaseへ送信する
  3. Supabaseに保存されたスコアを読み込む
  4. 高得点順にランキング表示する

という仕組みにします。

Supabaseでは、作成したテーブルをAPI経由で扱うことができます。テーブルはダッシュボードのTable Editorから作成することも、SQL EditorからSQLを実行して作成することも可能です。

今回はゲーム利用者自身にはSupabaseへのログインを求めません。

プレイヤー側から見ると、

ゲームを遊ぶ → 名前を入力 → スコア登録

だけです。

Supabaseのアカウントを作るのは、ゲームを管理する私だけです。


Supabaseのアカウントを作成する

まずSupabaseの公式サイトを開き、アカウントを作成します。

登録後、管理画面から新しいプロジェクトを作ります。

1.Supabaseへ登録する

Supabaseの公式サイトを開き、サインインまたは新規登録へ進みます。

登録方法は画面の案内に従って進めれば大丈夫です。

ここで作成するアカウントは、ゲーム利用者用ではなく、ゲームのデータベースを管理する自分用です。

ゲームを遊ぶ人にSupabaseアカウントを作ってもらう必要はありません。

2.新しいプロジェクトを作成する

ログイン後、新しいProjectを作成します。まず+ New organization をクリック。Nameを入れます。

Plan:必ず Free を選択します。

Create organizationをクリックして次の画面にプロジェクト名などを入力します。

プロジェクト名は自分で分かりやすいものにしておきます。

たとえば今回なら、

onion-theater

のような名前でもよいでしょう。

プロジェクト作成時には、所属Organization、プロジェクト名、データベース用パスワード、リージョンなどの設定画面が表示される場合があります。

管理画面は更新されることがあるため、実際の表示に従って進めてください。

データベースパスワードは、あとで必要になる可能性があるので安全な場所へ保管しておきます。

「Automatically expose new tables」のチェックは外してください。画面にも「無効化を推奨」と書かれています。

ランキングを安全に作るため、Securityは次の状態がおすすめです。

  • Enable Data API:チェックしたまま
  • Automatically expose new tables:チェックを外す
  • Enable automatic RLS:チェックを入れる

RLSは、誰がランキングを閲覧・登録できるかを制限するセキュリティ機能です。あとでランキング用の許可設定をこちらから指定します。

その状態で Create new project を押します。


Securityの部分を以下に変更して、Create new projectをクリックします。

次は、プレイヤーがログイン操作なしでランキング登録できるよう「匿名認証」を有効にします。

左側メニューから、

Authentication → Sign In / Providers

と進み、一覧の中にある Anonymous Sign-Ins または Anonymous を開いてください。

そこで、

  • Allow anonymous sign-ins:オン

にして、Saveを押します。

匿名認証は、利用者にメールアドレスやパスワードを入力させず、ブラウザごとに内部IDを発行する機能です。

Confirm emaiについては、ゲームではメール登録を使わないので無効にして構いません。むしろ不要な登録経路を閉じるため、無効がおすすめです。

ランキング用のテーブルを作成する

プロジェクトができたら、次はスコアを保存する場所を作ります。

Supabaseでは、この保存場所をテーブルとして作成します。

テーブルはExcelの表をイメージすると比較的分かりやすいです。

Supabase公式ドキュメントでも、テーブルには「列」と「行」があり、表計算シートに近いイメージから理解できると説明されています。

今回のゲームなら、最低限、

項目内容
id各記録を区別する番号
nameプレイヤー名
score得点
created_at登録日時

のような情報があればランキングを作れます。

実際の列名は、Codexが生成したゲーム側のコードと一致させる必要があります。

SQL Editorから作る場合

左側メニューの SQL Editor を開き、New queryを押してください。表示された入力欄へ、以下を最初から最後までまとめて貼り付けます。

もちろん以下のコードはChatGPT Workが書いてくれるので、コピーして貼り付けるだけです。

-- 玉ねぎ劇場ランキング
create table public.leaderboard (
  id bigint generated always as identity primary key,
  user_id uuid not null unique references auth.users(id) on delete cascade,
  player_name text not null
    check (char_length(trim(player_name)) between 1 and 8),
  score integer not null
    check (score between 0 and 5000),
  max_combo integer not null default 0
    check (max_combo between 0 and 100),
  bows integer not null default 0
    check (bows between 0 and 4),
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

-- セキュリティを有効化
alter table public.leaderboard enable row level security;

-- ランキングは誰でも閲覧可能
create policy "Public leaderboard can be viewed"
on public.leaderboard
for select
to anon, authenticated
using (true);

-- 表への直接書き込みは禁止
revoke all on table public.leaderboard from anon, authenticated;
grant select on table public.leaderboard to anon, authenticated;

-- 安全に自己最高記録だけを登録する関数
create or replace function public.submit_score(
  p_name text,
  p_score integer,
  p_max_combo integer,
  p_bows integer
)
returns void
language plpgsql
security definer
set search_path = public, pg_temp
as $$
declare
  clean_name text := trim(p_name);
begin
  if auth.uid() is null then
    raise exception 'Authentication required';
  end if;

  if char_length(clean_name) < 1 or char_length(clean_name) > 8 then
    raise exception 'Name must be between 1 and 8 characters';
  end if;

  if p_score < 0 or p_score > 5000 then
    raise exception 'Invalid score';
  end if;

  if p_max_combo < 0 or p_max_combo > 100 then
    raise exception 'Invalid combo';
  end if;

  if p_bows < 0 or p_bows > 4 then
    raise exception 'Invalid bow count';
  end if;

  insert into public.leaderboard (
    user_id,
    player_name,
    score,
    max_combo,
    bows
  )
  values (
    auth.uid(),
    clean_name,
    p_score,
    p_max_combo,
    p_bows
  )
  on conflict (user_id)
  do update set
    player_name = excluded.player_name,
    score = excluded.score,
    max_combo = excluded.max_combo,
    bows = excluded.bows,
    updated_at = now()
  where excluded.score > leaderboard.score;
end;
$$;

-- 匿名認証済みプレイヤーだけが登録関数を使用可能
revoke all on function public.submit_score(text, integer, integer, integer)
from public, anon;

grant execute on function public.submit_score(text, integer, integer, integer)
to authenticated;

貼り付けたら、右下または上部の Run を押します。

成功すると通常は、

Success. No rows returned

と表示されます。これは「データがない」というエラーではなく、ランキング表と設定が正常に作られたという意味です。


Supabaseの公開用情報を取得してゲームと接続する

ランキング用のテーブルを作成したら、次はゲームとSupabaseをつなぐための情報を確認します。

ここも私はWorkに教えてもらいながら進めました。

最初に案内されたのは、プロジェクト画面上部にある「Connect」から接続情報を確認する方法です。

必要なのは、次の2つだけです。

  • Project URL
  • Publishable key

Project URLは、

https://○○○○.supabase.co

という形式のURLです。

Publishable keyは、

sb_publishable_...

のような文字列です。

この2つは、今回のようなブラウザゲームからSupabaseへ接続するために使います。

Project Settingsから確認する

Supabaseの左側メニュー下部にある歯車アイコン「Project Settings」を開きます。

そこから、次の2か所を確認しました。

API Keys

「API Keys」を開きます。

ここに表示されている「Publishable key」の右側にあるCopyボタンを押してコピーします。

今回使うのは、ブラウザから利用するための公開用キーです。

Data API

次に「Data API」を開きます。

ここに表示されているProject URL、またはURLをコピーします。

形式は、

https://○○○○.supabase.co

となっています。

この2つがそろえば、ゲームとSupabaseを接続する準備は完了です。

Workへ送ったのはこの2つ

私は次のような形でWorkへ送りました。

Project URL:https://○○○○.supabase.co

Publishable key:sb_publishable_○○○○

すると、Work側でこの情報を使ってランキング機能をゲーム本体へ組み込んでくれました。

ここで少し注意が必要です。

Supabaseの設定画面には、ほかにもいろいろなキーやパスワードが表示されますが、今回Workへ渡したのは上の2つだけです。

次のような情報は送らないようにしました。

  • Secret key
  • service_role
  • Database password
  • Access token

私も最初は、どれを使えばよいのか全く分かりませんでした。

ただ、画面をスクリーンショットで見せながら、

「どれでしょう?」

と聞くだけで、次に開く場所を案内してもらえました。

Supabaseのような外部サービスは、慣れていないと設定画面だけで難しく感じますが、今回のようにWorkに画面を確認してもらいながら進めると、かなり分かりやすかったです。

ゲームにランキング機能を組み込む

Project URLとPublishable keyをWorkへ渡したら、あとはゲーム側へランキング機能を組み込んでもらいました。

ゲーム終了後に、

  • 名前を入力する
  • スコアを登録する
  • みんなのランキングを表示する

という流れになるように修正してもらいます。

プレイヤーがSupabaseへログインする必要はありません。

ゲームを遊ぶ人から見ると、名前を入力して「記録を登録」を押すだけです。

設定が終わったあと、実際にゲームをプレイしてスコアを登録し、ランキングに表示されるか確認しました。

ここまでできると、ただ自分の端末だけで遊ぶゲームから、ほかの人とスコアを比べられるゲームに一気に変わります。

私自身、最初は「ランキング機能なんて難しそう」と思っていましたが、Workに言われるがまま一つずつ進めたら、ちゃんと完成しました。

このときは本当に、Workすごいなと思いました。


ランキングを表示できるか確認する

設定が終わったら、実際にゲームを遊んで確認します。

チェックしたいのは、

  • 名前を登録できる
  • スコアが保存される
  • ページを再読み込みしてもランキングが残る
  • 別の端末からも同じランキングを確認できる
  • 高得点順に表示される
  • 不要なデータ編集ができない

といった点です。

端末内のlocalStorageへ保存する自己ベストとは違い、Supabaseへ保存したランキングは、複数の利用者で共有できます。

「玉ねぎ劇場」でも、結果画面に「みんなのランキング」があり、8文字以内の名前を入力してゲーム記録を登録できるようになりました。

ゲームはこちら↓↓

https://demo.ai-blog-labo.com/onion-theater


ランキング追加にあわせてゲーム自体も改良

ランキングだけ追加して終わりではありませんでした。

実際に競えるようになると、

「ゲームの運によって点数差が大きくなりすぎない方がいい」

という問題が気になってきます。

そこでゲーム性と公平性を高めるため、いくつか仕様を調整しました。

プレイ時間は45秒のまま

30秒では短すぎて物足りなかったため、前回の改良で45秒にしています。

今回も45秒を維持しました。

短時間で繰り返し遊べますが、コンボやお辞儀を狙う時間も確保できます。

コンボは4秒以内

玉ねぎを取ったあと、4秒以内に次の玉ねぎを取ることでコンボが続くようにしました。

これにより、ただ落ちてきた玉ねぎを待つだけではなく、

「次を取りに行く」

という判断が生まれます。

現在のゲーム画面にも、「4秒以内につなげてコンボ」とルールを表示しています。

拍手回数を固定

以前は拍手イベントの発生回数にもランダム性がありました。

しかし、お辞儀成功にはボーナスがあるため、拍手回数までプレイヤーごとに大きく違うと、ランキングの公平性が下がります。

そこで1ゲームにつき拍手4回固定へ変更しました。

ランダム性は残しつつ、得点チャンスの回数自体は同じになります。

玉ねぎの出方も調整

玉ねぎの出現にも偏りが出すぎないよう調整しました。

完全なランダムにすると、

「今回は取りやすい場所ばかり」

「今回は左右に振られすぎて無理」

といった差が大きくなることがあります。

そこで、取得が不可能に近い配置が続きにくいように調整しました。

ランキングを付けることで、こうしたゲームバランスの問題に初めて気付いたのも面白かったところです。

ラスト10秒だけ少し高速化

最後まで同じテンポでは単調になりやすいため、残り10秒になると少しだけゲーム速度を上げています。

急激に難しくするのではなく、約8%程度の高速化に抑えました。

最後に少し慌ただしくなることで、45秒の中にも小さな盛り上がりができます。

カーテンコールも追加

ゲーム終了時には、ただスコアを表示するのではなく、劇場らしく「CURTAIN CALL」の結果画面へ移ります。

通常の玉ねぎ、大きな玉ねぎ、お辞儀成功、間違った野菜など、その公演の結果が表示されます。公開版でもこれらの結果項目を確認できます。

ゲームの世界観としても、この演出はかなり気に入っています。


完成版はAIブログラボのサブドメインへ公開

前回はNetlifyを使いましたが、今回のアップデート版は、AIブログラボのサブドメインへ公開しました。

玉ねぎ劇場を遊んでみる

ブラウザゲームなので、アプリをインストールする必要はありません。

PCではキーボード、スマートフォンでは画面下のボタンで遊べます。

ランキングも付いたので、よかったら遊んでみてください。


Supabaseを使ってみた感想

Supabaseという名前だけを見ると、正直かなり難しそうでした。

データベース、API、RLS、キー……。

普段触らない言葉が次々出てきます。

それでも今回はWorkに、

「この画面になりました」

「次は何を設定しますか?」

と確認しながら、言われたとおり一つずつ進めていきました。

結果として、オンラインランキングまでちゃんと動きました。

ここは今回かなり「Workすごい!」と感じた部分です。

以前なら、データベースを使う時点で「これは私には無理かな」と諦めていたかもしれません。

もちろん、AIの指示だからと何も確認せず設定するのはおすすめしません。

特に外部公開するデータベースでは、RLSやAPIキーの扱いなど、最低限のセキュリティは理解しておいた方が安心です。

それでも、

分からないところをその場で聞きながら進められる

というだけで、以前よりハードルがかなり下がったと感じました。


今後さらに改良するなら

今回で、最初の「玉ねぎを拾うだけ」のゲームからかなり進化しました。

今後やるとしたら、

  • 自己ベストをさらに分かりやすく表示
  • ランキング表示の改善
  • 不正スコア対策
  • 効果音やBGMで演出する
  • ゲームバランスの追加調整
  • 新しい舞台

なども面白そうです。

ただ、45秒だけ遊べる素朴なゲームだからこその良さもあるので機能を増やしすぎる必要もないと思っています。


まとめ

今回は、ChatGPT WorkとCodexで作ったブラウザゲーム「玉ねぎ劇場」に、Supabaseを使ったオンラインランキングを追加しました。

最初は少しハードルが高そうに感じたSupabaseも、Workにサポートしてもらいながら設定することで、実際にランキング機能まで完成させることができました。

今回のポイントまとめ

  • Supabaseを使ってオンラインランキングを実装
  • プレイヤー側のSupabaseログインは不要
  • 名前とゲーム記録を保存
  • ランキング追加にあわせてゲームの公平性も調整
  • 拍手回数や玉ねぎ配置などランダム性を見直した
  • 45秒、4秒コンボ、ラスト10秒高速化などゲーム性も改良
  • 完成版はAIブログラボのサブドメインへ公開

最初は小さなブラウザゲームだったのに、遊んでいるうちに「ランキングも付けたい」「もう少し公平にしたい」と、次々やりたいことが出てきました。

AIを使った制作は、最初から完璧なものを作るというより、実際に使いながら少しずつ育てていくのが面白いのかもしれません。

ゲーム制作に興味がある方は、まずは簡単なミニゲームから作ってみてはいかがでしょうか。

作ったあとに「次はこれを付けたい」と考える時間も、結構楽しいですよ。

よかったらシェアしてね!

これからブログを始める方はこちら
Xserverのクイックスタートなら、WordPressブログを最短10分で始められます。

目次