Debugging
Techniques for debugging game code using browser developer tools
Table of Contents
- Console Debugging
- Hit Box Visualization
- Source-Level Debugging
- Network Debugging
- Application Debugging
- Element Inspection
Console Debugging
Console debugging is the foundation of tracking game state and identifying issues. Using console.log() strategically throughout your code allows you to monitor variables, method calls, and game flow in real-time.
Strategic Logging in Update Methods
In my game projects, I use console.log() to track collision detection and state changes:
/**
* Example from Guard.js - tracking collision and boundary behavior
*/
update() {
// Update begins by drawing the object
this.draw();
if (this.spriteData && typeof this.spriteData.update === 'function') {
this.spriteData.update.call(this);
}
// Check for collision with the player
if (!this.playerDestroyed && this.collisionChecks()) {
this.handleCollisionEvent();
}
this.position.y += this.velocity.y; // update position
// Ensure the object stays within the canvas boundaries
this.stayWithinCanvas();
}
stayWithinCanvas() {
// Bottom of the canvas
if (this.position.y + this.height > this.gameEnv.innerHeight) {
this.position.y = this.gameEnv.innerHeight - this.height;
this.velocity.y *= -1; // Reverse vertical velocity to create a "bounce" effect
console.log(this.velocity.y); // ← Debug: Track velocity changes
}
// ...more boundary checks...
}
handleCollisionEvent() {
var player = this.gameEnv.gameObjects.find(obj => obj instanceof Player);
console.log("Collision has occurred, player has been destroyed."); // ← Debug: Log collision events
player.destroy();
this.playerDestroyed = true;
}
How to Use Console Logging:
- Open DevTools with
F12or right-click → Inspect - Go to the Console tab
- As your game runs, logs will appear showing variable values, method calls, and state changes
- Use different log levels:
console.log(),console.warn(),console.error()
Hit Box Visualization
Visualizing collision boundaries helps you understand why collisions are or aren’t being detected. By drawing rectangles around game objects, you can refine your collision detection logic.
Drawing Collision Boundaries
Most game engines can toggle hitbox visualization. This allows you to see the collision rectangles around your game objects:
/**
* Example: Visualizing a collision boundary on the canvas
*/
function drawHitbox(gameObject, context) {
const hitbox = gameObject.collisionData.hit;
// Draw rectangle showing the collision boundary
context.strokeStyle = 'red'; // Red for active collision
context.lineWidth = 2;
context.strokeRect(
hitbox.x,
hitbox.y,
hitbox.width,
hitbox.height
);
}
// In your render loop, conditionally draw hitboxes
if (DEBUG_MODE) {
for (const gameObj of gameEnv.gameObjects) {
drawHitbox(gameObj, context);
}
}
To Toggle Hitbox Display:
- Add a debug flag in your game configuration
- Press a key (like
D) to toggleDEBUG_MODE - Adjust collision rectangle values until collisions work as expected
Source-Level Debugging
Source-level debugging lets you pause code execution and inspect variables at specific points, making it easier to understand complex logic.
Using Breakpoints in DevTools
/**
* Example: Setting a breakpoint to examine collision logic
*/
handleCollisionEvent() {
var player = this.gameEnv.gameObjects.find(obj => obj instanceof Player);
// ← DevTools: Click the line number to set a breakpoint here
console.log("Collision has occurred, player has been destroyed.");
player.destroy();
this.playerDestroyed = true;
}
How to Debug with Breakpoints:
- Open DevTools (
F12) - Go to the Sources tab
- Find your JavaScript file
- Click on the line number to set a breakpoint (a blue marker appears)
- Run your game and trigger the code
- Execution pauses at the breakpoint
- Use the Variables panel to inspect object values
- Click Step Over (or press
F10) to execute line-by-line - Click Resume (or press
F8) to continue execution
Network Debugging
Network debugging helps you track API calls and inspect responses for errors.
Examining Fetch Requests
In my heist-exe project, heistMusic.js checks the fetch response for errors:
async fetchPreviewUrl() {
const response = await fetch(this.endpoint);
if (!response.ok) {
throw new Error('API request failed (' + response.status + ')');
}
const data = await response.json();
// ... rest of the code
}
async startMusic() {
try {
const previewUrl = await this.fetchPreviewUrl();
this.audio = new Audio(previewUrl);
this.audio.play();
} catch (error) {
console.warn('Background music: failed to start', error);
}
}
How to Debug Network Requests:
- Open DevTools (
F12) → Network tab - Trigger the API call
- Click on the request to inspect:
- Status: 200 (success), 404 (not found), 500 (error)
- Response: The data returned from the API
- Headers: Request/response metadata
Application Debugging
Application debugging lets you inspect browser storage where game state is persisted—cookies, localStorage, and sessionStorage.
Inspecting Stored Data
From my local-storage project:
/**
* Example: Storing and retrieving player data
*/
// Store coins collected
const coinsCollected = parseInt(localStorage.getItem('coinsCollected') || '0');
const newTotal = coinsCollected + this.value;
localStorage.setItem('coinsCollected', newTotal);
// Store player name in session storage
const playerName = sessionStorage.getItem('playerName');
if (!playerName) {
playerName = prompt('Enter your name for the leaderboard:') || 'Anonymous';
sessionStorage.setItem('playerName', playerName);
}
How to Debug Application Storage:
- Open DevTools (
F12) - Go to the Application tab
- Look at the left sidebar:
- LocalStorage: Persists across browser sessions
- SessionStorage: Clears when you close the tab
- Cookies: Authentication and user tracking data
- Select an entry to see all stored data
- You can edit, delete, or clear storage manually for testing
- Use the search function to find specific keys
Element Inspection
Element inspection helps you understand the DOM structure, check styles, and inspect game canvas properties.
Inspecting Canvas and DOM Elements
<!-- Example: Canvas element in your HTML -->
<canvas id="gameCanvas" width="800" height="600"></canvas>
<!-- DevTools allows you to inspect these elements -->
How to Inspect Elements:
- Open DevTools (
F12) - Go to the Elements tab
- Click the Select Element button (top-left arrow icon)
- Click on any element in your game or page
- The DevTools will show:
- HTML structure: How the element is nested
- Styles: All CSS applied to the element
- Box Model: Padding, margin, borders, dimensions
- Event Listeners: JavaScript events attached to the element
Inspecting Game Object State
You can also inspect JavaScript objects in the Console:
// In your console, type:
gameEnv.gameObjects // View all game objects
gameEnv.gameObjects[0] // Inspect a specific object
player.position // Check player's current position
player.velocity // Check velocity values
This allows you to query your game state in real-time without adding console logs everywhere.
Debugging Workflow Example
Here’s how to debug a collision issue:
- Console Debugging: Add
console.log()to track collision detection - Element Inspection: Use the console to check
player.positionandenemy.position - Hit Box Visualization: Enable debug mode to see collision rectangles
- Source-Level Debugging: Set a breakpoint in
handleCollisionEvent() - Step Through: Use Step Over to execute line-by-line
- Application Debugging: Check if game state is being saved correctly
By combining these techniques, you can quickly identify and fix bugs in your game!