Debugging

Table of Contents

Debugging is the process of finding and fixing problems in your code. Every developer spends a huge amount of time debugging — the key is knowing which tools to use and where to look.

Console Debugging

console.log is the most basic and most used debugging tool.

Code Runner Challenge

Console Debugging

View IPYNB Source
%%js

//CODE_RUNNER: Console Debugging


class Player {
    constructor(data) {
        this.x         = data.x;
        this.y         = data.y;
        this.velocityY = 0;
        this.health    = 100;
        this.isJumping = false;
        this.state     = "idle";
    }

    update() {
        // Strategic log — tracks position and velocity every frame
        console.log(`[update] x: ${this.x}, y: ${this.y.toFixed(1)}, velocityY: ${this.velocityY.toFixed(2)}, state: ${this.state}`);

        this.velocityY += 0.4;  // gravity
        this.y         += this.velocityY;
    }

    handleCollision(other, direction) {
        // Strategic log — tracks what was hit and from which direction
        console.log(`[collision] hit: ${other.label}, direction: ${direction}, health before: ${this.health}`);

        if (other.label === "Enemy" && direction === "side") {
            this.health -= other.damage;
            this.state   = "hurt";
        }

        // Strategic log — tracks outcome after collision logic runs
        console.log(`[collision] health after: ${this.health}, state: ${this.state}`);
    }
}

const player = new Player({ x: 100, y: 300 });

console.log("--- Simulating 3 frames ---");
player.update();
player.update();
player.update();

console.log("\n--- Simulating a collision ---");
player.handleCollision({ label: "Enemy", damage: 20 }, "side");
player.handleCollision({ label: "Platform", damage: 0 }, "top");
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Explanation - These console logs help show what the game is doing while it runs. The update log shows the player’s movement changing over time. The collision log shows what the player hit and how health changed. This makes bugs easier to find because you can see the important values in the console.

Hitbox visualization

A hit box is the invisible rectangle the game uses for collision detection. When collisions feel wrong — the player dies before touching an enemy, or walks through a platform — the hit box is usually misaligned. Visualizing it draws the rectangle on screen so you can see exactly what the game thinks.

Code Runner Challenge

Hitbox visualization

View IPYNB Source
%%js

//CODE_RUNNER: Hitbox visualization

// Run this to see hit box data being calculated and logged

class GameObject {
    constructor(data) {
        this.x      = data.x;
        this.y      = data.y;
        this.width  = data.width;
        this.height = data.height;
        this.label  = data.label;
        this.showHitBox = false; // toggle this to visualize
    }

    // Returns the collision rectangle
    getHitBox() {
        return {
            left:   this.x,
            right:  this.x + this.width,
            top:    this.y,
            bottom: this.y + this.height,
        };
    }

    // In a real game this draws a red rectangle on the canvas
    // Here we log what it would draw
    drawHitBox() {
        if (!this.showHitBox) return;
        const hb = this.getHitBox();
        console.log(`[hitbox] ${this.label} — left:${hb.left} right:${hb.right} top:${hb.top} bottom:${hb.bottom}`);
    }

    // Check overlap with another object's hit box
    isOverlapping(other) {
        const a = this.getHitBox();
        const b = other.getHitBox();
        return a.left < b.right &&
               a.right > b.left &&
               a.top < b.bottom &&
               a.bottom > b.top;
    }
}

const player = new GameObject({ x: 100, y: 300, width: 48, height: 48, label: "Player" });
const enemy  = new GameObject({ x: 130, y: 300, width: 40, height: 40, label: "Enemy"  });

// Toggle hit boxes on for debugging
player.showHitBox = true;
enemy.showHitBox  = true;

console.log("--- Hit box positions ---");
player.drawHitBox();
enemy.drawHitBox();

console.log("\n--- Overlap check ---");
const overlapping = player.isOverlapping(enemy);
console.log(`Player and enemy overlapping: ${overlapping}`);

