「COZY CAT CAFE」は、お客さんの注文を見て、3種類の飲み物から同じものを選ぶ60秒ゲームです。ルールを聞くと、とても簡単に思えるはずです。実際、最初の正解までは数秒で到達できます。けれど私たちが時間をかけたのは、その正解を「作業」にせず、自然にもう一杯へ進みたくなる流れを作ることでした。
短いゲームでは、ルールの数より「見る・決める・触る・喜ぶ」が途切れないことを大切にします。
この記事では、注文の状態設計、同じ注文を連続させない抽選、タップ入力の扱い、5連続正解から始まる8秒フィーバー、そしてかわいさを情報として機能させる方法を解説します。猫のゲームですが、中身は差分時間、乱数、状態遷移、フィードバックの優先順位まで考えた、小さなリアルタイムシステムです。
最初の3秒で一周できるループを作る
遊びの最小単位は、「注文を見る」「候補を比べる」「ひとつ押す」「結果を受け取る」の4段階です。説明を読まなくても、吹き出しのカップと下に並ぶカップが同じ形・色を持っていれば、するべきことを推測できます。
重要なのは、正解後に長い演出を挟まないことです。コインが増え、猫が喜び、短い音が鳴った直後には、次の注文が目へ入ります。前の報酬を味わいながら、次の判断が始まっている状態です。この重なりが、60秒を一続きの体験へ変えます。

注文、比較、タップ、報酬を円環にし、各段階の待ち時間を短くそろえました。
注文をひとつの状態として表す
画面に見えるお客さん、吹き出し、飲み物ボタンをそれぞれ独立して更新すると、表示と正解データが食い違う危険があります。そこで、現在の注文をひとつのオブジェクトにまとめ、その値から見た目を描画します。
type DrinkId = "coffee" | "milk" | "tea";
type CafePhase = "ready" | "serving" | "paused" | "result";
type CafeState = {
phase: CafePhase;
order: DrinkId;
orderRemaining: number;
orderDuration: number;
coins: number;
combo: number;
feverRemaining: number;
};実装で使う飲み物IDは coffee、milk、tea の3つです。orderRemaining は今の注文を待てる残り秒数、orderDuration はゲージ全体の長さです。ここでは一つひとつの値に役割があり、アニメーションの途中経過は保存しません。
場面は phase で限定します。準備画面では飲み物を押しても採点せず、ポーズ中は残り時間とフィーバー時間の両方を止め、結果画面では再挑戦だけを受け付けます。「今この入力は有効か」を最初に判定することで、二重採点や終了後のコイン増加を防ぎます。
ランダム注文を「公平に見える乱数」にする
完全な一様乱数でも、同じ飲み物が何回も続くことはあります。確率としては正しくても、3択ゲームでは画面を見ずに同じボタンを押せてしまいます。そこで現在の実装は、直前の注文を候補から外し、残った2種類から次を選びます。毎回必ず比較し直す必要を作りながら、固定順にはしない方法です。
const drinks: DrinkId[] = ["coffee", "milk", "tea"];
const chooseNextDrink = (previous: DrinkId, random = Math.random) => {
// 直前の注文を除き、残る2択からランダムに選びます。
const choices = drinks.filter((drink) => drink !== previous);
return choices[Math.floor(random() * choices.length)] ?? "coffee";
};抽選を関数へ分け、乱数関数を引数で受け取れる形にすると、テストでは random を固定できます。配列の先頭と末尾が選ばれる境界値や、どの注文のあとにも同じ注文が返らないことを毎回同じ条件で確かめられます。
見た目の差も公平さの一部です。3種類は色だけでなく、カップの輪郭、トッピング、湯気の形を変えます。色覚の違いがあっても「緑だからお茶」だけに頼らず、「背の低い丸いカップ」「背の高いクリーム付きグラス」のように形で区別できます。
タップを早くしつつ誤操作を増やさない
飲み物の選択肢は、画像そのものではなく意味を持つ button として作ります。これによりキーボードでフォーカスでき、EnterやSpaceでも決定できます。見た目のカップより押せる領域を広くし、隣のボタンとは十分な間隔を取ります。
ブラウザの button は、マウスクリックとタップのどちらでも同じ click イベントを発生させます。ゲーム側は入力機器を判別せず、選ばれた飲み物IDだけを serve へ渡します。さらに1・2・3キーも同じ関数へ接続するため、採点処理を入力方法ごとに複製しません。
const serve = (selected: DrinkId) => {
if (state.phase !== "serving") return;
const isCorrect = selected === state.order;
applyResult(isCorrect);
createNextOrder();
renderHud();
};次の注文はすぐ表示しますが、猫の成功・失敗アニメーションは約0.34秒残します。前の結果を味わいながら次の比較を始められるため、操作を停止させずに違いを認識できます。不正解でも長い停止や画面全体の赤い点滅は使いません。猫が小さく揺れ、コンボが途切れ、低い音が一度鳴れば十分です。
5連続正解を8秒フィーバーへ変える
正解するたびにコンボが1増え、5へ到達すると8秒のフィーバーが始まります。フィーバー中は獲得コインが2倍になり、背景の明るさ、効果音の音域、カップの残像が少しずつ華やかになります。目的は大当たりの偶然ではなく、連続して正しく読めた技術を短い祝祭へ変えることです。

