Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Ver.3系の「イベントを1つずつこなす診断ゲーム」を廃止し、「60秒で刺激をさばき続ける高速リズムゲーム」 そのものに作り替えた。診断色を消し、ゲーム自体がドパガキ的な体験になることを最優先している。 Ver.4.1ではゲーム構造は変更せず、実機プレイで見つかったスコアバランス・お題の不可能状態・ テンポ・タイプ判定の甘さを修正した(詳細は「Ver.4.1でのバランス調整」を参照)。 Ver.4.2でもゲーム構造は維持したまま、「○回押せ」を停止確認方式に作り直し、 「押したい・待てない・止まれない」というドパガキの衝動をそのままゲーム化した6種の新お題を追加した (詳細は「Ver.4.2で追加した内容」を参照)。 Ver.4.3では新お題は最小限(高速仕分けのみ)に留め、iPhone実機プレイで見つかった 「正しく操作しても失敗するHOLDの不具合」と「初見で何をすればいいか分からないお題」を 重点的に修正した(詳細は「Ver.4.3で修正した内容」を参照)。README 전문 보기 ↗
Ver.3系の「イベントを1つずつこなす診断ゲーム」を廃止し、「60秒で刺激をさばき続ける高速リズムゲーム」 そのものに作り替えた。診断色を消し、ゲーム自体がドパガキ的な体験になることを最優先している。
Ver.4.1ではゲーム構造は変更せず、実機プレイで見つかったスコアバランス・お題の不可能状態・ テンポ・タイプ判定の甘さを修正した(詳細は「Ver.4.1でのバランス調整」を参照)。
Ver.4.2でもゲーム構造は維持したまま、「○回押せ」を停止確認方式に作り直し、 「押したい・待てない・止まれない」というドパガキの衝動をそのままゲーム化した6種の新お題を追加した (詳細は「Ver.4.2で追加した内容」を参照)。
Ver.4.3では新お題は最小限(高速仕分けのみ)に留め、iPhone実機プレイで見つかった 「正しく操作しても失敗するHOLDの不具合」と「初見で何をすればいいか分からないお題」を 重点的に修正した(詳細は「Ver.4.3で修正した内容」を参照)。
Ver.4.4ではゲーム内容・スコアバランスは変更せず、「上手くプレイするほどゲームそのものが 刺激過多になっていく」という演出面を大幅強化した。段階的に盛り上がるBGM、連続正解の 気持ちよさの可視化、100%到達時の静寂→爆発のコントラスト、連打→STOPの緑/赤UI化などを 実装した(詳細は「Ver.4.4で強化した演出」を参照)。
Ver.4.5では60秒ラッシュ・ドパガキ度・スコアバランス・既存お題・結果画面・タイプ判定は 維持したまま、「次に何が来るか分からない、刺激まみれの60秒」をテーマに、(1) 連打→STOPを 「信号連打」という独立したゲームへ再設計、(2) BGM/SEの刺激をさらに強化(COMBO段階別レイヤー・ 正解音の音階上昇・残り20秒からの予告・FINAL DOPA RUSH強化・100%爆発の豪華化)、 (3) 新お題を7種類追加、(4) 出題プールの直近重複抑制を強化してプレイごとの展開をより ランダムにした(詳細は「Ver.4.5で追加・強化した内容」を参照)。
Ver.4.6では新お題の追加はせず、ゲーム構造・27種のお題・スコア・BGM・COMBO・OVERDRIVEは 維持したまま、「難しいのはOK。意味不明と理不尽はNG。」をテーマに、(1) 初見で意味が 伝わりにくかったお題(信号ゲーム・高速仕分け・信号連打・ショート動画)のUIを再設計、 (2) 「成功したはずなのにMISSになる」誤判定の根本原因(外側の汎用タイムアウトが進捗を 無視して発火するレース)を6問について構造的に修正、(3) FINAL DOPA RUSHと3-2-1カウントダウンが お題の中央領域を覆っていた表示バグを修正した(詳細は「Ver.4.6で修正した内容」を参照)。
Ver.4.7では通常問題のロジック・スコア計算・OVERDRIVE発動条件・正誤判定・問題制限時間は
一切変更せず、DOPA OVERDRIVE(100%突破)を完全にプレゼンテーション層として「黄金の非常事態」に
作り替えた。100%→101%突破を「上限を破壊した」演出に強化し、黄金サイレン・黄金パーティクル・
専用BGM/SEを追加、120%到達に専用のクライマックス演出と黄金結果カードを用意した
(詳細は「Ver.4.7で追加した黄金DOPA OVERDRIVE演出」を参照)。演出はPlayScreenと
?preview=overdrive確認画面(Vercel Preview限定)の両方で同じコンポーネントを共有している。
タイトル → プレイ(固定60秒・お題が絶え間なく切り替わる) → 結果画面 → リトライ。
npm install
npm run dev
表示されたURL(デフォルト http://localhost:5173/)をブラウザ(スマホ幅推奨・DevToolsのデバイスモードでもOK)で開く。
本番ビルドは npm run build(dist/ に出力)、npm run preview でビルド後の確認ができる。
A.色選択/B.仲間外れ/C.最大数字/D.最小数字/E.違うもの/F.同じもの/G.多い方/H.大きい方/
I.簡単な計算/J.○回押せ/K.長押し/L.押すな/M.緑になったら押せ(信号ゲーム)/N.SKIPが出たら押せ/
O.信号連打(Ver.4.5で再設計)/P.98〜102でSTOP/Q.通知を消せ/R.変わったやつを押せ/S.高速仕分け、
T.1→4の順に押せ/U.ターゲットを探せ/V.緑で離せ/W.ショート動画スワイプ/X.文字の色(ストループ課題)/
Y.光ったやつ/Z.通知ラッシュ(Ver.4.5で追加)、を実装。
方向のみを指示する旧「スワイプ」(J)はVer.4.3で通常プールから除外し、代わりに高速仕分け(S)を
出題している(コードはSwipeQuestion.tsxとして残存、src/questions/index.tsには登録済みだが
difficultyConfig.tsのどのフェーズプールにも含まれないため出題されない)。
難易度フェーズごとに出題候補プールを変え、src/questions/ に1問1ファイルで実装しているため、
新しい問題タイプを追加してもGame本体を編集せずに済む構造にしてある
(src/questions/index.ts に登録するだけ)。
各お題はreaction(認知・反応系)/rapid(高速入力系)/inhibition(止まる・待つ系)/
visual(視覚探索系)/timing(タイミング系)/sorting(仕分け・選別系、Ver.4.5で追加)/
memory(記憶・順序系、Ver.4.5で追加)の7カテゴリいずれかに属し(QuestionModule.category)、
questionPicker.tsが直近2問と同じカテゴリが3連続にならないよう出題を調整する。
「待つ系ばかり3連続」のようなテンポを損なう並びを避け、60秒間ずっと操作感が変化するようにしている。
Ver.4.5では直近3問のタイプ自体もゆるく避ける抑制も追加し(候補が尽きたら通常のプールへ
フォールバックする程度の緩い抑制。完全禁止はしていない)、お題の種類が増えたことで単調な
繰り返しが起きにくいようにした。
反応時間 / その問題のtargetTimeMs の比率で決める
(PERFECT: 35%以内 / GREAT: 60%以内 / GOOD: 100%以内 / それ以外はMISS)。長押し・押すな等
「速さ」で測れない問題は成功/失敗の二値でPERFECT・MISSを直接割り当てるqualitySumRef ÷ answeredCountRef)。Ver.4は累積加算方式だったため出題数(=速さ×時間)
が多いほど正答率に関わらずスコアが積み上がってしまっていたが、平均方式にしたことで出題数を
稼いでもドパガキ度は上がらず、正答率が素直に反映されるようになったACCURACY_CAPS、例:70%未満→75%、90〜94%→99%、95%以上→100%到達可)を
平均値にかけ合わせ、たとえ判定・COMBOで高い値が出ても正答率が低ければ100%に到達できないようにしたsrc/config/scoreConfigV4.ts に集約src/config/overdriveConfig.ts に集約。Ver.4.1では
平均ベースのスコアで100%到達自体が簡単になった分、accuracyThreshold(0.85→0.92)と
reactionRatioThreshold(0.45→0.4)を引き上げ、OVERDRIVEがより高精度プレイ限定になるよう調整したcomputeMinTargetTimeMs を実装し(src/config/timingConfig.ts に集約)、後半の高速化で
HOLDや連打の必要時間より制限時間が短くなり「絶対にクリアできない」状態になるバグを解消したsrc/screens/PlayScreen.tsx)。100%到達/OVERDRIVE突入の瞬間だけは演出のため意図的に一瞬静止するVer.4.1までは指定回数に到達した瞬間に自動で成功していたが、Ver.4.2では
「指定回数まで押す→停止確認時間(700〜900msでランダム)に何も押さなければ成功」に変更した
(src/questions/RepeatTapQuestion.tsx)。
ratioWindowMsという新しい仕組みで、判定比率の分母から停止確認時間を除外している)computeMinTargetTimeMs)、終盤の高速フェーズでも
「押した後の停止確認が完了する前に問題時間が終了する」状態を作らないようにした「勢いで押しすぎる」というドパガキの衝動をそのままゲーム化した、今回の中心的な変更。
すべて1問あたり約1〜2秒前後で完結し、既存ラッシュに自然に混ざるよう実装。判定はVer.4.1と同様、 次のお題の上にオーバーレイ表示され、進行を止めない。
GoWaitQuestion.tsx、inhibition):READY...表示後、0.5〜1.3秒のランダム待機で
GO!に変化。GO前に押すと即MISS、GO後の反応速度をPERFECT/GREAT/GOODで判定SkipWaitQuestion.tsx、inhibition):広告風の「SKIPまで2→1→SKIP」カウントダウン。
SKIP表示前に押すと即MISS、SKIP後の反応速度で判定RapidStopQuestion.tsx、rapid):「連打しろ!!!」で高速連打→0.65〜1.1秒後に
「止まれ!!!」に変化。変化前に最低3〜4回(生成時に必ず物理的に届く回数だけ要求)タップし、
変化後700msタップなしなら成功。変化後に1回でも押すと即MISS。20秒以降のフェーズから出現StopAt100Question.tsx、timing):高速で増える数字を見てタップで停止。
100ちょうどでPERFECT、±2でGREAT、±5でGOOD、それ以外はMISS。数値の増加速度は問題ごとに
わずかにランダム化し、暗記でのタイミング攻略を防止ClearNotificationsQuestion.tsx、visual):赤い通知バッジ(3〜4個)だけを全てタップ。
赤以外を押すと即MISSSpotChangeQuestion.tsx、visual):同じアイコン4つのうち1つが
300〜600ms後に変化。変化前に押すと即MISS、変化後の反応速度で判定ACCURACY_CAPS)・OVERDRIVE条件はそのまま維持。
新お題が増えても「累積問題数」ではなく「プレイ品質」でドパガキ度が決まる思想は壊していない
(検証結果は下記「動作確認結果」を参照)PlayStatsに集計し
(earlyPressCount/overPressCount)、「待てない型」判定にこれらの合計が3件以上でも該当する
経路を追加した(src/config/resultTypesV4.tsのTYPE_THRESHOLDS.impatient.minImpulseEvents)PlayStatsに保持し、犯行記録の候補
(「100で止めろ→117で停止しました」等)としても利用。OVERDRIVEの隠し条件は今回変更していないが、
これらのログは将来の条件拡張にそのまま使える形で保持している実機で「ゲージがかなり溜まっているのに完了直前で問題が終了してMISSになる」ことがあった。
原因:外側の自動失敗タイマーは元々「問題表示(マウント)からの固定時間」で発火していた。
一方、ゲージ完了の判定はrequestAnimationFrame(rAF)のtickだけに頼っていたため、
反応してから指を置くまでの時間が長い場合や、タブの状態・描画負荷でrAFが間引かれた場合に、
「必要時間はとっくに満たしているのに、判定がそれより先に走ってMISSになる」レースが起きていた。
修正(src/questions/HoldPressQuestion.tsx):
requiredMs + completionSafetyMsで引き直し、
問題表示からの反応時間に依存しない構造にしたpointerup/pointercancel(指を離した瞬間)と
外側の安全弁タイマーの両方でも「保持開始からの実経過時間」を直接計算して判定するようにした。
これにより、rAFがどれだけ間引かれても、必要時間を満たしていれば必ず成功が優先されるreactionBufferMs: 450→700ms、safetyMarginMs: 200→300ms)、
requiredMs≒700msの場合で問題全体の最低時間が約1700ms確保されるようにした(timingConfig.ts)GoWaitQuestion.tsx):「READY...→GO!」という文字だけの
切り替えは初見でルールが伝わらなかったため、「緑になったら押せ!」を固定表示し、
中央の丸が赤/グレー→緑に変わる信号機形式に変更。ルールが視覚だけで理解できるようにしたRapidStopQuestion.tsx):常時「連打 → STOPで止まれ」という
固定キャプションを表示するようにした(QuestionShellにsubプロパティを追加)。メイン表示は
「連打!!!」→「STOP!」と変化し、初見でも「今何をすべきか」「次に何が来るか」が分かるStopAt100Question.tsx):「100でSTOP!」だと成功範囲が不明だった
ため、「98〜102でSTOP!」と表示を内部の成功条件(100=PERFECT/99・101=GREAT/98・102=GOOD/
範囲外=MISS)に完全一致させたSkipWaitQuestion.tsx):常時「SKIPが出たら押せ!」を表示するように
変更(以前は「広告」とだけ表示していた)SpotChangeQuestion.tsx):変化前の表示が「よく見て…」
では何のルールか分からなかったため、「変わったら押せ!」に変更し、MISSする前にルールが
分かるようにしたdifficultyConfig.tsの全フェーズプールから外した
(コードは削除せず保持)FoodSortQuestion.tsx):「← 食べ物 それ以外 →」というルールを
常時固定表示し、中央のアイコン1つを見て左右にスワイプで仕分ける。指の動きにアイコンが少し
追従するようにして操作感を出した。方向swipeの代替として全フェーズのプールに組み込んだVer.4.1/4.2で調整したスコアバランス(質スコア平均方式・ACCURACY_CAPS・COMBOボーナス)と
OVERDRIVE発動条件は変更していない。判定オーバーレイによる「即次問題」テンポも維持している。
テーマは「上手くプレイするほど、ゲームそのものが刺激過多になっていく」。ゲーム内容・お題構成・ スコアバランス・OVERDRIVE条件・結果画面は変更していない。
src/utils/audioContext.ts(新規):BGMとSEで共有するAudioContextと、2系統のマスターゲイン
(sfxGain/bgmGain)を管理。ミュートはこの2つを同時に操作して一括ミュートを実現しつつ、
音量は内部的に別管理できるようにしたsrc/utils/bgm.ts(新規):ルックアヘッド方式のステップシーケンサーによる手続き生成BGM。
既存の6フェーズ(0-10/10-20/20-30/30-40/40-50/50-60秒)をそのままBGMの段階として使い、
キック→ハイハット→ベース→追加パーカッション/シンセを段階的に積み上げる。テンポも
ステージが進むごとに滑らかに上昇する(目安:序盤96BPM→終盤158BPM)
AudioContextの生成・resumeはSTART/リトライ
ボタン押下の同期コールバック内で必ず呼ぶ(App.tsxのstartPlay→unlockAudio())。
リトライ時は前回プレイの音声グラフを再利用しつつ、残っている可能性のあるゲイン自動化を
キャンセルしてクリーンな状態にリセットしてから開始する100%到達の瞬間、BGM・SEを一瞬(約300ms)ほぼ無音までダッキングし、静寂の後に金色爆発の
バーストSEと演出を同時に出す。「騒音→静寂→爆発」のコントラストを強めるため、ダッキングは
「下げてすぐ戻す」のではなく「下げて保持し、終わり際に一気に戻す」形にして、静寂区間を
きちんと聞こえるようにしている(duckAudio(), src/utils/audioContext.ts)。
これまでオレンジ/赤という紛らわしい配色だったのを、緑(連打してよい)/赤(止まれ)という
誰でも直感的にわかる信号色に変更した(RapidStopQuestion.tsx)。判定ロジック自体は
Ver.4.3から変更していない。
sfx.comboMilestone)を鳴らし、10問・20問では
「10問連続正解!」のようなバナーを短時間表示するcomboVisualBonus,
useRushGame.ts)10連続以上のCOMBOを切った場合だけ、通常のMISS演出に加えて「怯み」演出を追加した:
BGM/SEを一瞬弱める(duckAudio)、画面を約0.2秒暗転させる、「COMBO BREAK」の代わりに
「15問連続で終了」のように実際の数字を表示する。COMBOが途切れると演出レベルも
自動的に元の段階まで下がるため、「また盛り上げたい」という動機になる。MISS後も
即座に次の問題へ進むテンポは変更していない。
テーマは「次に何が来るか分からない、刺激まみれの60秒」。60秒ラッシュ・ドパガキ度・スコアバランス・ 正答率cap・COMBO・FINAL DOPA RUSH・100%到達演出・DOPA OVERDRIVE・HOLD修正版・高速仕分け・ 信号ゲーム・SKIP・98〜102 STOP・結果画面・タイプ判定・犯行記録の仕組みは変更していない。
これまでの「連打→1回だけ急停止」は単調だったため、緑→赤→緑→赤(3回切替)の複数フェーズに
再設計した(RapidStopQuestion.tsx)。緑は連打してよい合図、赤は1回でもタップしたら即MISS。
最後の赤フェーズを静かに待ち切れて、かつ緑フェーズで十分に連打できていた場合のみ成功になる
(MIN_TOTAL_TAPS未満のタップ数だと、赤に一切触れていなくても成功扱いにしない)。
各フェーズの長さは毎回ランダムに変化し、src/engine/difficultyStage.ts経由でゲーム進行度に
応じてわずかに短縮される(固定タイミングを覚えられないようにするため)。判定品質(PERFECT/GREAT/GOOD)は
緑フェーズでの平均タップ間隔から算出する。色の切り替え自体を文章より強く見せるため、
発光の強さとパルスアニメーションを新規追加した(signal-pulse/signal-green-glow/signal-red-glow)。
SequenceTapQuestion.tsx)FindTargetQuestion.tsx)ReleaseZoneQuestion.tsx)ShortVideoSwipeQuestion.tsx)。操作自体は単純なため出現頻度は控えめColorWordQuestion.tsx)。中盤(20秒)以降から出題FlashSpotQuestion.tsx)NotifRushQuestion.tsx)。バッジの出現枠を固定6箇所に限定し、各バッジに個別の
自動消滅タイマーを持たせることでDOM・AudioNodeの無限生成を防いでいる新お題はいずれも初見で理解できる操作感・1〜2秒程度の短さを優先し、既存お題と操作感が
被りすぎないよう設計した。フェーズごとの解禁タイミングは10秒(1→4/ターゲット探し/光ったやつ)→
20秒(文字の色/ショート動画/緑で離せ)→30秒(通知ラッシュ、以降は信号連打を含む全種類)→
50秒(FINAL DOPA RUSHとして全種類から出題)という段階構成にしてある(difficultyConfig.ts)。
bgm.ts):COMBO5で軽い追加シンセ、10で低音アクセント、
15で高音アルペジオ、20で追加パーカッション、25以上でさらに刺激的なレイヤーを追加する。
MISSでCOMBOが0に戻ると、次のtickで自動的にすべてのレイヤーが消え、COMBOを伸ばし直すと
また戻ってくる構造にしている(新規の状態管理は不要で、既存の「comboRefが0に戻る」仕組みに
乗っただけ)sound.tsのcomboPitchedTier):連続正解が伸びるほど判定音の音程が
少しずつ上がる(上限で頭打ちにして耳障りにならないようにしている)playLateGameSweetener)sfx.finalWarningBeep/countdownBeep)sfx.hundred)questionPicker.tsに、直前1問だけでなく直近3問のタイプもゆるく避けるfilterByRecentTypesを
追加した(候補が尽きたら通常のプールにフォールバックするため、完全に出題不能にはならない)。
既存のカテゴリ連続回避と合わせて、お題の種類が増えたことでプレイごとの展開がより読めなくなる
ようにしている。1回のプレイで全27種が出る必要はなく、前回出なかったお題が次回出てくるという
リプレイ性を意図している。
新お題からもPlayStatsにログを取得している(rapidStopRedTaps/sequenceTapSamples/
findTargetSamples/releaseZoneOverMs/shortVideoSamples/colorWordFooledCount/
notifRushSamples)。「1→4を0.83秒で処理」「文字の色に3回騙されました」のように、いくつかは
resultEngineV4.tsの犯行記録候補に反映済み。将来的に全て結果画面へ出す前提で保持している。
テーマは「難しいのはOK。意味不明と理不尽はNG。」。新お題の追加はなし。ゲーム構造・27種のお題・ スコア計算・BGM構造・COMBO構造・OVERDRIVE・結果画面は変更していない。
これまでは「灰色→緑」の一発切替だったため、見た瞬間すでに緑に見えることがあり、
「待つ・反応する」ゲームとして成立しないケースがあった。固定指示を「緑で押せ!」に変更し、
青/赤/黄を2〜5回ランダムに高速切替してから必ず緑で終わるシーケンスに構造化した
(GoWaitQuestion.tsx)。切替回数・色順・各表示時間は毎回ランダムで、数学的に「初手緑」が
発生し得ない構造にしている。緑になる前にタップしたらMISS、なってからのタップはSUCCESSで
反応速度によりPERFECT/GREAT/GOODを判定するロジックは維持。
上部に「← 食べ物」「その他 →」を高コントラストな色付きチップで大きく固定表示し、背景演出に
埋もれないようにした。成功時はアイコンが仕分け方向へ飛んでいくフェードアウト演出を追加し、
「左右へ仕分けている」感覚を視覚的にも伝える(FoodSortQuestion.tsx)。
「🟢 連打|🔴 STOP」を常時表示する主要UIとして追加し、現在のフェーズに応じてどちらが
アクティブかを色で示す。中央ボタンも緑フェーズは「連打!」、赤フェーズは「STOP!」と
大きく表示するようにした(RapidStopQuestion.tsx)。ロジック(緑→赤→緑→赤の4フェーズ、
最低タップ数、赤タップ即MISS)は変更していない。
固定指示を「↑ 上に3回スワイプ!」に変更し、「あとN本」という残数表示を追加。正しく
上スワイプするたびにカードが上へ飛んでいき、下から次のカードが現れる演出にした
(ShortVideoSwipeQuestion.tsx)。
全27問のresolve処理(SUCCESS/MISSコールバック・generic timeout・setTimeout・
requestAnimationFrame・pointerup/cancel)を監査した結果、外側の汎用タイムアウト
(setTimeout(() => finish(false), spec.targetTimeMs))がコンポーネントのマウント時に
一度だけセットされ、プレイヤーが正しく進捗している最中でも再武装されないという
構造的なレース条件を6問で発見した:
RepeatTapQuestion:規定回数タップ後の「止まれ」待機中に発火し得たReleaseZoneQuestion:指を置くのが少し遅れただけで、ゲージ完走中に発火し得たSequenceTapQuestion:1つ目の数字を見つけるのが少し遅れただけで、残りをタップ中に発火し得たClearNotificationsQuestion:1個目を消すのが少し遅れただけで、残りを消している最中に発火し得たNotifRushQuestion:赤の出現運が悪く1個目が遅れただけで、消している最中に発火し得たShortVideoSwipeQuestion:1回目のスワイプが少し遅れただけで、残りのスワイプ中に発火し得た(RapidStopQuestionは自前の内部タイマーチェーンで完結しており、この種の外側タイムアウトを
持たないため元々対象外。単純な単発タップ問題(色選択・98〜102 STOPなど)も「決定=解決」の
ため対象外。)
Ver.4.3でHOLDに導入した「進捗するたびに安全弁タイマーを引き直す」という考え方を、 上記6問すべてに適用した。規定回数への到達・正しいタップ・1個の正しいクリアなど、 プレイヤーが検証可能な形で前進するたびに、外側タイマーを「残り工程ぶんの猶予」で 引き直す。これにより、外側タイムアウトは「本当に何もしなかった場合」だけの安全弁となり、 正しく進行中の操作を上書きすることが構造的にできなくなった。
FoodSortQuestion/ShortVideoSwipeQuestionの新しい「飛んでいく」演出についても、
判定は演出の前に確定させ(doneRef相当のフラグを即座に立てて外側タイマーを無効化)、
演出時間ぶんだけonResult呼び出しを遅らせる方式にすることで、演出待ちの間に古いタイマーが
結果を書き換えるレースが起きないようにしている。
開発時だけMISSの原因を追跡できるよう、useRushGame.tsのhandleQuestionResultに
console.debugベースのデバッグログ(questionType/failureReason/elapsedMs/
targetTimeMsなど)を追加した。本番ビルドでは出力されず、import.meta.env.DEVでのみ動作する。
実機で、FINAL DOPA RUSHの中央大型バナーと3-2-1の巨大数字表示が、出題中のお題と選択肢の上に
重なりゲームが見えなくなる不具合があった。中央を覆う全画面バナーを廃止し、上部HUDに
pointer-events-noneの細い警告バー(「FINAL DOPA RUSH・残りN秒」)を常時表示する方式に
変更した。3-2-1のカウントダウンは、画面右上のTIME表示欄内で大きく表示する方式に変更し、
中央のお題操作領域とは一切重ならないようにした。赤い警告ランプ(画面端の点滅)・サイレン・
高速BGM・警告ビープ・背景演出は変更なし(PlayScreen.tsx)。
上記4問以外の23問についても初見プレイヤー視点で再確認した。押す対象・スワイプ方向・ 待つか押すか・成功条件と画面表示の一致・終了条件の推測可能性のいずれも大きな問題は 見つからず、追加の変更はしていない。
DOPA OVERDRIVE(100%突破)を完全にプレゼンテーション層として作り替えた。通常問題のロジック・
スコア計算・OVERDRIVE発動条件(overdriveConfig.ts)・正誤判定・問題制限時間には一切触れていない。
コンセプトは、通常ゲームの紫・ネオン系、FINAL DOPA RUSHの赤い非常警報に対して、
DOPA OVERDRIVEを**「黄金の非常事態」**として明確に差別化すること。
src/components/OverdriveFx.tsx)演出は実ゲーム(PlayScreen.tsx)と?preview=overdrive確認画面(OverdrivePreviewScreen.tsx、
Vercel Preview限定)の両方から同じコンポーネントを呼び出す構成にした。見た目のロジックを
ここに一本化することで、「Previewで見た演出」と「実際にOVERDRIVEが発動した時の演出」が
ほぼ同じになる。getOverdriveTier(percent)でpercentから0〜4の段階を判定し、
OverdriveAmbience(画面端の黄金サイレン+外周パーティクル)、LimitErrorOverlay
(100→101%突破時のグリッチ)、OverdriveRevealOverlay(DOPA OVERDRIVE到達)、
Golden120Overlay(120%到達クライマックス)を提供する。全要素にpointer-events-noneを設定。
既存の「騒音→一瞬静寂→金色爆発」(100%到達)は維持しつつ、その後OVERDRIVE条件を満たしている
場合だけ、「100%という上限を破壊した」と感じられる新しいシーケンスを追加した
(useRushGame.tsのsetPercentTarget()):
DOPAGAKI表示の数字が震える(anim-limit-shake)→ グリッチ+暗転+「LIMIT ERROR」の異常表示
(LimitErrorOverlay、約550ms)→ 101%表示+sfx.overdrive()+黄金衝撃波の「DOPA OVERDRIVE」
バースト(OverdriveRevealOverlay)。100%到達と同じ答えでOVERDRIVEにも突入する場合と、
すでに100%到達済みの状態で後の答えでOVERDRIVEに突入する場合の両方に対応している。
OVERDRIVEに入った瞬間から、画面左右端に細い帯状の黄金サイレン(golden-siren-bar、
FINAL DOPA RUSHの赤サイレンとは別の点滅パターン)を常時表示する。左右で点灯タイミングを
半周期ずらし、「左から光る→右から光る」という回転灯のような見え方にした。外周には
overdrive-ringのパルス発光、パーティクルは画面端0〜15%/85〜100%の帯にのみ配置し、
中央60〜70%の問題表示領域には一切演出をかけない(信号・色問題・通知色のUIに
黄金フィルターがかからないことをPlaywrightで確認済み)。
getOverdriveTier()が percent に応じて4段階を返し、サイレンの点滅速度・外周発光の脈動速度・
パーティクル数を連動して強めていく。
Golden120Overlayによる最大クライマックスbgm.tsにOVERDRIVE専用レイヤーを追加した:playOverdriveBass(通常より太い専用低音)、
playOverdriveArpeggio(COMBOアルペジオより速く広い駆け上がり)、playOverdriveSiren
(黄金サイレンの音版、パトランプ風の上下スイープを1小節に1回)。既存のplayOverdriveStab
(高音シンセ)と合わせ、「通常ゲームの延長」ではなく「隠しステージに入った」音になるようにした。
SEをかき消さないよう、音量は既存のBGM/SEバランスの範囲内に収めている。
上限(OVERDRIVE_CONFIG.maxPercent)に初めて到達した瞬間だけの追加クライマックスを実装した
(crossingMax、useRushGame.ts)。上限の値・発動条件自体は変更せず、「target が初めて
上限に達したこと」を観測して演出するだけ。一瞬音を引く(duckAudio)→ sfx.overdriveMax()
(100%到達より一段大きい専用爆発SE)→ 黄金爆発+画面端から広がる金色衝撃波(anim-golden-shockwave)
+「120%」+タイプ名(getOverdriveTitle(120)=「ドパガキ最終形態」)を表示。多少やりすぎな
くらいの演出量を許容している。
ResultCard.tsxを、通常結果と一目で区別できるように強化した。101%以上で「⚡ DOPA OVERDRIVE ⚡」
バッジ・黄金グロー・カード端に控えめな金色パーティクルを表示し、120%到達時はさらに「・MAX」の
表示と、より強い黄金グロー(shadowを2段階に強化)を追加する。SNSスクショ映えを意識し、
通常の紫系カードとは明確に別物に見えるようにした。
?preview=overdrive)Ver.4.6で追加した確認用画面(src/dev/OverdrivePreviewScreen.tsx)を、今回の黄金演出込みで
一通り確認できるように更新した。98%→100%到達→LIMIT ERRORブリーチ→101%突破→DOPA OVERDRIVE→
110〜116%上昇→120%到達クライマックス→黄金結果画面、までを約13秒で再生する。到達可否は
引き続きビルド時注入の__DOPAGAKI_PREVIEW_ENABLED__(Productionビルドでは常にfalse)で
制御しており、通常プレイのロジック・スコア計算・OVERDRIVE発動条件には一切触れていない。
最大表示は常に「ドパガキ度」。その下にタイプ名、さらに小さく最大COMBO/最速反応/正答率を表示し、
GAME SCOREは表示しない。99%終了時は「あと1%でした。」のような悔しさを煽るコメントを出す。
タイプ名は通常時(脳直高速処理型/連打中毒型/高速フリック型/待てない型/刺激処理マシーン/
完全体ドパガキ/ドパガキ見習い/バランス型)とOVERDRIVE時(限界突破ドパガキ〜ドパガキ最終形態)で
分けて src/config/resultTypesV4.ts に定義。犯行記録はゲームログから自動生成し、最もネタになる2件を表示する。
Ver.4.1でのタイプ判定の厳格化:Ver.4では「反応時間/制限時間の比率が0.55以下」というだけで
脳直高速処理型が付与され、最速反応0.73秒程度の緩いプレイでも該当してしまっていた。Ver.4.1では
src/config/resultTypesV4.ts の TYPE_THRESHOLDS に、最低サンプル数・比率・絶対反応時間(ms)・
正答率を組み合わせた閾値を定義し、src/engine/resultEngineV4.ts の determineType() を
「どの条件も明確に満たさない場合は汎用の『バランス型ドパガキ』にフォールバックする」方式に変更した。
「押すな」を実際に複数回押してしまった場合の「待てない型」判定は好評だったため、最優先の判定として維持している。
npx tsc --noEmit / npm run build / npm run lint すべて成功
(lintの警告は各お題ファイルの構造に起因する軽微なFast Refresh警告のみで、ビルドを妨げない)statsRef.current.maxCombo が最終結果に反映されていなかった問題を修正npx tsc --noEmit / npm run build / npm run lint すべて成功(新規追加分含めエラーなし)scoreConfigV4.tsの数式を再現):
正答率60/70/80/90/95/98%それぞれについて、判定分布を正答率相応に仮定した20000試行の平均値は
56.8% / 67.4% / 78.3% / 89.2% / 94.7% / 98.1% となり、指示された目標バンド
(60%→50-65%、70%→60-75%、80%→70-85%、90%→85-95%、95%以上+高反応+高COMBO→95-100%)に
収まることを確認したcomputeMinTargetTimeMsによる下限保証が機能している)npx tsc --noEmit / npm run build / npm run lint すべて成功(新規追加分含めエラーなし)computeMinTargetTimeMsの下限保証が機能)NoPressQuestion.tsxはVer.4.1から変更しておらず、
コードレビューで挙動を確認済みnpx tsc --noEmit / npm run build / npm run lint すべて成功swipeタイプが3回の60秒プレイいずれでも一度も出題されないことを確認npx tsc --noEmit / npm run build / npm run lint すべて成功AudioContextがrunning状態になることを確認(iPhone Safariの
自動再生制限に対する対策が機能している)running: false)ことを確認unlockAudio()で明示的にリセットするようにしたnpx tsc --noEmit / npm run build / npm run lint すべて成功(lintは既存お題ファイル共通の
Fast Refresh警告のみで、エラーは0件)window.__DOPAGAKI_SNAPSHOT__のインスタンスIDを使って問題ごとの判定を個別に検証:
lastJudgement: 'MISS'になることを確認PERFECT)になることを確認comboMilestone/comboPitchedTier)が
エラーなく発火することを確認running: false)ことを確認page.locator('button').first()でミュートボタン(画面上部)を
誤って操作していたため、信号連打の赤タップ検証が常に失敗していた。ミュートボタンを
除外するセレクタに修正して解決snapshot.currentSpec.instanceIdで
問題インスタンスを判定する方式に修正して解決npx tsc --noEmit / npm run build / npm run lint すべて成功(エラー0件、警告は既存の
Fast Refresh警告のみ)window.__DOPAGAKI_SNAPSHOT__のインスタンスIDで問題ごとに検証し、
(a) 出題直後のボタン色が緑になっていることは一度もない、(b) 緑になる前にタップすると
lastJudgement: 'MISS'になる、(c) 緑になってからタップすると成功になる、の3点をすべて確認pointer-events: noneで表示されていることを確認text-4xlに変更した際、テストスクリプトの命令文セレクタ(text-3xl等を対象にしていた)が
追従しておらず凡例検出が一時的に誤判定になった。DOM上の凡例テキストを直接探す方式に
修正して解決npx tsc --noEmit / npm run build / npm run lint すべて成功(エラー0件)?preview=overdrive、Chromiumヘッドレス):
0→30→60→85→98→100→101→104→108→112→116→120という想定通りの%推移、
「DOPAGAKI 100%」バースト、「LIMIT ERROR」グリッチ、「DOPA OVERDRIVE」バースト、
120%クライマックス(Golden120Overlay)、黄金結果カードの「MAX」バッジまで
すべて表示されることを確認。コンソールエラー0件__DOPAGAKI_FORCE_OVERDRIVE_SETUP__、検証後に削除済み)で統計値を直接注入したうえで、
実際の色選択お題に1問正解させ、本物のhandleQuestionResult()→setPercentTarget()を
実行させて検証した。showHundredBurst/showLimitErrorGlitch/showOverdriveBurst/
overdriveActive/showMaxBurstのすべてが実エンジンのコードパス上で正しく発火し、
displayPercentが100・120の両方に到達することを確認。コンソールエラー0件VERCEL_ENV=productionでビルドしたバンドルに対し、
?preview=overdriveを付けても通常のタイトル画面が表示され、確認用画面・黄金演出のいずれも
出現しないことを確認(Ver.4.6で確立した仕組みがVer.4.7の追加後も機能している)src/config/difficultyConfig.ts:6段階の時間帯・出題速度・出題プールsrc/config/scoreConfigV4.ts:判定ごとの質スコア・COMBOボーナス・正答率別の到達上限(ACCURACY_CAPS)src/config/timingConfig.ts:HOLD/連打/スワイプ/計算問題の物理的な最低制限時間src/config/overdriveConfig.ts:DOPA OVERDRIVEの隠し発動条件の閾値src/config/visualConfig.ts:演出レベル(発光/ネオン/パーティクル/ゴールド/ギラギラ)の定義src/config/resultTypesV4.ts:タイプ名(通常/OVERDRIVE称号)とタイプ判定の閾値(TYPE_THRESHOLDS)src/config/messagesV4.ts:タイトル文言・リトライ文言・結果コメント・シェア文面src/questions/*.tsx:お題の追加・見た目・難易度調整(1問1ファイル。categoryでカテゴリも設定)src/utils/sound.ts:効果音(Web Audio APIの簡易SE。音源ファイルへの差し替えも容易)(Ver.4.2で追加)
generate()内の乱数レンジ(GOの待機時間、100で止めろの速度、通知の対象数など)RepeatTapQuestion.tsx内のstopConfirmMsのレンジ(現在700〜900ms)(Ver.4.3で追加)
src/config/timingConfig.tsのhold.completionSafetyMs:HOLD完了判定の安全弁タイマーの猶予StopAt100Question.tsxのGOOD_RANGE:「98〜102でSTOP!」の成功範囲の広さ(表示と条件が自動的に一致する)difficultyConfig.tsの各フェーズプールにswipeを戻せば方向スワイプを復活させることも可能(Ver.4.4で追加)
src/utils/audioContext.tsのBGM_BASE_GAIN/SFX_BASE_GAIN:BGM/SEそれぞれの基準音量src/utils/bgm.tsのSTAGE_BPM:6段階のBPM。playKick/playHat/playBass/playPerc/
playShimmer/playOverdriveStabの各関数で音色・音量を調整可能useRushGame.tsのCOMBO_MILESTONES/comboVisualBonus/comboMilestoneLevel:連続正解の
節目とその演出強度useRushGame.tsのHUNDRED_SILENCE_MS/BIG_COMBO_BREAK_THRESHOLD/COMBO_BREAK_FLINCH_MS:
100%到達時の静寂の長さ、大きいCOMBO BREAKの発動しきい値とその演出の長さ(Ver.4.5で追加)
RapidStopQuestion.tsxのMIN_TOTAL_TAPS/REFERENCE_INTERVAL_MS:信号連打の最低タップ数、
判定品質の基準タップ間隔src/engine/difficultyStage.ts:進行度に応じてお題側の難易度を微調整したい場合の共有ステージ値
(generate()はzero-argのままなので、この値を読むことで最小限のアーキテクチャ変更で対応している)src/config/difficultyConfig.tsの各フェーズプール:新お題7種の解禁タイミングを変更可能src/config/timingConfig.tsのsequenceTap/findTarget/releaseZone/shortVideoSwipe/
colorWord/flashSpot/notifRush:新お題それぞれの物理的な最低制限時間bgm.tsのCOMBOレイヤーしきい値(scheduleStep内のcombo >= 5/10/15/20/25):
COMBOに応じて追加される音レイヤーの発動タイミングsrc/engine/questionPicker.tsのRECENT_TYPES_LENGTH(useRushGame.ts):直近何問分のタイプを
ゆるく避けるか(Ver.4.6で追加)
GoWaitQuestion.tsxのNON_GREEN_COLORS/randInt(2, 5):信号ゲームの非緑色の種類・切替回数の範囲FoodSortQuestion.tsx/ShortVideoSwipeQuestion.tsxのFLY_MS:成功時の「飛んでいく」演出の長さRepeatTapQuestionのstopSafetyMarginMs、
ShortVideoSwipeQuestionのPER_REMAINING_SWIPE_MSなど):各問題の再武装タイマーの余裕時間useRushGame.tsのinferFailureReason/logQuestionMiss:開発時のMISS原因ログ
(import.meta.env.DEV時のみconsole.debugに出力、本番には出ない)(Ver.4.7で追加)
src/components/OverdriveFx.tsxのgetOverdriveTierのしきい値(101/110/115/120)、
TIER_SIREN_MS/TIER_RING_MS/TIER_PARTICLE_COUNT:黄金演出の段階と強度useRushGame.tsのLIMIT_ERROR_MS/MAX_SILENCE_MS/MAX_BURST_HOLD_MS:
100→101%突破演出・120%到達演出それぞれの長さsrc/utils/bgm.tsのplayOverdriveBass/playOverdriveArpeggio/playOverdriveSiren:
OVERDRIVE専用BGMレイヤーの音色・音量src/utils/sound.tsのoverdriveMax:120%到達専用の爆発SEsrc/components/ResultCard.tsxのGOLD_CARD_PARTICLES:黄金結果カードの装飾パーティクル位置overdriveConfig.tsでいつでも調整可能)。Playwrightボットでの検証では、
「正答率・反応速度は高いが押すな/先走りタップが一切ない完璧すぎるプレイ」だとOVERDRIVEの
追加条件(高COMBO/せっかちタップ/押すな失敗のうち2つ以上)を満たさず発動しなかった。
実機で人間らしいプレイをした際に自然に発動するか、体感を重点的に確認してほしいResultCardコンポーネントとして分離済みなので拡張しやすい)?preview=overdriveで確認した演出と、実際にOVERDRIVEを発動させた際の演出が
実機でもほぼ同じに見えるか