Documentation & Debugging - JSDoc, Comments, Console Logging
How I document code and debug using console, DevTools, and error handling
Documentation & Debugging
Requirements
- JSDoc comments for classes and methods
- Strategic inline comments explaining logic
- Console logging for state tracking
- Error handling with try/catch
1. JSDoc Comments - Class Documentation
GameLevelOutside.js - Comprehensive JSDoc
/**
* GameLevelOutside
*
* Defines the configuration for the Outside mini-game level.
* This class constructs the objects that will exist in the level,
* including the background, player, NPC, barrier, and moving target.
*
* Each object is described with a configuration object that determines
* sprite properties, positioning, animations, and gameplay behavior.
*/
class GameLevelOutside {
/**
* Friendly name of the game level
* @static
* @type {string}
*/
static friendlyName = "Level 1: Castle Grounds";
/**
* Creates a new Outside level configuration.
*
* @param {GameEnvironment} gameEnv - The main game env object
*/
constructor(gameEnv) {
const width = gameEnv.innerWidth;
const height = gameEnv.innerHeight;
const path = gameEnv.path;
// ...
}
}
How it meets the requirement:
- Class Documentation: Describes purpose and structure
- @param Tags: Document parameters with types
- @static: Marks static properties
SpriteSheetCoin.js - Method Documentation
/**
* SpriteSheetCoin extends the basic Coin class to support image/spritesheet rendering.
* Instead of a colored circle, you can now display any image asset (gem, star, etc).
*
* @example
* const gemCoin = new SpriteSheetCoin({
* id: 'gem-coin',
* INIT_POSITION: { x: 0.5, y: 0.5 },
* SCALE_FACTOR: 30,
* value: 5,
* spriteImagePath: '/images/gem.png',
* spriteFrames: { rows: 2, columns: 2, frameIndex: 0 }
* }, gameEnv);
*/
class SpriteSheetCoin extends Coin {
/**
* Load the sprite image asynchronously
*/
loadImage() {
const img = new Image();
// ...
}
/**
* Draw the coin using spritesheet if available, otherwise fall back to colored circle
*/
draw() {
// ...
}
/**
* Draw the sprite image on the canvas
*/
drawSpriteImage() {
// ...
}
}
How it meets the requirement:
- Method Documentation: Each method has JSDoc
- @example: Shows usage pattern
2. Strategic Inline Comments
DeathBarrier.js - Inline Comments Explaining Logic
class DeathBarrier extends Barrier {
constructor(data, gameEnv) {
super(data, gameEnv);
this._hasTriggeredDeath = false;
// Store the level start time - all barriers share this for grace period
if (!DeathBarrier.levelStartTime) {
DeathBarrier.levelStartTime = new Date();
}
}
update() {
// Checks for collisions, if triggered then uses the below code
super.update();
// If the death is already triggered no need to trigger it again
if (this._hasTriggeredDeath) return;
const player = this.gameEnv?.gameObjects?.find(obj => obj.constructor?.name === 'Player');
if (!player || !player.canvas || !this.canvas) return;
this.isCollision(player);
if (this.collisionData?.hit) {
// Check grace period from level start time
const timeSinceLevelStart = new Date() - DeathBarrier.levelStartTime;
// We added a grace period because there was an error where the barrier would kill
// the player before they could even play
if (timeSinceLevelStart < 500) {
console.log('[MazeDebug] Grace period active:', timeSinceLevelStart, 'ms');
return; // we added a grace period to prevent instant death
}
this._hasTriggeredDeath = true;
player.isDead = true;
// Log collision details for debugging
console.log('[MazeDebug] DeathBarrier hit player:', this.canvas?.id || this.id || 'unknown');
console.log('[MazeDebug] Player Position:', player.x, player.y);
try {
showDeathScreen(player, 'You got lost in the maze.');
} catch (error) {
console.error('DeathBarrier failed to show death screen:', error);
this._hasTriggeredDeath = false;
player.isDead = false;
}
}
}
}
How it meets the requirement:
- Grace Period Logic: Explains why 500ms delay is needed
- State Management: Comments explain _hasTriggeredDeath purpose
Ghost.js - Collision Logic Comments
handleCollisionEvent() {
// Prevent duplicate death triggers
if (this._hasTriggeredDeath || this.playerDestroyed) return;
const player = this.getPlayer();
// Check both flags to ensure player is valid and alive
if (!player || player.isDead) return;
// Mark collision as handled and player as dead
this._hasTriggeredDeath = true;
this.playerDestroyed = true;
player.isDead = true;
// Show death screen with appropriate message
showDeathScreen(player, 'The ghost caught you.');
}
How it meets the requirement:
- State Flag Comments: Explains collision tracking logic
3. Console Logging - State Tracking
DeathBarrier.js - Strategic console.log
update() {
if (this._hasTriggeredDeath) return;
const player = this.gameEnv?.gameObjects?.find(obj => obj.constructor?.name === 'Player');
if (!player || !player.canvas || !this.canvas) return;
this.isCollision(player);
if (this.collisionData?.hit) {
const timeSinceLevelStart = new Date() - DeathBarrier.levelStartTime;
// ← Track grace period timing
if (timeSinceLevelStart < 500) {
console.log('[MazeDebug] Grace period active:', timeSinceLevelStart, 'ms');
return;
}
// ← Log collision details
console.log('[MazeDebug] DeathBarrier hit player:', this.canvas?.id || this.id || 'unknown');
console.log('[MazeDebug] Player Position:', player.x, player.y);
}
}
How it meets the requirement:
- Grace Period Logging: Track timing precision
- Collision Logging: Identify which barrier hit player
- Position Logging: Debug player location
SpriteSheetCoin.js - Image Loading Logs
loadImage() {
const img = new Image();
// ← Track successful image load
img.onload = () => {
this.spriteImage = img;
this.isImageLoaded = true;
console.log(`SpriteSheetCoin image loaded: ${this.spriteImagePath}`);
};
// ← Track image load failures
img.onerror = () => {
console.warn(`Failed to load SpriteSheetCoin image: ${this.spriteImagePath}`);
this.isImageLoaded = false;
};
img.src = this.spriteImagePath;
}
How it meets the requirement:
- Load Success: Log when sprites are ready
- Load Failure: Warn when assets fail to load
4. Error Handling - try/catch Blocks
GameLevelMaze.js - NPC Dialog Error Handling
interact: function () {
// Clear any existing dialogue first to prevent duplicates
if (this.dialogueSystem && this.dialogueSystem.isDialogueOpen()) {
this.dialogueSystem.closeDialogue();
}
// Create a new dialogue system if needed - lazy initialization
if (!this.dialogueSystem) {
try { // ← TRY: attempt to create DialogueSystem
this.dialogueSystem = new DialogueSystem();
} catch (error) { // ← CATCH: if creation fails
console.error('Error creating DialogueSystem:', error);
return; // Exit gracefully
}
}
const whattosay = "Welcome to the coolest maze this side of the atlantic ocean, escape or get rekt lol"
try { // ← TRY: display dialogue
this.dialogueSystem.showDialogue(
whattosay,
"mr portensen",
this.spriteData.src,
{
columns: 3,
rows: 4,
frameX: 0,
frameY: 0,
frameWidth: 78,
frameHeight: 108
}
);
this.dialogueSystem.addButtons([
{
text: "Enter the maze",
primary: true,
action: () => {
this.dialogueSystem.closeDialogue();
this.destroy();
}
}
]);
} catch (error) { // ← CATCH: if dialogue display fails
console.error('Error calling showDialogue:', error);
}
}
How it meets the requirement:
- try/catch Blocks: Handle potential errors
- Error Logging: Log caught exceptions
- Graceful Degradation: Continue game if dialog fails
GameLevelOutside.js - Event Listener Error Handling
reaction: function () {
if (this.dialogueSystem) {
this.showReactionDialogue();
} else {
console.log(sir_morty_greeting);
}
},
interact: function () {
try { // ← TRY: attempt AI interaction
AiNpc.showInteraction(this);
} catch (error) { // ← CATCH: fallback if API fails
console.error('Error in AiNpc.showInteraction:', error);
// Show basic dialogue instead of AI response
if (this.dialogueSystem) {
this.dialogueSystem.showDialogue(
this.greeting,
this.id,
this.src
);
}
}
}
How it meets the requirement:
- API Error Handling: Gracefully fail if backend unavailable
- Fallback Logic: Show basic response if AI fails
Summary
✅ JSDoc Comments - Class and method documentation with @param, @example
✅ Inline Comments - Explain grace periods, state flags, collision logic
✅ Console Logging
- Grace period timing tracking
- Collision detection logging
- Image loading status
✅ Error Handling - try/catch for DialogueSystem creation
- try/catch for showDialogue() calls
- Graceful fallbacks when features fail