Game Engine Code Snippets by Topic
1. Transition Screens
Victory Screen Implementation
The victory screen system handles game completion with proper state management and visual feedback.
// Enhanced method to handle victory
handleVictory() {
console.log('handleVictory called with hitCount:', this.fireballHitCount);
// Prevent multiple victory screens
if (this.victoryTriggered) {
console.log('Victory already triggered, ignoring');
return;
}
this.victoryTriggered = true;
// Remove any existing victory screen
const existingVictory = document.getElementById('victory-screen');
if (existingVictory) {
existingVictory.remove();
}
this.showVictoryScreen();
setTimeout(() => {
location.reload();
}, 3000);
}
// Enhanced method to display victory screen
showVictoryScreen() {
console.log('Showing victory screen');
const victoryDiv = document.createElement('div');
victoryDiv.id = 'victory-screen';
victoryDiv.style.cssText = `
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
background-color: rgba(0, 50, 0, 0.95) !important;
display: flex !important;
flex-direction: column !important;
justify-content: center !important;
align-items: center !important;
z-index: 99999 !important;
color: #00FF00 !important;
font-size: 48px !important;
font-family: Arial, sans-serif !important;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8) !important;
pointer-events: auto !important;
`;
victoryDiv.innerHTML = `
<div>🎉 VICTORY! 🎉</div>
<div style="font-size: 32px; margin-top: 20px;">You defeated the Ghast!</div>
<div style="font-size: 24px; margin-top: 10px;">Fireballs Hit Back: ${this.fireballHitCount}/2</div>
<div style="font-size: 18px; margin-top: 20px;">Restarting in 3 seconds...</div>
`;
// Ensure it's added to the body and visible
document.body.appendChild(victoryDiv);
// Force visibility
setTimeout(() => {
victoryDiv.style.display = 'flex';
}, 10);
console.log('Victory screen added to DOM');
}
Game Over Screen
Simple game over implementation with automatic restart functionality.
handleGameOver: function() {
this.showGameOverScreen();
setTimeout(() => {
location.reload();
}, 3000);
},
showGameOverScreen: function() {
const gameOverDiv = document.createElement('div');
gameOverDiv.id = 'game-over-screen';
gameOverDiv.style.cssText = `
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0.8); display: flex; flex-direction: column;
justify-content: center; align-items: center; z-index: 10000;
color: #FF0000; font-size: 48px; font-family: Arial, sans-serif;
`;
gameOverDiv.innerHTML = `
<div>GAME OVER</div>
<div style="font-size: 24px; margin-top: 20px;">Restarting in 3 seconds...</div>
`;
document.body.appendChild(gameOverDiv);
}
2. Enemy System
Ghast Enemy Configuration
Complete enemy configuration with health, animations, and behavior patterns.
const sprite_data_ghast = {
id: 'Ghast',
down: { row: 0, start: 0, columns: 4 },
greeting: "ROOOOOAAAAAR! *shoots fireballs*",
src: sprite_src_ghast,
SCALE_FACTOR: GHAST_SCALE_FACTOR,
ANIMATION_RATE: 100,
pixels: { width: 256, height: 256 },
INIT_POSITION: { x: width - 300, y: 100 },
orientation: { rows: 2, columns: 4 },
idle: { row: 0, start: 0, columns: 4 },
shooting: { row: 1, start: 0, columns: 4 },
hitbox: { widthPercentage: 0.8, heightPercentage: 0.8 },
health: 150,
fireballCooldown: 0,
fireballRate: 120,
isEnemy: true,
gameEnv: gameEnv,
lastFireballTime: 0,
reaction: function () {
this.health -= 30;
console.log('Ghast health:', this.health);
if (this.health <= 0) {
console.log('Ghast destroyed!');
if (this.parent && this.gameEnv && this.gameEnv.gameObjects) {
const index = this.gameEnv.gameObjects.indexOf(this.parent);
if (index > -1) {
this.gameEnv.gameObjects.splice(index, 1);
}
}
// Trigger victory when ghast is destroyed
if (gameLevel) {
console.log('Calling handleVictory from ghast destruction');
gameLevel.handleVictory();
}
}
}
};
Enemy Behavior Update System
AI behavior system with distance-based attack patterns and cooldown management.
npcInstance.updateGhastBehavior = function() {
if (this.spriteData.fireballCooldown > 0) {
this.spriteData.fireballCooldown--;
}
const players = this.gameEnv.gameObjects.filter(obj =>
obj.constructor.name === 'Player' && obj.spriteData.id === 'Steve'
);
if (players.length === 0) return;
const player = players[0];
if (!player.position || !this.position) return;
const dx = player.position.x - this.position.x;
const dy = player.position.y - this.position.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (this.spriteData.fireballCooldown <= 0 && distance < 600) {
this.shootFireball(player);
this.spriteData.fireballCooldown = this.spriteData.fireballRate;
this.direction = 'shooting';
} else {
this.direction = 'idle';
}
};
3. Blocks and Environmental Hazards
Lava Block Hazard
Environmental hazard implementation with damage and visual effects.
const sprite_data_lava = {
id: 'Lava-Pool',
src: sprite_src_lava,
SCALE_FACTOR: 8,
ANIMATION_RATE: 75,
pixels: { width: 128, height: 64 },
INIT_POSITION: { x: width / 2, y: height - 100 },
orientation: { rows: 1, columns: 8 },
down: { row: 0, start: 0, columns: 8 },
hitbox: { widthPercentage: 0.9, heightPercentage: 0.5 },
damage: 15,
reaction: function () {
// Damage reaction could be implemented here
}
};
4. Canvas and Game Object Management APIs
Canvas Management API
Dynamic canvas creation and management for rendering game elements.
// Canvas creation and management
this.canvas = document.createElement('canvas');
this.canvas.width = gameEnv.innerWidth;
this.canvas.height = gameEnv.innerHeight;
this.canvas.style.position = 'absolute';
this.canvas.style.top = '0';
this.canvas.style.left = '0';
this.canvas.style.pointerEvents = 'none';
this.canvas.style.zIndex = '10';
this.canvas.id = `fireball-canvas-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
this.ctx = this.canvas.getContext('2d');
// Add canvas to game container
if (gameEnv.gameContainer) {
gameEnv.gameContainer.appendChild(this.canvas);
} else {
document.getElementById('gameContainer')?.appendChild(this.canvas);
}
Game Object Management API
Comprehensive cleanup system for managing game objects and preventing memory leaks.
clearGameObjects(gameEnv) {
if (gameEnv && gameEnv.gameObjects) {
const objectsToRemove = [...gameEnv.gameObjects];
objectsToRemove.forEach(obj => {
try {
if (obj && typeof obj.destroy === 'function') {
obj.destroy();
}
if (obj && obj.element && obj.element.parentNode) {
if (obj.element.tagName !== 'CANVAS') {
obj.element.parentNode.removeChild(obj.element);
}
}
if (obj.intervalId) {
clearInterval(obj.intervalId);
}
if (obj.timeoutId) {
clearTimeout(obj.timeoutId);
}
} catch (error) {
console.warn('Error cleaning up object:', error);
}
});
gameEnv.gameObjects.length = 0;
}
}
5. Animation Systems
Enemy Animation State System
Multi-state animation system for enemy behaviors.
const sprite_data_ghast = {
// Animation configurations
orientation: { rows: 2, columns: 4 },
idle: { row: 0, start: 0, columns: 4 },
shooting: { row: 1, start: 0, columns: 4 },
ANIMATION_RATE: 100,
// Animation state management in behavior update
updateGhastBehavior: function() {
// ... distance and cooldown logic ...
if (this.spriteData.fireballCooldown <= 0 && distance < 600) {
this.shootFireball(player);
this.spriteData.fireballCooldown = this.spriteData.fireballRate;
this.direction = 'shooting'; // Switch to shooting animation
} else {
this.direction = 'idle'; // Switch to idle animation
}
}
};
Player Animation States
8-directional player animation system with rotation support.
const sprite_data_steve = {
orientation: {rows: 8, columns: 4 },
down: {row: 1, start: 0, columns: 4 },
downRight: {row: 7, start: 0, columns: 4, rotate: Math.PI/8 },
downLeft: {row: 5, start: 0, columns: 4, rotate: -Math.PI/8 },
left: {row: 5, start: 0, columns: 4 },
right: {row: 7, start: 0, columns: 4 },
up: {row: 3, start: 0, columns: 4 },
upLeft: {row: 5, start: 0, columns: 4, rotate: Math.PI/8 },
upRight: {row: 7, start: 0, columns: 4, rotate: -Math.PI/8 },
ANIMATION_RATE: 25,
};
6. Dialogue and Interaction Systems
NPC Dialogue Configuration
Interactive dialogue system with portal and item interactions.
const sprite_data_portal = {
id: 'Nether-Portal',
greeting: "Return to the Desert?",
dialogues: [
"The portal shimmers with otherworldly energy.",
"You can return to the Desert through this portal.",
"The familiar world awaits beyond this threshold."
],
interact: function () {
const confirmReturn = confirm("Return to the Desert? (This will end the Nether challenge)");
if (confirmReturn) {
if (gameEnv && gameEnv.gameControl) {
this.cleanupNetherLevel();
gameEnv.gameControl.goToLevel("Desert");
}
}
}
};
const sprite_data_potion = {
id: 'Health-Potion',
greeting: "Health Potion - restores 50 HP",
// Interaction through collision/pickup system
};
7. Combat and Interaction Systems
Player Attack System
Comprehensive attack system with fireball deflection mechanics.
const sprite_data_steve = {
canHitFireballs: true,
isAttacking: false,
attackCooldown: 0,
handleAttack: function() {
console.log('handleAttack called, cooldown:', this.attackCooldown);
if (this.attackCooldown <= 0) {
this.isAttacking = true;
this.attackCooldown = 20;
// Call checkFireballHit with proper context
this.checkFireballHit.call(this);
setTimeout(() => {
this.isAttacking = false;
}, 300);
}
},
checkFireballHit: function() {
console.log('checkFireballHit called');
if (!this.gameEnv || !this.gameEnv.gameObjects) {
console.log('No gameEnv or gameObjects');
return;
}
const playerPos = this.parent ? this.parent.position : null;
if (!playerPos) {
console.log('No player position');
return;
}
const fireballs = this.gameEnv.gameObjects.filter(obj =>
obj instanceof GhastFireball &&
obj.spriteData &&
obj.spriteData.canBeHitBack &&
obj.spriteData.damagePlayer === true
);
console.log('Found fireballs:', fireballs.length);
for (let fireball of fireballs) {
if (!fireball.position) continue;
const dx = fireball.position.x - playerPos.x;
const dy = fireball.position.y - playerPos.y;
const distance = Math.sqrt(dx * dx + dy * dy);
console.log('Fireball distance:', distance);
if (distance < 80) {
console.log('Fireball hit! Distance:', distance);
const ghasts = this.gameEnv.gameObjects.filter(obj =>
obj.spriteData && obj.spriteData.id === 'Ghast'
);
if (ghasts.length > 0) {
fireball.reverseDirection(ghasts[0]);
// Increment hit count and check for win condition
if (this.gameLevel) {
this.gameLevel.fireballHitCount++;
console.log('Hit count increased to:', this.gameLevel.fireballHitCount);
if (this.gameLevel.fireballHitCount >= 2) {
console.log('Victory condition met!');
this.gameLevel.handleVictory();
}
}
}
break;
}
}
}
};
Damage System
Health management and game over mechanics for both players and enemies.
// Player damage reaction
reaction: function () {
if (this.health > 0) {
this.health -= 20;
if (this.health <= 0) {
this.handleGameOver();
}
}
},
// Enemy damage and destruction
reaction: function () {
this.health -= 30;
console.log('Ghast health:', this.health);
if (this.health <= 0) {
console.log('Ghast destroyed!');
if (this.parent && this.gameEnv && this.gameEnv.gameObjects) {
const index = this.gameEnv.gameObjects.indexOf(this.parent);
if (index > -1) {
this.gameEnv.gameObjects.splice(index, 1);
}
}
// Trigger victory when ghast is destroyed
if (gameLevel) {
gameLevel.handleVictory();
}
}
}
8. Projectile Systems
Fireball Projectile Class
Complete projectile implementation with homing behavior and collision detection.
class GhastFireball {
constructor(x, y, target, gameEnv, speed = 3, turnRate = 0.06) {
this.gameEnv = gameEnv;
this.target = target;
this.speed = speed;
this.turnRate = turnRate;
this.radius = 15;
this.baseRadius = 15;
this.color = "#FF4500"; // Orange-red fireball color
this.active = true;
this.exploding = false;
this.impactFrames = 0;
this.maxImpactFrames = 45;
this.position = { x: x, y: y };
// Add sprite data for compatibility with game engine
this.spriteData = {
id: 'Ghast-Fireball',
canBeHitBack: true,
damagePlayer: true,
damageGhast: false,
hitBackSpeed: 6
};
// Calculate initial velocity toward target
const dx = target.position.x - x;
const dy = target.position.y - y;
const angle = Math.atan2(dy, dx);
this.velocity = {
x: Math.cos(angle) * speed,
y: Math.sin(angle) * speed
};
}
}
Homing Projectile Behavior
Advanced AI targeting system with gradual turning and collision detection.
update() {
// ... validation code ...
// Calculate distance to target
const dx = this.target.position.x - this.position.x;
const dy = this.target.position.y - this.position.y;
const distance = Math.sqrt(dx * dx + dy * dy);
// Check for collision with target (player)
const collisionDistance = this.radius + (this.target.size?.width || 30) / 2;
if (distance < collisionDistance) {
console.log('💥 Direct hit on player!');
this.explode();
this.damagePlayer();
return;
}
// Homing behavior - adjust velocity toward target
if (this.spriteData.damagePlayer) {
const targetAngle = Math.atan2(dy, dx);
const currentAngle = Math.atan2(this.velocity.y, this.velocity.x);
// Calculate angle difference and normalize
let angleDiff = targetAngle - currentAngle;
while (angleDiff > Math.PI) angleDiff -= 2 * Math.PI;
while (angleDiff < -Math.PI) angleDiff += 2 * Math.PI;
// Apply gradual turning
const newAngle = currentAngle + this.turnRate * angleDiff;
this.velocity.x = Math.cos(newAngle) * this.speed;
this.velocity.y = Math.sin(newAngle) * this.speed;
}
// Update position
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
}
Projectile Reversal Mechanic
Fireball deflection system that changes target and visual properties.
// Method to reverse fireball direction (for hitting back)
reverseDirection(newTarget) {
if (!newTarget || !newTarget.position) return;
this.target = newTarget;
// Calculate new direction
const dx = newTarget.position.x - this.position.x;
const dy = newTarget.position.y - this.position.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
const newSpeed = this.spriteData.hitBackSpeed || 6;
this.velocity.x = (dx / distance) * newSpeed;
this.velocity.y = (dy / distance) * newSpeed;
this.speed = newSpeed;
// Change damage properties
this.spriteData.damagePlayer = false;
this.spriteData.damageGhast = true;
// Visual feedback - change color slightly
this.color = "#4169E1"; // Royal blue when hit back
console.log("🔄 Fireball reversed direction!");
}
}
9. Visual Effects and Particle Systems
Particle System for Fireballs
Trail and particle effects for enhanced visual feedback.
// Fireball trail effect
this.trail = [];
this.maxTrailLength = 8;
// Particle effects
this.particles = [];
this.maxParticles = 6;
updateTrail() {
// Add current position to trail
this.trail.unshift({
x: this.position.x,
y: this.position.y,
alpha: 1.0
});
// Remove old trail points
if (this.trail.length > this.maxTrailLength) {
this.trail.pop();
}
// Fade trail points
this.trail.forEach((point, index) => {
point.alpha = 1.0 - (index / this.maxTrailLength);
});
}
updateParticles() {
// Add new particles
if (this.particles.length < this.maxParticles) {
this.particles.push({
x: this.position.x + (Math.random() - 0.5) * 10,
y: this.position.y + (Math.random() - 0.5) * 10,
vx: (Math.random() - 0.5) * 2,
vy: (Math.random() - 0.5) * 2,
life: 1.0,
decay: 0.05 + Math.random() * 0.05
});
}
// Update existing particles
this.particles = this.particles.filter(particle => {
particle.x += particle.vx;
particle.y += particle.vy;
particle.life -= particle.decay;
return particle.life > 0;
});
}
Visual Effects Rendering
Advanced rendering with gradients, pulsing effects, and layered visuals.
drawFireball(ctx) {
// Pulsing effect while moving
const time = Date.now();
const pulse = Math.sin(time / 80) * 3;
const drawRadius = this.baseRadius + pulse;
// Outer glow
const gradient = ctx.createRadialGradient(
this.position.x, this.position.y, 0,
this.position.x, this.position.y, drawRadius + 10
);
gradient.addColorStop(0, 'rgba(255, 255, 100, 0.8)');
gradient.addColorStop(0.4, 'rgba(255, 69, 0, 0.6)');
gradient.addColorStop(1, 'rgba(255, 0, 0, 0.1)');
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, drawRadius + 10, 0, Math.PI * 2);
ctx.fillStyle = gradient;
ctx.fill();
// Main fireball body
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, drawRadius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
// Inner core
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, drawRadius * 0.6, 0, Math.PI * 2);
ctx.fillStyle = '#FFFF00'; // Bright yellow core
ctx.fill();
// Hot white center
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, drawRadius * 0.3, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.fill();
}
Explosion Effects
Multi-layered explosion animation with particle effects and fade-out.
drawExplosion(ctx) {
const progress = this.impactFrames / this.maxImpactFrames;
const alpha = 1 - progress;
const explosionRadius = this.radius + this.impactFrames * 2;
// Draw explosion particles first
this.drawParticles(ctx);
// Outer explosion ring
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, explosionRadius, 0, Math.PI * 2);
ctx.fillStyle = `rgba(255, 100, 0, ${alpha * 0.6})`;
ctx.fill();
// Middle ring
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, explosionRadius * 0.7, 0, Math.PI * 2);
ctx.fillStyle = `rgba(255, 150, 0, ${alpha * 0.8})`;
ctx.fill();
// Inner core
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, explosionRadius * 0.4, 0, Math.PI * 2);
ctx.fillStyle = `rgba(255, 255, 100, ${alpha})`;
ctx.fill();
// White hot center
if (this.impactFrames < 20) {
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, explosionRadius * 0.2, 0, Math.PI * 2);
ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`;
ctx.fill();
}
// Explosion outline
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, explosionRadius, 0, Math.PI * 2);
ctx.strokeStyle = `rgba(255, 255, 255, ${alpha * 0.8})`;
ctx.lineWidth = 3;
ctx.stroke();
}
Final Project Learning Connections
Each section of code demonstrates key computer science concepts required for the final project:
Software Engineering & Development Lifecycle Practices
- Planning & Documentation: Extensive code comments and structured organization throughout all sections
- Source Control: Modular code structure enabling easy forking, branching, and merging
- Testing & Verification: Console logging and debug statements in victory/game over screens for troubleshooting
- Code Reviews: Clear method separation and readable function names facilitate review processes
Data Types
- Numbers: Health values (150, 30, 20), coordinates (x, y), animation rates (100, 25), and mathematical calculations
- Strings: Entity IDs (‘Ghast’, ‘Steve’), CSS styling strings, and console messages
- Booleans: State flags (victoryTriggered, isAttacking, canBeHitBack, active)
- Arrays: Game object collections (gameObjects), trail points, and particle systems
- JSON Objects: Sprite data configurations, position objects, and game state management
Operators
- String Operations: Template literals for CSS styling and HTML content creation
- Mathematical Operations: Distance calculations (Math.sqrt, dxdx + dydy), trigonometry (Math.atan2, Math.sin), and coordinate transformations
- Boolean Expressions: Conditional checks (health <= 0, distance < 80, this.attackCooldown <= 0)
Control Structures
- Iterations: forEach loops for object cleanup, filter operations for game object selection, and particle system updates
- Conditions: Victory/defeat state management, collision detection, and animation state switching
- Nested Conditions: Complex game logic combining health checks, distance calculations, and cooldown management
Input/Output
- HTML5 Input: Key event handling for attack actions and movement
- DOM Manipulation: Dynamic creation of victory/game over screens, canvas management, and element styling
- Validation: Input validation for game state changes and collision detection
Classes & Object-Oriented Programming
- Class Definition: GhastFireball class with constructor and methods
- Method Creation: handleVictory(), checkFireballHit(), updateGhastBehavior() methods
- Object Instantiation: Creating sprite data objects, canvas elements, and game entities
- Method Calls: Calling reaction(), destroy(), and update() methods with proper parameters
- Return Values: Distance calculations, collision detection results, and state validations
Coding Practices
- Single Responsibility Principle (SRP): Each function handles one specific task (victory handling, collision detection, animation updates)
- Object Literals: Sprite data configurations using object literal syntax with properties and methods
- Object Instances: Creating specific instances of game entities with unique properties and behaviors
- Finite State Machines (FSMs): Animation state management (idle, shooting, exploding) and game state transitions
- Inheritance: Sprite data objects sharing common properties while maintaining unique characteristics