Skip to content

Add classic edition Super Mario Bros 1-1 game - #22

Closed
naoto714714 wants to merge 1 commit into
mainfrom
codex/create-browser-game-for-mario-level-1-1
Closed

naoto714714 wants to merge 1 commit into
mainfrom
codex/create-browser-game-for-mario-level-1-1

Conversation

@naoto714714

@naoto714714 naoto714714 commented Nov 30, 2025

Copy link
Copy Markdown
Owner

Summary

  • add a new classic-edition Super Mario Bros 1-1 game directory alongside the existing version
  • document the new classic edition entry in the project listing and landing page

Testing

  • not run

Codex Task

Summary by CodeRabbit

リリースノート

  • 新機能
    • 新作ゲーム「Super Mario Bros 1-1 Classic Edition」をリリース。ピクセルアート風のクラシックな操作感でマリオを操作し、ステージをクリアするゲームです。キーボードおよびゲームパッド両対応で、スコア・コイン・ライフ管理機能を備えています。レスポンシブデザイン対応で、様々なデバイスでプレイ可能です。

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Nov 30, 2025

Copy link
Copy Markdown

ウォークスルー

このプルリクエストは、ブラウザゲーム集に「Super Mario Bros 1-1 Classic Edition」という新作ゲームを追加します。HTML5 Canvas、Vanilla JavaScript、CSS3を使用した完全なゲーム実装で、メインリポジトリのドキュメントとインデックスを更新し、専用ディレクトリに12個のJavaScriptモジュール、スタイルシート、HTMLファイルを含みます。

変更内容

コホート / ファイル 変更内容
リポジトリ ドキュメント
README.md, index.html
メインREADMEに「Super Mario Bros 1-1 Classic Edition」セクションを追加。ゲームグリッドに新作ゲームのカードエントリを追加。
ゲーム ドキュメント
super-mario-bros-1-1-classic/README.md
ゲーム概要、操作方法、目的、技術仕様(HTML5 Canvas、Vanilla JS モジュール設計、CSS3、物理エンジン)、ファイル構造、オリジナル要素、開発メモを記載した包括的なREADMEを追加。
ゲーム UI/スタイリング
super-mario-bros-1-1-classic/css/style.css
グローバルリセット、ゲームコンテナ、HUD(スコア、コイン、ワールド、時間、ライフ)、キャンバス、開始/ゲームオーバー画面、コントロールパネルのスタイルを定義。ピクセルアート対応とモバイルレスポンシブ設計(768px、480pxブレークポイント)を実装。
ゲーム HTML エントリーポイント
super-mario-bros-1-1-classic/index.html
ゲーム UI レイアウト、HUD、開始/ゲームオーバー画面、1024x448 キャンバスを配置。JavaScript モジュール(constants、utils、spriteLoader、physics、entities、enemies、level、player、camera、input、audio、game、main)をシーケンシャルロードするリンクを含む。
ゲーム ロジック(コア)
super-mario-bros-1-1-classic/js/game.js, super-mario-bros-1-1-classic/js/main.js
Game クラスでゲームループ、状態管理(START、PLAYING、GAME_OVER、LEVEL_COMPLETE)、入力処理、物理・衝突解決、HUD 更新、レンダリングを実装。main.js で初期化、キャンバス取得、SpriteLoader 設定、ゲーム作成、イベントハンドリングを実行。
ゲーム システム
super-mario-bros-1-1-classic/js/input.js, super-mario-bros-1-1-classic/js/audio.js, super-mario-bros-1-1-classic/js/camera.js, super-mario-bros-1-1-classic/js/physics.js
InputManager はキーボード/ゲームパッド入力を一元化。AudioManager は Web Audio API で効果音と BGM を生成・管理。Camera はビューポート追跡、スムージング、デッドゾーン、スクリーンシェイク、座標変換を実装。Physics は重力・摩擦、タイル/エンティティ/プラットフォーム衝突解決を提供。
ゲーム エンティティ
super-mario-bros-1-1-classic/js/entities.js, super-mario-bros-1-1-classic/js/enemies.js, super-mario-bros-1-1-classic/js/player.js
Entity 基底クラス、Block(地形・レンガ・?ブロック、アイテム生成)、Item(コイン・キノコ・ファイアフラワー、収集ロジック)を entities.js で定義。Enemy 基底クラス、Goomba(歩行 AI)、KoopaTroopa(歩行・甲羅状態)を enemies.js で実装。Player クラスで Mario 風プレイヤー(パワーアップ状態、ジャンプ・歩行、アニメーション、無敵状態、ライフ管理)を player.js で定義。
レベル システム
super-mario-bros-1-1-classic/js/level.js
Level クラスでテレイン生成(地面、プラットフォーム、パイプ、敵、?ブロック、レンガ、背景)、エンティティ管理(追加・削除・更新)、レンダリング、カメラ範囲内の可視オブジェクト取得を実装。
ユーティリティ
super-mario-bros-1-1-classic/js/constants.js, super-mario-bros-1-1-classic/js/utils.js, super-mario-bros-1-1-classic/js/spriteLoader.js
constants.js はゲーム全体の設定定数を一元管理。utils.js は衝突検查、補間、タイル/ピクセル変換、スコア/時間フォーマット等の汎用関数を提供。spriteLoader.js はキャンバスベースのピクセルアート スプライト生成・キャッシング機能を実装。

シーケンス図