正解の積み重ねを光量と密度で見せ、最後に短い高得点時間へ接続します。
フィーバーの残り時間は、フレーム数を1ずつ減らすのではなく、前回描画からの経過秒 delta を feverRemaining から引いて計算します。端末の描画回数が違っても、8秒という実時間が伸び縮みしにくくなります。ポーズ中はゲーム更新そのものを止めるため、残り時間もその値のまま保持されます。
報酬は通常時1コイン、フィーバー中2コインと単純に計算します。画面へ出す演出と得点計算を分離すれば、光を減らす設定でもコインは同じです。開始条件を「コンボがちょうど5になり、現在フィーバー中ではないとき」に限定しているため、同じ連続成功中に無限延長は起こりません。一度失敗してコンボを組み直せば、次のフィーバーを狙えます。
かわいさを飾りではなく情報にする
猫の表情は世界観のためだけではありません。注文受付中は視線をカップへ向け、正解時は耳としっぽが上がり、不正解時は一瞬だけ困った顔になります。文章を読まなくても、結果が伝わる第二の表示です。コイン数、色、音、表情のどれか一つを見落としても、ほかで補えます。
アニメーションの優先順位も決めました。最優先は選んだカップの反応、次が注文したお客さん、最後が背景の飾りです。全要素が同時に大きく動くと、何を見ればよいか分からなくなります。背景の植物や湯気はゆっくり、採点に関係するものは短くはっきり動かします。
音は正解、不正解、フィーバー開始で高さと長さを分けますが、音を消しても遊べるよう視覚反応を必ず残します。prefers-reduced-motion が有効な場合は、カップの移動距離や紙吹雪を減らし、輪郭の発光と数値の更新を中心にします。
かわいい反応は、正解をほめると同時に、次に見る場所を案内します。
難易度を「速さ」だけで上げない
反射神経だけを難しくすると、ゆっくり考える人が参加しにくくなります。COZY CAT CAFEでは注文ごとの待ち時間を開始時4.2秒にし、経過に合わせて最短2.2秒まで少しずつ縮めます。突然半分になるのではなく、60秒を通して毎秒0.028秒ずつ短くするため、慣れと圧力が一緒に進みます。時間切れではコンボとフィーバーが切れますが、ゲーム全体はそのまま続きます。
難しさは、注文を待てる秒数で調整します。フィーバー中でも注文ルールと制限時間は変えず、報酬と演出だけを強くします。候補は常に3つで、途中から新しい飲み物を突然追加しません。学んだ規則が最後まで有効だから、上達を感じられます。
テストでは、平均コインだけでなく次を確認しました。
- 初回プレイで説明なしに1杯以上正解できるか
- 3種類のうち特定の飲み物だけ正答率が低くないか
- 誤タップ直後にもう一度押したくなるか、やめたくなるか
- 5コンボへ到達する割合と、到達までの秒数
- フィーバー中の点滅や音量が強すぎないか
- 片手のスマートフォン操作とキーボード操作の両方で完走できるか
セーブするのは思い出せる記録だけ
ゲーム終了時には、その回のコインとベスト記録を表示します。永続保存するのはベストコインなどの小さなデータだけです。現在の注文やフィーバー残り時間は一時的な状態なので、再読込をまたいで復元しません。
保存先には親サイトのセーブブリッジを使います。ゲームをiframe内のLocal Storageへ強く結びつけず、親サイトがゲームIDとデータ形式を管理します。将来ゲームだけを別のPagesプロジェクトへ移しても、同じ契約でセーブを受け渡せる設計です。受け取った値は型と範囲を確認し、負数や極端に大きい値をそのまま表示しないようにします。
完成したゲームの規則は、注文を見る、3つから選ぶ、5回続ける、8秒楽しむ、という短い言葉で説明できます。その背後で状態と演出を分け、乱数を制御し、入力を一度だけ処理し、異なる感覚へ同じ結果を返しています。単純さを守るために、内部は丁寧に作る必要があります。
COZY CAT CAFEで目指した中毒性は、止め時を奪う仕掛けではありません。「あと一杯なら、もっと上手に出せそう」と自分の成長を予想できることです。次の成功が近く、失敗からもすぐ戻れ、短い祝祭が待っている。その小さな期待の連鎖が、やさしいカフェの60秒を何度も開きたくなる時間へ変えました。

