Testing & Verification - Gameplay, Integration, and Error Handling
How I test collision detection, NPC interactions, level transitions, and API integration
Testing & Verification
Requirements
- Gameplay Testing - Level completion, character interactions, collision detection
- Integration Testing - Level transitions, NPC dialogue, AI responses work together
- API Error Handling - Try/catch blocks for API calls, network error handling
1. Gameplay Testing - Collision and Character Interaction
Collision Detection System
Ghost.js - AI Enemy Collision
Testing Evidence:
class Ghost extends Enemy {
constructor(data, gameEnv) {
super(data, gameEnv);
this.followSpeedFactor = data?.followSpeedFactor ?? 0.4;
this.followStopDistance = data?.followStopDistance ?? 8; // ← Testing parameter
this._hasTriggeredDeath = false;
}
handleCollisionEvent() {
// Tests:
// 1. Did ghost collide with player?
if (this._hasTriggeredDeath || this.playerDestroyed) return; // ← Prevent duplicate trigger
const player = this.getPlayer();
// 2. Is player still in game?
if (!player || player.isDead) return;
// 3. Mark as triggered and show death screen
this._hasTriggeredDeath = true;
this.playerDestroyed = true;
player.isDead = true;
showDeathScreen(player, 'The ghost caught you.');
}
}
Test Cases:
- ✅ Ghost moves toward player correctly
- ✅ Ghost stops at followStopDistance (8 pixels)
- ✅ Collision detection triggers death event once
- ✅ Death screen displays with appropriate message
DeathBarrier.js - Maze Wall Collision
Testing Evidence:
class DeathBarrier extends Barrier {
update() {
super.update();
// Test 1: Prevent duplicate death triggers
if (this._hasTriggeredDeath) return;
const player = this.gameEnv?.gameObjects?.find(obj => obj.constructor?.name === 'Player');
// Test 2: Player and barrier both exist
if (!player || !player.canvas || !this.canvas) return;
this.isCollision(player);
// Test 3: Collision occurred
if (this.collisionData?.hit) {
// Test 4: Grace period prevents instant death
const timeSinceLevelStart = new Date() - DeathBarrier.levelStartTime;
if (timeSinceLevelStart < 500) {
console.log('[MazeDebug] Grace period active:', timeSinceLevelStart, 'ms');
return; // Grace period still active
}
// Test 5: Trigger death event
this._hasTriggeredDeath = true;
player.isDead = true;
console.log('[MazeDebug] DeathBarrier hit player:', this.canvas?.id);
showDeathScreen(player, 'You got lost in the maze.');
}
}
static resetLevelStartTime() {
DeathBarrier.levelStartTime = new Date();
}
}
Test Cases:
- ✅ 19 barriers placed correctly in maze
- ✅ Grace period active for first 500ms
- ✅ Collision detected when player touches barrier
- ✅ Death triggered only once per barrier
- ✅ Player position logged for debugging
2. Integration Testing - Level Transitions & NPC Dialogue
Level Transition - GameLevelOutside → GameLevelArchery → GameLevelMaze
Testing Evidence:
interact: function () {
// Test 1: Clear previous dialogue to prevent duplicates
if (this.dialogueSystem && this.dialogueSystem.isDialogueOpen()) {
this.dialogueSystem.closeDialogue();
}
// Test 2: Initialize dialogue system
if (!this.dialogueSystem) {
this.dialogueSystem = new DialogueSystem();
}
this.dialogueSystem.showDialogue(
"Are you ready to enter the castle?",
"DarkKnight",
this.spriteData.src
);
// Test 3: Add interaction buttons
this.dialogueSystem.addButtons([
{
text: "Start",
primary: true,
action: () => {
this.dialogueSystem.closeDialogue();
// Test 4: Create fade overlay for smooth transition
const fadeOverlay = document.createElement('div');
Object.assign(fadeOverlay.style, {
position: 'fixed',
width: '100%',
height: '100%',
backgroundColor: 'rgba(0, 0, 0, 0.35)',
opacity: '0',
transition: 'opacity 2000ms ease-in-out',
zIndex: '9999'
});
document.body.appendChild(fadeOverlay);
// Test 5: Animate starfield background
// ... starfield animation code ...
// Test 6: Type dialogue during transition
const typeLine = (line) => new Promise((resolve) => {
// Type animation ...
});
// Test 7: Wait for all animations to complete
Promise.all([
runTransitionDialogue(),
sleep(2000)
]).then(() => {
// Test 8: Level transition
gameControl._originalLevelClasses = gameControl.levelClasses;
gameControl.levelClasses = [GameLevelArchery];
gameControl.currentLevelIndex = 0;
gameControl.isPaused = false;
gameControl.transitionToLevel();
});
}
}
]);
}
Test Cases:
- ✅ Dialogue displays without duplicates
- ✅ Fade overlay animates smoothly
- ✅ Starfield parallax displays correctly
- ✅ Typed dialogue completes before level transition
- ✅ Level switches to GameLevelArchery
- ✅ Player can navigate new level without errors
NPC Interaction - Sir Morty AI Integration
Testing Evidence:
const sir_morty_data = {
id: "Sir Morty",
greeting: "Hello! I'm Sir Morty!",
expertise: "default", // ← Backend topic
chatHistory: [], // ← Track conversation
dialogues: [ // ← Random greetings
"Enter the castle if you dare!",
"The Dark Knight awaits inside.",
"I heard there's a treasure in the castle.",
"Beware of the traps in the castle!",
"The castle has stood for centuries."
],
knowledgeBase: { // ← Context for AI
default: [
{ question: "What is inside the castle?", answer: "..." },
{ question: "Who are you?", answer: "..." },
{ question: "How do I win the game?", answer: "..." }
]
},
interact: function () {
// Test 1: Call AI service with knowledge base
AiNpc.showInteraction(this);
// This sends knowledgeBase to backend
// Backend returns: { response: "AI generated answer", confidence: 0.92 }
}
};
Test Cases:
- ✅ AI receives knowledge base context
- ✅ Backend generates relevant responses
- ✅ Dialogue displayed without errors
- ✅ Chat history preserved across interactions
- ✅ Fallback to random greeting if API fails
3. API Error Handling & Network Resilience
GameLevelMaze.js - Dialogue System Error Handling
Testing Evidence:
interact: function () {
// Test 1: Guard against missing DialogueSystem
if (!this.dialogueSystem) {
try {
this.dialogueSystem = new DialogueSystem();
} catch (error) {
console.error('Error creating DialogueSystem:', error);
return; // Test: Gracefully exit on error
}
}
// Test 2: Handle dialogue display errors
try {
this.dialogueSystem.showDialogue(
"Welcome to the maze...",
"mr portensen",
this.spriteData.src,
{
columns: 3,
rows: 4,
frameX: 0,
frameY: 0,
frameWidth: 78,
frameHeight: 108
}
);
// Test 3: Handle button interaction errors
this.dialogueSystem.addButtons([
{
text: "Enter the maze",
primary: true,
action: () => {
try {
this.dialogueSystem.closeDialogue();
this.destroy();
} catch (error) {
console.error('Error closing dialogue or destroying NPC:', error);
}
}
}
]);
} catch (error) {
// Test: Fallback if dialogue display fails
console.error('Error calling showDialogue:', error);
// Game continues without dialogue
}
}
Test Cases:
- ✅ DialogueSystem creation fails gracefully
- ✅ Dialogue display errors caught and logged
- ✅ Game continues if dialogue system unavailable
- ✅ Button callbacks handle errors
GameLevelOutside.js - AI API Error Handling
Testing Evidence:
reaction: function () {
// Test 1: Basic response if dialogue system exists
if (this.dialogueSystem) {
this.showReactionDialogue();
} else {
// Test: Fallback to console if UI unavailable
console.log(sir_morty_greeting);
}
},
interact: function () {
try {
// Test 1: Attempt AI interaction
AiNpc.showInteraction(this);
} catch (error) {
// Test 2: Catch API errors
console.error('Error in AiNpc.showInteraction:', error);
// Test 3: Fallback to basic dialogue
if (this.dialogueSystem) {
this.dialogueSystem.showDialogue(
this.greeting, // Show greeting instead of AI response
this.id,
this.src
);
} else {
console.log(this.greeting);
}
}
}
Test Cases:
- ✅ AI service errors caught and logged
- ✅ Falls back to static greeting if API fails
- ✅ Game continues without breaking
- ✅ User still sees dialogue (AI or fallback)
4. Complete Gameplay Flow Testing
Full Game Loop
Play Sequence:
- Level 1: Castle Grounds (GameLevelOutside)
- ✅ Player spawns at starting position
- ✅ WASD movement controls work
- ✅ Sir Morty NPC responds to E-key interaction
- ✅ Player can change costume at closet
- ✅ Dark Knight triggers level transition
- Transition Animation
- ✅ Fade overlay animates
- ✅ Starfield parallax displays
- ✅ Typed dialogue shows correctly
- ✅ All elements fade out smoothly
- Level 2: The Maze (GameLevelMaze)
- ✅ Player spawns at maze entrance
- ✅ Ghost enemy follows player correctly
- ✅ 19 DeathBarriers placed correctly
- ✅ Grace period prevents instant death
- ✅ Collision detection works for walls
- ✅ NPC dialogue available at maze entrance
- Error Scenarios
- ✅ API timeout: Use fallback dialogue
- ✅ Image load failure: Use placeholder
- ✅ DialogueSystem crash: Game continues
- ✅ Missing NPC data: Game loads level anyway
Summary
✅ Gameplay Testing
- Collision detection with enemies and barriers
- Character interactions and animations
- NPC dialogue and menu systems
✅ Integration Testing
- Level transitions with animations
- NPC AI responses via backend
- Multiple game systems working together
✅ API Error Handling
- try/catch blocks for all external calls
- Graceful fallbacks when services fail
- Game continues even with partial failures
- Console logging for debugging