3D Maze Game Using HTML and JavaScript
Creating engaging browser-based games is a fantastic way to polish your programming skills. In this tutorial, we’ll walk through building a simple maze game with a 3D effect using HTML5 Canvas and JavaScript. The game involves guiding a player from the starting point to the goal, navigating through a randomly generated maze.
Features of the Maze Game
- 3D Visual Effect: Walls, the player, and the goal have subtle gradients for a 3D appearance.
- Random Maze Generation: Each play-through offers a unique challenge with a maze generated using recursive backtracking.
- Keyboard Navigation: Use arrow keys to navigate the player through the maze.
- Winning State: A congratulatory message appears when the player reaches the goal.
Game Setup
The game is built using HTML, CSS, and JavaScript. Here’s how it’s structured:
- HTML: Defines the canvas element and layout.
- CSS: Styles the game elements and adds 3D effects.
- JavaScript: Implements the game logic, including maze generation, rendering, and player movement.
Follow this video for complete guidance :
Full Source Code
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Find Your Way - 3D</title> <style> body { text-align: center; font-family: Arial, sans-serif; background: linear-gradient(to bottom, #e0e0e0, #b0b0b0); margin: 0; padding: 0; } canvas { border: 10px solid #222; border-radius: 10px; background: linear-gradient(to bottom, #f4f4f4, #d4d4d4); box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.5); margin: 20px auto; display: block; } #message { font-size: 2em; font-weight: bold; color: green; text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); display: none; } h1 { color: #333; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); } </style> </head> <body> <h1>Find Your Way</h1> <div id="message">You Win!</div> <canvas id="gameCanvas" width="400" height="400"></canvas> <script> const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const gridSize = 20; const rows = canvas.height / gridSize; const cols = canvas.width / gridSize; let player = { x: 0, y: 0 }; let goal = { x: cols - 1, y: rows - 1 }; let maze = []; // Maze Generator using Recursive Backtracking function generateMaze() { maze = Array.from({ length: rows }, () => Array(cols).fill(1)); // Fill maze with walls const directions = [ { dx: 0, dy: -1 }, // Up { dx: 0, dy: 1 }, // Down { dx: -1, dy: 0 }, // Left { dx: 1, dy: 0 } // Right ]; // Helper to shuffle directions for random exploration function shuffle(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; } // Recursive function to carve paths function carvePath(x, y) { maze[y][x] = 0; // Mark cell as path shuffle(directions).forEach(({ dx, dy }) => { const nx = x + dx * 2; const ny = y + dy * 2; if (nx >= 0 && ny >= 0 && nx < cols && ny < rows && maze[ny][nx] === 1) { maze[y + dy][x + dx] = 0; // Remove wall between cells carvePath(nx, ny); } }); } carvePath(0, 0); // Start carving from the top-left corner ensureGoalPath(); } // Ensure the bottom-right corner is reachable function ensureGoalPath() { maze[rows - 1][cols - 1] = 0; // Ensure goal position is a path if (maze[rows - 2][cols - 1] === 1 && maze[rows - 1][cols - 2] === 1) { maze[rows - 2][cols - 1] = 0; // Create path if isolated } } // Draw Maze, Player, and Goal function drawGame() { ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < rows; i++) { for (let j = 0; j < cols; j++) { if (maze[i][j] === 1) { // Draw walls with a 3D effect ctx.fillStyle = '#444'; ctx.fillRect(j * gridSize, i * gridSize, gridSize, gridSize); ctx.fillStyle = '#555'; ctx.fillRect(j * gridSize + 2, i * gridSize + 2, gridSize - 4, gridSize - 4); } } } // Draw goal with gradient for 3D effect const goalGradient = ctx.createLinearGradient( goal.x * gridSize, goal.y * gridSize, (goal.x + 1) * gridSize, (goal.y + 1) * gridSize ); goalGradient.addColorStop(0, '#3fa34d'); goalGradient.addColorStop(1, '#2d7a35'); ctx.fillStyle = goalGradient; ctx.fillRect(goal.x * gridSize, goal.y * gridSize, gridSize, gridSize); // Draw player with gradient for 3D effect const playerGradient = ctx.createLinearGradient( player.x * gridSize, player.y * gridSize, (player.x + 1) * gridSize, (player.y + 1) * gridSize ); playerGradient.addColorStop(0, '#4a90e2'); playerGradient.addColorStop(1, '#357abf'); ctx.fillStyle = playerGradient; ctx.fillRect(player.x * gridSize, player.y * gridSize, gridSize, gridSize); } // Movement Logic function movePlayer(dx, dy) { const newX = player.x + dx; const newY = player.y + dy; if ( newX >= 0 && newX < cols && newY >= 0 && newY < rows && maze[newY][newX] === 0 ) { player.x = newX; player.y = newY; if (player.x === goal.x && player.y === goal.y) { document.getElementById('message').style.display = 'block'; document.removeEventListener('keydown', handleKeyDown); } } drawGame(); } // Key Controls function handleKeyDown(e) { if (e.key === 'ArrowUp') movePlayer(0, -1); if (e.key === 'ArrowDown') movePlayer(0, 1); if (e.key === 'ArrowLeft') movePlayer(-1, 0); if (e.key === 'ArrowRight') movePlayer(1, 0); } // Game Initialization function initGame() { generateMaze(); drawGame(); document.getElementById('message').style.display = 'none'; player = { x: 0, y: 0 }; document.addEventListener('keydown', handleKeyDown); } initGame(); </script> </body> </html>
How to Run the Game
- Copy the code into an .html file.
- Open the file in your browser.
- Use the arrow keys to guide the player to the goal.
Enhancements
- Add Difficulty Levels: Increase maze size or player speed.
- Timer: Introduce a countdown for added challenge.
- Mobile Support: Implement touch controls for mobile devices.
This simple maze game is a fun and educational project to practice JavaScript and canvas drawing. Happy coding! 🎮