// Move enemy away and check again
enemy.x = 300;
console.log(`\nAfter moving enemy to x=300 — overlapping: ${player.isOverlapping(enemy)}`);
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Explanation - A hitbox is the invisible box the game uses for collisions. This example shows the box around each object and checks if two boxes are touching. If the hitbox does not match the sprite, the player might get hit too early or pass through something, so this is a useful debugging check.

Source Debugging

The DevTools Sources tab lets you pause execution at any line of code and step through it one line at a time. This is more powerful than console.log because you can inspect every variable at the exact moment the code is paused — without adding any extra logging.

// Run this  then open DevTools Sources tab and set a breakpoint on handleCollision

class Player {
    constructor(data) {
        this.x      = data.x;
        this.y      = data.y;
        this.health = 100;
        this.state  = "idle";
    }

    handleCollision(other, direction) {
        // Set your breakpoint on the line below in DevTools Sources tab
        // Execution will pause here and you can inspect: other, direction, this.health
        let tookDamage = false;

        if (other.label === "Enemy" && direction === "side") {
            this.health -= other.damage;
            this.state   = "hurt";
            tookDamage   = true;
        }

        // Step through to here and check tookDamage in the Scope panel
        console.log(`tookDamage: ${tookDamage}, health: ${this.health}`);
        return tookDamage;
    }
}

const player = new Player({ x: 100, y: 300 });
player.handleCollision({ label: "Enemy", damage: 20 }, "side");
player.handleCollision({ label: "Platform", damage: 0 }, "top");

Explanation - A breakpoint pauses the code right where you want to inspect it. When the code pauses, Inspect shows the current values of the variables. This helps you catch problems like the wrong health value, the wrong collision direction, or an object not being what you expected.

Network Debugging

The DevTools Network tab records every HTTP request the page makes. For the leaderboard, this shows you the fetch POST and GET calls, the exact data sent, the server’s response, and any errors like CORS or 404.

The Network tab shows what happened when the page talked to the backend. If the leaderboard does not save, you can check the request status. A login problem, wrong URL, or backend error will show up there. You can also check the payload to see what data was sent.

Aplication Debugging

The DevTools Application tab shows everything stored in the browser — localStorage, sessionStorage, and cookies. The leaderboard uses localStorage as a fallback when the backend is unavailable, so this tab lets you verify scores are actually being saved locally.

Code Runner Challenge

Application Debugging

View IPYNB Source
%%js

//CODE_RUNNER: Application Debugging

// Run this to write and read localStorage the same way Leaderboard.js does

const gameName   = "MarioGame";
const storageKey = `score_counter_${gameName}`;

// Write a score to localStorage (same as the fallback in Leaderboard.js)
const entry = {
    id:        `local-${Date.now()}`,
    payload:   { user: "mario", score: 4500, gameName: gameName },
    timestamp: new Date().toISOString()
};

const stored = JSON.parse(localStorage.getItem(storageKey) || "[]");
stored.push(entry);
localStorage.setItem(storageKey, JSON.stringify(stored));

console.log("Score saved to localStorage under key:", storageKey);

// Read it back (same as fetchLeaderboard fallback)
const retrieved = JSON.parse(localStorage.getItem(storageKey) || "[]");
console.log("Retrieved from localStorage:", retrieved.length, "entries");
retrieved.forEach((e, i) => {
    console.log(`${i + 1}. ${e.payload.user}${e.payload.score} pts`);
});

// In DevTools Application tab you can now see this key and its value
console.log("\nNow open DevTools → Application → Local Storage to see this data live");
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Explanation - Local storage lets the browser save small pieces of data. In this example, the game saves score data in the browser and reads it back later. The Application tab in Inspect lets you see that saved data, which is useful when checking if fallback saving is working.

Element Inspection

The DevTools Elements tab shows the full HTML structure of the page while the game runs. You can click on the canvas element or any game UI element and see its exact size, position, and CSS styles — useful for fixing layout issues or verifying the canvas is the right dimensions.

The Elements tab helps you inspect what is actually on the page. If the game canvas is too small, in the wrong place, or missing, you can click it in Inspect and see its size and styles. This helps find layout problems that are caused by HTML or CSS instead of game logic.

Game Status: Not Started