sequenceDiagram
    participant User as ユーザー
    participant Main as main.js
    participant Game as Game
    participant Input as InputManager
    participant Level as Level
    participant Player as Player
    participant Physics as Physics
    participant Collision as 衝突処理
    participant Audio as AudioManager
    participant Camera as Camera
    participant Render as レンダリング

    User->>Main: ページ読み込み
    activate Main
    Main->>Game: new Game(canvas)
    activate Game
    Game->>Game: setupCanvas()
    Game->>Level: new Level()
    activate Level
    Level->>Level: generateLevel()
    deactivate Level
    Game->>Player: new Player()
    Game->>Input: new InputManager()
    Game->>Camera: new Camera()
    Game->>Audio: new AudioManager()
    deactivate Game
    deactivate Main

    User->>Game: Space キー
    activate Game
    Game->>Game: startGame()
    Game->>Game: initializeGame()
    Game->>Audio: enableAudio()
    Game->>Game: gameLoop()
    
    loop ゲームループ
        Game->>Input: update()
        Game->>Game: handleInput()
        Game->>Player: setInput(...)
        
        Game->>Player: update(deltaTime)
        activate Player
        Player->>Player: updateMovement()
        Player->>Player: updateAnimation()
        deactivate Player
        
        Game->>Game: updatePhysics()
        activate Physics
        Physics->>Physics: applyGravity(Player)
        Physics->>Physics: applyFriction(Player)
        Physics->>Physics: updatePosition(Player)
        Physics->>Collision: resolveCollisionWithTiles()
        activate Collision
        Collision-->>Physics: 衝突結果
        deactivate Collision
        deactivate Physics
        
        Game->>Game: handleCollisions()
        Game->>Collision: checkPlayerBlockCollisions()
        Game->>Collision: checkPlayerEnemyCollisions()
        Game->>Collision: checkPlayerItemCollisions()
        
        Game->>Level: update(deltaTime)
        activate Level
        Level->>Level: 敵/アイテム更新
        deactivate Level
        
        Game->>Camera: update(Player)
        
        Game->>Audio: playSound(...)
        
        Game->>Game: render()
        activate Render
        Render->>Level: render(ctx, camera)
        Render->>Player: render(ctx, camera)
        deactivate Render
        
        break ゲームオーバー
            Game->>Game: gameOver()
        end
    end
    deactivate Game
Loading

推定コードレビュー工数

🎯 4 (複雑) | ⏱️ 約60-75分

特に注意が必要な領域:

  • js/game.js — ゲームループ、状態管理、複数の衝突タイプ(ブロック・敵・アイテム)処理、HUD同期ロジックが密集。各衝突ハンドラの相互作用を検証。
  • js/physics.js — タイル衝突解決、エンティティ衝突、プラットフォーム処理など複数の衝突ファミリーが混在。エッジケース(接地判定、落下判定)の正確性確認。
  • js/level.js — テレイン生成パイプライン(地面、プラットフォーム、パイプ、敵配置)、可視範囲内エンティティ取得の効率性。
  • js/player.js — パワーアップ/ダウン状態遷移、コヨーテタイム・ジャンプバッファリング、無敵状態管理の相互作用。
  • js/audio.js — Web Audio API の手続き的音生成;AudioContext の状態管理とクリーンアップ。
  • モジュール間の依存関係 — 13個の JS ファイル(constants、utils、spriteLoader 経由の依存)の初期化順序とデータフロー確認。

関連する可能性のあるプルリクエスト

🐰 キャンバスに描かれた懐かしきマリオ、
物理とぶつかりが織りなす冒険の舞、
敵を踏み、コインを集め、進みゆく道、
ウサギも跳ねるほど楽しき完成!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルはプルリクエストの主要な変更内容を正確に反映しており、新しい「Super Mario Bros 1-1 Classic Edition」ゲームの追加というコアな変更を明確に伝えています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/create-browser-game-for-mario-level-1-1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude

claude Bot commented Nov 30, 2025

Copy link
Copy Markdown
Contributor

Claude encountered an error —— View job


I'll analyze this and get back to you.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (23)
super-mario-bros-1-1-classic/js/camera.js (1)

38-84: 右方向スクロール時のデッドゾーン処理ロジックの意図確認 & シェイク処理について

  • Line 43–47 で水平デッドゾーンを計算したあと、Line 57–59 で「velocityX > 0 のとき常に this.targetX = target.x - this.deadZone.left;」と再代入しているため、右移動中はデッドゾーン判定の結果がほぼ上書きされます。

    • 「マリオ風に“右方向のみスクロール”させたい」意図ならありえますが、プレイヤーがデッドゾーン中央付近にいても常に deadZone.left に合わせようとするため、カメラがやや前のめりに追従する挙動になります。
    • もし「デッドゾーンを越えたときだけ追従」させたいのであれば、velocityX > 0 条件をデッドゾーン境界と組み合わせる(例: velocityX > 0 && playerScreenX > this.deadZone.right)など、条件をもう少し絞ると分かりやすくなります。
  • Line 81–84 の clampToBounds では、this.x + this.shake.offsetX / this.y + this.shake.offsetY をそのまま this.x / this.y に書き戻しているため、「ベース位置+揺れ」ではなく「揺れ込みの位置」を状態として保持する形になっています。

    • 機能的には問題にならない可能性も高いですが、一般的には「内部状態としての camera.x/y」と「描画時の揺れオフセット」を分離しておく方が、将来の調整やデバッグがしやすいです(例: getRenderPosition() で揺れを加算)。

挙動が狙い通りか一度プレイして確認しておくと安心です。

super-mario-bros-1-1-classic/js/input.js (1)

47-193: キーコードリテラルと KEYS 定数の統一について

この InputManagerevent.code ベースでキー状態を管理しており、Line 49, 97–113, 141–157 などで 'ArrowLeft', 'ArrowRight', 'Space', 'KeyX', 'KeyP' といったリテラルを直接使っています。一方で constants.js には KEYS オブジェクトがあり、特に KEYS.JUMP' '(スペース文字)になっているため、将来 KEYS を参照するコードと食い違う可能性があります。

  • KEYS 側を 'Space' など KeyboardEvent.code に合わせた値に修正したうえで、InputManager 内の文字列も KEYS.JUMP / KEYS.RUN などの定数経由に寄せると、
    • キー割り当て変更時の修正漏れを防げる
    • ゲーム内でキー定義の単一ソースを保てる
      というメリットがあります。

ゲーム全体のキー定義をどこで正とするか、一度決めておくとメンテしやすいです。

super-mario-bros-1-1-classic/README.md (1)

55-75: コードブロックに言語指定を付けると markdownlint が通ります

Line 55 のディレクトリ構成のコードブロックが ````` のみで開始されており、markdownlint (MD040: fenced-code-language) の警告対象になっています。

例えば次のように言語を付けておくと、Lint も静かになりますし閲覧時のシンタックスハイライトも安定します。

-```
+```text
 super-mario-bros-1-1-classic/
 ├── index.html              # メインHTML
 ...
super-mario-bros-1-1-classic/js/main.js (1)

2-85: グローバル汚染とガイドラインとの整合性について

初期化フロー自体は分かりやすくて良いのですが、プロジェクトルール(*/js/**/*.js : グローバル変数は使用しない)との観点で気になる点がいくつかあります。

  • Line 56–57: window.DEBUG を直接立てています。
  • Line 67: window.game = game; でゲームインスタンスをグローバルに公開しています。
  • このファイルに限りませんが、SpriteLoaderGame もグローバル名前空間上のクラスとして利用されています。

このゲームは単独ページで動くので即問題になるわけではありませんが、「ブラウザ全体で複数ゲームを扱う」というリポジトリ方針を考えると、将来的には以下のような形に寄せていくと安全です。

  • IIFE や名前空間オブジェクトに閉じ込める: window.MarioClassic = { Game, SpriteLoader, ... } など。
  • もしくは <script type="module"> 化して、import / export ベースで依存関係を表現する。
  • デバッグ用の window.game / window.DEBUG も、可能であれば「デバッグ時のみ有効」にするラッパー(例: if (window.location.hash === '#debug') window.MarioClassicDebug = { game };)に寄せる。

現状でも動作上の問題はなさそうですが、リポジトリ全体のルールに揃えるという意味で、余裕のあるタイミングで見直しておくと良さそうです。

super-mario-bros-1-1-classic/js/constants.js (1)

1-147: グローバル定数の定義方針について

このファイルの GAME_CONSTANTSDIRECTIONBLOCK_TYPESENEMY_TYPESITEM_TYPESKEYS はすべてトップレベル const として定義されており、<script> 直読み構成ではグローバル名前空間に載ります。リポジトリのルール(*/js/**/*.js : ゲーム間で名前衝突を防ぐため、グローバル変数は使用しない)に照らすと、将来的には IIFE や名前空間オブジェクト、あるいは ES Modules (type="module") への移行を検討しておくと安心です。

補足: KEYS 定数は定義されていますが、実装では使用されておらず、InputManager は直接 event.code 文字列('Space''ArrowLeft' など)を使用しています。

super-mario-bros-1-1-classic/js/utils.js (2)

1-2: グローバル変数の使用はコーディングガイドラインに違反しています。

Utils がグローバル定数として宣言されており、ゲーム間での名前衝突を引き起こす可能性があります。モジュールパターンまたはIIFEでカプセル化することを推奨します。Based on coding guidelines and learnings.

-// ユーティリティ関数
-const Utils = {
+// ユーティリティ関数
+const MarioClassicUtils = (() => {
+  const Utils = {
   // 矩形の衝突判定
   checkCollision(rect1, rect2) {

ファイル末尾を以下のように変更:

   getAnimationFrame(frameCount, frameRate, totalFrames) {
     return Math.floor(frameCount / frameRate) % totalFrames;
   },
-};
+  };
+  return Utils;
+})();

または、ES6モジュール形式への移行を検討してください。


111-129: deepClone関数の冗長なチェックとエッジケース処理

Line 122の typeof obj === 'object' チェックは、Line 113の条件で非オブジェクトは既にリターンされているため冗長です。また、MapSetRegExpなどの特殊オブジェクトは正しくクローンされません。

   deepClone(obj) {
     if (obj === null || typeof obj !== 'object') {
       return obj;
     }
     if (obj instanceof Date) {
       return new Date(obj.getTime());
     }
     if (obj instanceof Array) {
       return obj.map((item) => this.deepClone(item));
     }
-    if (typeof obj === 'object') {
-      const clonedObj = {};
-      for (const key in obj) {
-        clonedObj[key] = this.deepClone(obj[key]);
-      }
-      return clonedObj;
+    const clonedObj = {};
+    for (const key in obj) {
+      if (Object.prototype.hasOwnProperty.call(obj, key)) {
+        clonedObj[key] = this.deepClone(obj[key]);
+      }
     }
+    return clonedObj;
   },

hasOwnPropertyチェックを追加することで、継承されたプロパティのコピーを防ぎます。

super-mario-bros-1-1-classic/js/enemies.js (2)

1-2: グローバルクラス宣言はコーディングガイドラインに違反しています。

EnemyGoombaKoopaTroopaがグローバルスコープで宣言されています。名前衝突を防ぐため、名前空間またはモジュールパターンでカプセル化してください。Based on coding guidelines.


182-183: マジックナンバーを定数に抽出することを推奨します。

甲羅の速度閾値 0.1 と蹴り速度 8 が複数箇所で使用されています。GAME_CONSTANTSに追加するか、クラス定数として定義することで保守性が向上します。

// GAME_CONSTANTSに追加
KOOPA: {
  // ...existing
  SHELL_VELOCITY_THRESHOLD: 0.1,
  SHELL_KICK_SPEED: 8,
},
super-mario-bros-1-1-classic/css/style.css (2)

84-90: 重複したimage-renderingプロパティについて(静的解析の警告)

これはクロスブラウザ対応のフォールバックパターンとして意図的に記述されていると理解しますが、image-rendering: pixelatedは標準プロパティとして広くサポートされているため、ベンダープレフィックス版のみをフォールバックとして残すことを検討してください。

 #gameCanvas {
   display: block;
   margin-top: 40px;
-  image-rendering: pixelated;
   image-rendering: -moz-crisp-edges;
   image-rendering: crisp-edges;
+  image-rendering: pixelated;
 }

最後にpixelatedを配置することで、対応ブラウザでは標準プロパティが優先されます。同様にLine 157-161のcanvasルールも修正してください。


163-168: transform: scaleはピクセルアートのレンダリング品質に影響する可能性があります。

モバイル対応にtransform: scaleを使用していますが、ピクセルパーフェクトなゲームでは拡大縮小時にぼやける可能性があります。JavaScriptでキャンバスサイズを動的に調整する方法も検討してください。

super-mario-bros-1-1-classic/js/physics.js (3)

1-2: グローバル変数の使用はコーディングガイドラインに違反しています。

Physicsがグローバル定数として宣言されています。他のモジュール(UtilsGAME_CONSTANTS)と同様に、名前空間またはモジュールパターンでカプセル化してください。Based on coding guidelines.


27-35: Utils.checkCollisionとの重複コード

この実装はUtils.checkCollisionと同一です。DRY原則に従い、既存の関数を再利用することを推奨します。

   // 矩形同士の衝突検出
   checkRectCollision(rect1, rect2) {
-    return (
-      rect1.x < rect2.x + rect2.width &&
-      rect1.x + rect1.width > rect2.x &&
-      rect1.y < rect2.y + rect2.height &&
-      rect1.y + rect1.height > rect2.y
-    );
+    return Utils.checkCollision(rect1, rect2);
   },

115-122: バウンス減衰係数のマジックナンバー

0.6の減衰係数がハードコードされています。GAME_CONSTANTSに追加することで調整が容易になります。

// GAME_CONSTANTSに追加
BOUNCE_DAMPING: 0.6,
super-mario-bros-1-1-classic/js/spriteLoader.js (1)

1-3: グローバル変数の使用を避けてください。

SpriteLoader がグローバルスコープで定義されています。コーディングガイドラインに従い、IIFE(即時実行関数式)やモジュールパターンを使用して名前空間を保護することを推奨します。

-// スプライトローダー(ピクセルアート生成)
-const SpriteLoader = {
-  sprites: {},
+// スプライトローダー(ピクセルアート生成)
+(function(global) {
+  const SpriteLoader = {
+    sprites: {},
+    // ... 既存のコード ...
+  };
+  global.SpriteLoader = SpriteLoader;
+})(window);

または ES モジュールの使用を検討してください。

Based on coding guidelines, グローバル変数は使用しない。

super-mario-bros-1-1-classic/js/entities.js (2)

1-2: グローバルスコープでのクラス定義。

EntityBlockItem クラスがグローバルスコープで定義されています。他のゲームとの名前衝突を防ぐため、モジュールパターンまたは ES モジュールでカプセル化することを検討してください。

Based on coding guidelines, グローバル変数は使用しない。


21-29: deltaTime パラメータが未使用。

update(deltaTime) メソッドで deltaTime を受け取っていますが、内部で使用されていません。フレームレート独立の更新が意図されている場合は、アニメーションや物理処理で活用を検討してください。

super-mario-bros-1-1-classic/js/level.js (2)

1-2: グローバルスコープでのクラス定義。

Level クラスがグローバルスコープで定義されています。モジュールパターンの使用を検討してください。

Based on coding guidelines, グローバル変数は使用しない。


406-422: getEntitiesInRange の重複呼び出し。

同じパラメータで getEntitiesInRange を3回呼び出しています。1回の呼び出しで結果をキャッシュすることでパフォーマンスを改善できます:

-   // ブロックの描画
-   const visibleBlocks = this.getEntitiesInRange(camera.x, GAME_CONSTANTS.CANVAS_WIDTH).blocks;
-   visibleBlocks.forEach((block) => {
-     block.render(ctx, camera);
-   });
-
-   // 敵の描画
-   const visibleEnemies = this.getEntitiesInRange(camera.x, GAME_CONSTANTS.CANVAS_WIDTH).enemies;
-   visibleEnemies.forEach((enemy) => {
-     enemy.render(ctx, camera);
-   });
-
-   // アイテムの描画
-   const visibleItems = this.getEntitiesInRange(camera.x, GAME_CONSTANTS.CANVAS_WIDTH).items;
-   visibleItems.forEach((item) => {
-     item.render(ctx, camera);
-   });
+   // 可視エンティティを一度に取得
+   const { blocks, enemies, items } = this.getEntitiesInRange(camera.x, GAME_CONSTANTS.CANVAS_WIDTH);
+   
+   blocks.forEach((block) => block.render(ctx, camera));
+   enemies.forEach((enemy) => enemy.render(ctx, camera));
+   items.forEach((item) => item.render(ctx, camera));
super-mario-bros-1-1-classic/js/player.js (2)

1-2: グローバルスコープでのクラス定義。

Player クラスがグローバルスコープで定義されています。モジュールパターンの使用を検討してください。

Based on coding guidelines, グローバル変数は使用しない。


164-167: 大きいマリオのスプライトが未実装。

BIG/FIRE 状態で小さいマリオのスプライトを使用しています。将来的にスプライトを追加する際は、この分岐を更新する必要があります。

この機能の実装を手伝いましょうか?

super-mario-bros-1-1-classic/js/game.js (2)

1-2: グローバルスコープでのクラス定義。

Game クラスがグローバルスコープで定義されています。モジュールパターンの使用を検討してください。

Based on coding guidelines, グローバル変数は使用しない。


197-201: instanceof チェックによる密結合。

enemy instanceof Goomba のチェックは密結合を生みます。代わりにメソッドの存在チェックやポリモーフィズムを使用することを検討してください:

-       if (enemy instanceof Goomba) {
-         enemy.checkDirectionChange(solidBlocks);
-       }
+       if (typeof enemy.checkDirectionChange === 'function') {
+         enemy.checkDirectionChange(solidBlocks);
+       }

これにより、新しい敵タイプを追加する際の変更が容易になります。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c44b620 and 56000ef.

📒 Files selected for processing (18)
  • README.md (1 hunks)
  • index.html (1 hunks)
  • super-mario-bros-1-1-classic/README.md (1 hunks)
  • super-mario-bros-1-1-classic/css/style.css (1 hunks)
  • super-mario-bros-1-1-classic/index.html (1 hunks)
  • super-mario-bros-1-1-classic/js/audio.js (1 hunks)
  • super-mario-bros-1-1-classic/js/camera.js (1 hunks)
  • super-mario-bros-1-1-classic/js/constants.js (1 hunks)
  • super-mario-bros-1-1-classic/js/enemies.js (1 hunks)
  • super-mario-bros-1-1-classic/js/entities.js (1 hunks)
  • super-mario-bros-1-1-classic/js/game.js (1 hunks)
  • super-mario-bros-1-1-classic/js/input.js (1 hunks)
  • super-mario-bros-1-1-classic/js/level.js (1 hunks)
  • super-mario-bros-1-1-classic/js/main.js (1 hunks)
  • super-mario-bros-1-1-classic/js/physics.js (1 hunks)
  • super-mario-bros-1-1-classic/js/player.js (1 hunks)
  • super-mario-bros-1-1-classic/js/spriteLoader.js (1 hunks)
  • super-mario-bros-1-1-classic/js/utils.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
*/js/**/*.js

📄 CodeRabbit inference engine (.cursor/rules/about-this-project.mdc)

ゲーム間で名前衝突を防ぐため、グローバル変数は使用しない

Files:

  • super-mario-bros-1-1-classic/js/camera.js
  • super-mario-bros-1-1-classic/js/main.js
  • super-mario-bros-1-1-classic/js/enemies.js
  • super-mario-bros-1-1-classic/js/physics.js
  • super-mario-bros-1-1-classic/js/utils.js
  • super-mario-bros-1-1-classic/js/audio.js
  • super-mario-bros-1-1-classic/js/player.js
  • super-mario-bros-1-1-classic/js/input.js
  • super-mario-bros-1-1-classic/js/level.js
  • super-mario-bros-1-1-classic/js/entities.js
  • super-mario-bros-1-1-classic/js/spriteLoader.js
  • super-mario-bros-1-1-classic/js/constants.js
  • super-mario-bros-1-1-classic/js/game.js
*/index.html

📄 CodeRabbit inference engine (.cursor/rules/about-this-project.mdc)

*/index.html: 動的コードが必要な場合も、入口は index.html に集約 (モジュール分割は js/ 内)
外部ライブラリは CDN 参照を推奨 (ローカル配置も可)
index.html にゲームロジックを実装 (必要に応じて js/・css/ を参照)

各ゲームは index.html から開始する(エントリーポイント)

Files:

  • super-mario-bros-1-1-classic/index.html
**/*.html

📄 CodeRabbit inference engine (CLAUDE.md)

外部ライブラリはCDN参照を推奨する

Files:

  • super-mario-bros-1-1-classic/index.html
  • index.html
README*

📄 CodeRabbit inference engine (.cursor/rules/coding-rule.mdc)

README に成果物の概要を記載

Files:

  • README.md
🧠 Learnings (6)
📚 Learning: 2025-07-20T03:15:07.280Z
Learnt from: CR
Repo: naoto714714/browser-games PR: 0
File: .cursor/rules/about-this-project.mdc:0-0
Timestamp: 2025-07-20T03:15:07.280Z
Learning: Applies to */index.html : index.html にゲームロジックを実装 (必要に応じて js/・css/ を参照)

Applied to files:

  • super-mario-bros-1-1-classic/index.html
  • super-mario-bros-1-1-classic/README.md
  • super-mario-bros-1-1-classic/js/main.js
  • index.html
  • super-mario-bros-1-1-classic/css/style.css
  • super-mario-bros-1-1-classic/js/game.js
📚 Learning: 2025-07-27T03:49:03.596Z
Learnt from: CR
Repo: naoto714714/browser-games PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-07-27T03:49:03.596Z
Learning: Applies to */index.html : 各ゲームは `index.html` から開始する(エントリーポイント)

Applied to files:

  • super-mario-bros-1-1-classic/index.html
  • super-mario-bros-1-1-classic/README.md
  • super-mario-bros-1-1-classic/js/main.js
  • index.html
  • super-mario-bros-1-1-classic/css/style.css
  • super-mario-bros-1-1-classic/js/game.js
📚 Learning: 2025-07-20T03:15:07.280Z
Learnt from: CR
Repo: naoto714714/browser-games PR: 0
File: .cursor/rules/about-this-project.mdc:0-0
Timestamp: 2025-07-20T03:15:07.280Z
Learning: Applies to */index.html : 動的コードが必要な場合も、入口は index.html に集約 (モジュール分割は js/ 内)

Applied to files:

  • super-mario-bros-1-1-classic/index.html
  • super-mario-bros-1-1-classic/js/main.js
📚 Learning: 2025-07-20T03:15:07.280Z
Learnt from: CR
Repo: naoto714714/browser-games PR: 0
File: .cursor/rules/about-this-project.mdc:0-0
Timestamp: 2025-07-20T03:15:07.280Z
Learning: 新規ゲーム追加時は <ゲーム名>/ ディレクトリを作成し、index.html とREADME.mdを配置

Applied to files:

  • super-mario-bros-1-1-classic/index.html
  • super-mario-bros-1-1-classic/js/main.js
  • index.html
📚 Learning: 2025-07-20T03:15:07.280Z
Learnt from: CR
Repo: naoto714714/browser-games PR: 0
File: .cursor/rules/about-this-project.mdc:0-0
Timestamp: 2025-07-20T03:15:07.280Z
Learning: Applies to */js/**/*.js : ゲーム間で名前衝突を防ぐため、グローバル変数は使用しない

Applied to files:

  • super-mario-bros-1-1-classic/js/main.js
  • super-mario-bros-1-1-classic/js/utils.js
  • super-mario-bros-1-1-classic/js/constants.js
📚 Learning: 2025-07-20T03:15:07.280Z
Learnt from: CR
Repo: naoto714714/browser-games PR: 0
File: .cursor/rules/about-this-project.mdc:0-0
Timestamp: 2025-07-20T03:15:07.280Z
Learning: Applies to common/js/**/*.js : 共通ユーティリティが必要な場合は /common/js/ などに配置し、各ゲームは相対パスで参照

Applied to files:

  • super-mario-bros-1-1-classic/js/utils.js
🧬 Code graph analysis (10)
super-mario-bros-1-1-classic/js/enemies.js (2)
super-mario-bros-1-1-classic/js/constants.js (3)
  • DIRECTION (108-111)
  • GAME_CONSTANTS (2-105)
  • ENEMY_TYPES (127-130)
super-mario-bros-1-1-classic/js/physics.js (1)
  • Physics (2-198)
super-mario-bros-1-1-classic/js/physics.js (2)
super-mario-bros-1-1-classic/js/constants.js (1)
  • GAME_CONSTANTS (2-105)
super-mario-bros-1-1-classic/js/utils.js (1)
  • Utils (2-135)
super-mario-bros-1-1-classic/js/utils.js (1)
super-mario-bros-1-1-classic/js/constants.js (1)
  • GAME_CONSTANTS (2-105)
super-mario-bros-1-1-classic/js/audio.js (1)
super-mario-bros-1-1-classic/js/utils.js (1)
  • Utils (2-135)
super-mario-bros-1-1-classic/js/player.js (1)
super-mario-bros-1-1-classic/js/constants.js (3)
  • GAME_CONSTANTS (2-105)
  • DIRECTION (108-111)
  • ITEM_TYPES (133-138)
super-mario-bros-1-1-classic/js/input.js (1)
bird-and-beans/js/input.js (1)
  • InputManager (1-53)
super-mario-bros-1-1-classic/js/level.js (2)
super-mario-bros-1-1-classic/js/constants.js (4)
  • GAME_CONSTANTS (2-105)
  • BLOCK_TYPES (114-124)
  • ENEMY_TYPES (127-130)
  • ITEM_TYPES (133-138)
super-mario-bros-1-1-classic/js/spriteLoader.js (3)
  • x (30-30)
  • y (29-29)
  • brick (157-174)
super-mario-bros-1-1-classic/js/entities.js (3)
super-mario-bros-1-1-classic/js/spriteLoader.js (3)
  • x (30-30)
  • y (29-29)
  • SpriteLoader (2-255)
super-mario-bros-1-1-classic/js/constants.js (4)
  • DIRECTION (108-111)
  • GAME_CONSTANTS (2-105)
  • BLOCK_TYPES (114-124)
  • ITEM_TYPES (133-138)
super-mario-bros-1-1-classic/js/physics.js (1)
  • Physics (2-198)
super-mario-bros-1-1-classic/js/spriteLoader.js (1)
super-mario-bros-1-1-classic/js/main.js (1)
  • canvas (6-6)
super-mario-bros-1-1-classic/js/game.js (7)
bird-and-beans/js/game.js (1)
  • Game (10-156)
super-mario-bros-1-1-classic/js/main.js (1)
  • canvas (6-6)
super-mario-bros-1-1-classic/js/spriteLoader.js (1)
  • canvas (21-21)
super-mario-bros-1-1-classic/js/constants.js (3)
  • GAME_CONSTANTS (2-105)
  • ITEM_TYPES (133-138)
  • BLOCK_TYPES (114-124)
bird-and-beans/js/audio.js (1)
  • AudioManager (3-68)
super-mario-bros-1-1-classic/js/physics.js (1)
  • Physics (2-198)
super-mario-bros-1-1-classic/js/utils.js (1)
  • Utils (2-135)
🪛 Biome (2.1.2)
super-mario-bros-1-1-classic/css/style.css

[error] 88-88: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

image-rendering is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)


[error] 159-160: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

image-rendering is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🪛 markdownlint-cli2 (0.18.1)
super-mario-bros-1-1-classic/README.md

55-55: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (12)
README.md (1)

7-10: クラシック版エントリ追加は問題ありません

既存セクションとスタイルが揃っており、概要テキストとリンク先 (/super-mario-bros-1-1-classic/) も妥当です。README に新しい成果物の概要がきちんと追記されていて良いと思います。

index.html (1)

98-102: ゲームカード追加の構成は良さそうです

  • 既存カードと同じマークアップ・クラス構成で、デザイン統一が保たれています。
  • リンク先 ./super-mario-bros-1-1-classic/ も新ディレクトリ構成と一致しています。

トップレベルの index.html からクラシック版に遷移できるようになっており、プロジェクトのルールにも沿っていると思います。

super-mario-bros-1-1-classic/index.html (1)

1-48: ゲーム用 index.html の構成はルールに沿っています

  • #gameCanvas, #startScreen, #gameOverScreen など、main.jsGame から参照される要素がすべて定義されています。
  • スクリプトも constants.jsutils.js → … → main.js の順で読み込んでおり、依存関係的にも自然です。
  • 「入口は index.html に集約し、ロジックは js/ に分割」というリポジトリルールにも適合していると思います。

特に問題になる点は見当たりません。

super-mario-bros-1-1-classic/js/enemies.js (2)

63-70: 踏みつけ判定のロジックは妥当ですが、エッジケースに注意。

プレイヤーの前フレーム位置を使用した踏みつけ判定は適切です。ただし、高速落下時(velocityYが大きい場合)に判定が不安定になる可能性があります。必要に応じて、より堅牢な判定方法を検討してください。


96-101: This concern is incorrect — animationTimer is properly initialized.

animationTimer is initialized to 0 in the Entity class constructor (super-mario-bros-1-1-classic/js/entities.js), which Goomba inherits through Enemy. The property will work as expected. No initialization issue exists.

super-mario-bros-1-1-classic/js/physics.js (1)

37-95: タイル衝突解決のロジックは適切に実装されています。

水平・垂直を分離した衝突解決は標準的なアプローチです。最初の衝突でbreakしているため、高速移動時のトンネリングが発生する可能性がありますが、このゲームの規模では許容範囲です。

super-mario-bros-1-1-classic/js/spriteLoader.js (2)

19-61: LGTM!

createCanvasgetColor の実装は正確で、ピクセルアートのレンダリングに適切です。未知の色コードに対するマゼンタのフォールバックも良いデバッグ手法です。


63-254: LGTM!

スプライト作成メソッドは適切に構造化されており、16x16のピクセルデータが正しく定義されています。getSprite アクセサも null セーフティを提供しています。

super-mario-bros-1-1-classic/js/entities.js (1)

235-247: LGTM!

Item クラスの実装は適切です。アイテムタイプに応じた動作設定と収集処理が正しく分離されています。

super-mario-bros-1-1-classic/js/level.js (1)

26-51: LGTM!

地面生成ロジックは正確で、穴の作成も適切に処理されています。タイル座標の計算も正しいです。

super-mario-bros-1-1-classic/js/player.js (1)

101-117: LGTM!

ジャンプ実装は適切です。コヨーテタイムとジャンプバッファの併用により、快適な操作感が実現されています。

super-mario-bros-1-1-classic/js/game.js (1)

395-426: LGTM!

HUD 更新と描画処理は適切に実装されています。null チェックによる防御的プログラミングと、条件付きデバッグ情報の表示が良いです。

Comment on lines +1 to +12
// 音響管理クラス(Web Audio API使用)
class AudioManager {
constructor() {
this.audioContext = null;
this.sounds = {};
this.musicVolume = 0.5;
this.sfxVolume = 0.7;
this.enabled = true;

this.initAudioContext();
this.createSounds();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

グローバルクラス宣言とプロパティ初期化の問題

AudioManagerがグローバルスコープで宣言されており、コーディングガイドラインに違反しています。また、musicEnabledプロパティがコンストラクタで初期化されていません。

 class AudioManager {
   constructor() {
     this.audioContext = null;
     this.sounds = {};
     this.musicVolume = 0.5;
     this.sfxVolume = 0.7;
     this.enabled = true;
+    this.musicEnabled = false;

     this.initAudioContext();
     this.createSounds();
   }
🤖 Prompt for AI Agents
In super-mario-bros-1-1-classic/js/audio.js around lines 1-12, the AudioManager
class is currently declared in the global scope and the constructor omits
initialization of the musicEnabled property; fix this by removing the global
exposure (declare the class as a module-local export — e.g., export the class or
wrap it in a module/namespace so it isn’t placed on window/global) and add an
explicit this.musicEnabled = <boolean> initialization in the constructor (set to
the intended default, e.g., true or false).

Comment on lines +180 to +215
// BGM(簡易版)
playBGM() {
if (!this.enabled || !this.audioContext) {
return;
}

// マリオのメインテーマの一部(プロシージャル)
const melody = [
659, 659, 0, 659, 0, 523, 659, 0, 784, 0, 0, 392, 0, 0, 523, 0, 0, 392, 0, 0, 330, 0, 0, 440, 0, 494, 0, 466, 0,
440, 0, 392, 659, 784, 880, 0, 698, 784, 0, 659, 0, 523, 587, 523,
];

let index = 0;
const playNote = () => {
if (index >= melody.length) {
index = 0; // ループ
}

const frequency = melody[index];
if (frequency > 0) {
this.createTone(frequency, 0.3, 'square')();
}

index++;
setTimeout(playNote, 200);
};

if (this.musicEnabled) {
playNote();
}
}

// BGM停止
stopBGM() {
this.musicEnabled = false;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

BGMループが正しく停止できず、musicEnabledチェックに問題があります。

  1. Line 207でthis.musicEnabledをチェックしていますが、コンストラクタで初期化されていないため常にundefined(falsy)となり、BGMが再生されません。
  2. setTimeoutの参照を保持していないため、stopBGM()を呼んでもタイマーチェーンを停止できません。
+  // BGMタイマーの参照
+  bgmTimeoutId = null;

   // BGM(簡易版)
   playBGM() {
     if (!this.enabled || !this.audioContext) {
       return;
     }

+    this.musicEnabled = true;
+
     // マリオのメインテーマの一部(プロシージャル)
     const melody = [
       659, 659, 0, 659, 0, 523, 659, 0, 784, 0, 0, 392, 0, 0, 523, 0, 0, 392, 0, 0, 330, 0, 0, 440, 0, 494, 0, 466, 0,
       440, 0, 392, 659, 784, 880, 0, 698, 784, 0, 659, 0, 523, 587, 523,
     ];

     let index = 0;
     const playNote = () => {
+      if (!this.musicEnabled) {
+        return;
+      }
       if (index >= melody.length) {
         index = 0; // ループ
       }

       const frequency = melody[index];
       if (frequency > 0) {
         this.createTone(frequency, 0.3, 'square')();
       }

       index++;
-      setTimeout(playNote, 200);
+      this.bgmTimeoutId = setTimeout(playNote, 200);
     };

-    if (this.musicEnabled) {
-      playNote();
-    }
+    playNote();
   }

   // BGM停止
   stopBGM() {
     this.musicEnabled = false;
+    if (this.bgmTimeoutId) {
+      clearTimeout(this.bgmTimeoutId);
+      this.bgmTimeoutId = null;
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// BGM(簡易版)
playBGM() {
if (!this.enabled || !this.audioContext) {
return;
}
// マリオのメインテーマの一部(プロシージャル)
const melody = [
659, 659, 0, 659, 0, 523, 659, 0, 784, 0, 0, 392, 0, 0, 523, 0, 0, 392, 0, 0, 330, 0, 0, 440, 0, 494, 0, 466, 0,
440, 0, 392, 659, 784, 880, 0, 698, 784, 0, 659, 0, 523, 587, 523,
];
let index = 0;
const playNote = () => {
if (index >= melody.length) {
index = 0; // ループ
}
const frequency = melody[index];
if (frequency > 0) {
this.createTone(frequency, 0.3, 'square')();
}
index++;
setTimeout(playNote, 200);
};
if (this.musicEnabled) {
playNote();
}
}
// BGM停止
stopBGM() {
this.musicEnabled = false;
}
// BGMタイマーの参照
bgmTimeoutId = null;
// BGM(簡易版)
playBGM() {
if (!this.enabled || !this.audioContext) {
return;
}
this.musicEnabled = true;
// マリオのメインテーマの一部(プロシージャル)
const melody = [
659, 659, 0, 659, 0, 523, 659, 0, 784, 0, 0, 392, 0, 0, 523, 0, 0, 392, 0, 0, 330, 0, 0, 440, 0, 494, 0, 466, 0,
440, 0, 392, 659, 784, 880, 0, 698, 784, 0, 659, 0, 523, 587, 523,
];
let index = 0;
const playNote = () => {
if (!this.musicEnabled) {
return;
}
if (index >= melody.length) {
index = 0; // ループ
}
const frequency = melody[index];
if (frequency > 0) {
this.createTone(frequency, 0.3, 'square')();
}
index++;
this.bgmTimeoutId = setTimeout(playNote, 200);
};
playNote();
}
// BGM停止
stopBGM() {
this.musicEnabled = false;
if (this.bgmTimeoutId) {
clearTimeout(this.bgmTimeoutId);
this.bgmTimeoutId = null;
}
}

Comment on lines +153 to +184
// ブロックが叩かれた時の処理
onHit(player) {
if (this.hit) {
return null;
}

this.hit = true;
this.bumpAnimation = 10; // バンプアニメーション開始

if (this.type === BLOCK_TYPES.BRICK) {
if (player.powerState === GAME_CONSTANTS.PLAYER_STATE.SMALL) {
// 小さいマリオは壊せない
return null;
} else {
// 大きいマリオは壊せる
this.broken = true;
this.destroy();
return { type: 'break', points: 50 };
}
} else if (this.type === BLOCK_TYPES.QUESTION) {
this.spriteKey = 'brick';
if (this.item) {
const itemResult = this.spawnItem();
return itemResult;
} else {
// コインを出す
return { type: 'coin', points: GAME_CONSTANTS.ITEM.COIN.POINTS };
}
}

return null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

小さいマリオがレンガブロックを叩いた時のバグ。

Line 159 で this.hit = true を設定した後、Line 163-165 で小さいマリオはブロックを壊せないため null を返しています。しかし、hit フラグが既に true になっているため、小さいマリオは同じブロックを再度叩けなくなります。

レンガブロックの場合は、壊れた時のみ hittrue にすべきです:

  onHit(player) {
    if (this.hit) {
      return null;
    }

-   this.hit = true;
    this.bumpAnimation = 10; // バンプアニメーション開始

    if (this.type === BLOCK_TYPES.BRICK) {
      if (player.powerState === GAME_CONSTANTS.PLAYER_STATE.SMALL) {
        // 小さいマリオは壊せない
        return null;
      } else {
        // 大きいマリオは壊せる
+       this.hit = true;
        this.broken = true;
        this.destroy();
        return { type: 'break', points: 50 };
      }
    } else if (this.type === BLOCK_TYPES.QUESTION) {
+     this.hit = true;
      this.spriteKey = 'brick';
🤖 Prompt for AI Agents
In super-mario-bros-1-1-classic/js/entities.js around lines 153-184, the code
currently sets this.hit = true unconditionally which prevents small Mario from
re-hitting a brick; change the logic so this.hit is only set when the block has
been consumed/processed: keep this.bumpAnimation = 10 as-is, but remove the
unconditional this.hit = true and instead set this.hit = true inside the BRICK
branch only when the brick is actually broken, and set this.hit = true inside
the QUESTION branch when an item/coin is spawned (after spawnItem or coin result
is determined) so blocks that should remain hittable by small Mario stay
hittable.

Comment on lines +86 to +94
// ゲームループ
gameLoop() {
if (this.state !== GAME_CONSTANTS.GAME_STATE.PLAYING) {
return;
}

const currentTime = performance.now();
this.deltaTime = (currentTime - this.lastFrameTime) / 1000;
this.lastFrameTime = currentTime;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

初回フレームの deltaTime が不正確。

lastFrameTime が 0 で初期化されているため、最初のフレームで deltaTime がページ読み込みからの経過時間になり、物理演算に異常が発生する可能性があります。

  // ゲーム開始
  startGame() {
    this.state = GAME_CONSTANTS.GAME_STATE.PLAYING;
    document.getElementById('startScreen').classList.add('hidden');

    // ゲームオブジェクトを初期化
    this.initializeGame();

    // 音響を有効化
    this.audioManager.enableAudio();

+   // フレーム時間を初期化
+   this.lastFrameTime = performance.now();

    // ゲームループ開始
    this.gameLoop();
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// ゲームループ
gameLoop() {
if (this.state !== GAME_CONSTANTS.GAME_STATE.PLAYING) {
return;
}
const currentTime = performance.now();
this.deltaTime = (currentTime - this.lastFrameTime) / 1000;
this.lastFrameTime = currentTime;
// ゲーム開始
startGame() {
this.state = GAME_CONSTANTS.GAME_STATE.PLAYING;
document.getElementById('startScreen').classList.add('hidden');
// ゲームオブジェクトを初期化
this.initializeGame();
// 音響を有効化
this.audioManager.enableAudio();
// フレーム時間を初期化
this.lastFrameTime = performance.now();
// ゲームループ開始
this.gameLoop();
}
🤖 Prompt for AI Agents
In super-mario-bros-1-1-classic/js/game.js around lines 86 to 94, the
first-frame deltaTime is incorrect because lastFrameTime is initialized to 0;
fix by initializing lastFrameTime to performance.now() when the game enters
PLAYING (or, in gameLoop, detect lastFrameTime === 0 and set deltaTime = 0 and
lastFrameTime = performance.now() before using it) so the first frame uses a
sensible delta (0) instead of elapsed time since page load.

Comment on lines +125 to +135
// ゲーム開始(スタート画面から)
if (this.state === GAME_CONSTANTS.GAME_STATE.START && input.jumpJustPressed) {
this.startGame();
return;
}

// ゲームオーバー画面からリスタート
if (this.state === GAME_CONSTANTS.GAME_STATE.GAME_OVER && input.jumpJustPressed) {
this.restartGame();
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Check for event listeners and input handling in the super-mario game
rg -n "addEventListener|keydown|keypress|click" super-mario-bros-1-1-classic/js/

Repository: naoto714714/browser-games

Length of output: 1499


🏁 Script executed:

# Get the full game.js file to understand the control flow
wc -l super-mario-bros-1-1-classic/js/game.js

Repository: naoto714714/browser-games

Length of output: 112


🏁 Script executed:

# Check for main.js or input manager
find super-mario-bros-1-1-classic -name "*.js" -type f

Repository: naoto714714/browser-games

Length of output: 619


🏁 Script executed:

# Read game.js around the gameLoop area to understand the control flow
sed -n '80,100p' super-mario-bros-1-1-classic/js/game.js

Repository: naoto714714/browser-games

Length of output: 481


🏁 Script executed:

# Read game.js around lines 125-135 to see handleInput in context
sed -n '115,145p' super-mario-bros-1-1-classic/js/game.js

Repository: naoto714714/browser-games

Length of output: 786


🏁 Script executed:

# Read main.js to understand the event listener setup
cat -n super-mario-bros-1-1-classic/js/main.js

Repository: naoto714714/browser-games

Length of output: 3006


The handleInput checks for START/GAME_OVER states (lines 126-133) are unreachable dead code.

While input handling during START and GAME_OVER states functions correctly—main.js has separate event listeners (lines 28-42, 45-53) that directly call startGame() and restartGame()—the state checks in handleInput will never execute because gameLoop exits early if state !== PLAYING (lines 88-90).

Remove the unreachable checks for START and GAME_OVER states from handleInput, or restructure to clarify that these states are handled outside of gameLoop.

🤖 Prompt for AI Agents
In super-mario-bros-1-1-classic/js/game.js around lines 125 to 135, the input
checks for START and GAME_OVER are unreachable because gameLoop exits early when
state !== PLAYING; remove the two if blocks that call startGame() and
restartGame() from handleInput, leaving only PLAYING-related input handling, and
add a short comment above handleInput noting that START/GAME_OVER are handled by
main.js event listeners so they are intentionally omitted here.

Comment on lines +119 to +144
// 移動処理の更新
updateMovement() {
// コヨーテタイム(地面から離れた直後でもジャンプ可能)
if (!this.grounded && this.coyoteTime > 0) {
this.coyoteTime--;
}

// ジャンプバッファ(ジャンプボタンを早押ししても有効)
if (this.jumpBufferTime > 0) {
this.jumpBufferTime--;
if (this.grounded) {
this.jump();
}
}

// 着地処理
if (this.grounded && this.jumping) {
this.jumping = false;
this.canJump = true;
}

// 地面から離れた時のコヨーテタイム設定
if (!this.grounded && !this.jumping && this.coyoteTime === 0) {
this.coyoteTime = 5;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

タイマーの二重デクリメントバグ。

coyoteTimejumpBufferTimeupdateMovement()updateTimers() の両方でデクリメントされています。update() が両方を呼び出すため、タイマーが意図した2倍の速度で減少します。

updateTimers() でのデクリメントを削除するか、updateMovement() 内のデクリメントを削除してください:

  // タイマー更新
  updateTimers() {
-   if (this.jumpBufferTime > 0) {
-     this.jumpBufferTime--;
-   }
-   if (this.coyoteTime > 0) {
-     this.coyoteTime--;
-   }
+   // タイマーのデクリメントは updateMovement() で行われるため、
+   // ここでは追加のタイマー処理のみ
  }

または updateMovement() からデクリメント処理を削除して updateTimers() に統合してください。

Also applies to: 187-195

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant