Before we start, here are some JavaScript Games you might like to create:
1. Snake Game using JavaScript
2. 2D Bouncing Ball Game using JavaScript
3. Rock Paper Scissor Game using JavaScript
4. Tic Tac Toe Game using JavaScript
5. Whack a Mole Game using JavaScript
I would recommend you don’t just copy and paste the code, just look at the code and type by understanding it.
HTML Code
Starter Template
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSS --> <link rel="stylesheet" href="style.css"> <title>Maze Game using JavaScript - @code.scientist x @codingtorque</title> </head> <body> <!-- Further code here --> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.touchswipe/1.6.18/jquery.touchSwipe.min.js"></script> <script src="script.js"></script> </body> </html>
Paste the below code in your <body>
tag.
<div id="gradient"></div> <div id="page"> <div id="Message-Container"> <div id="message"> <h1>Congratulations!</h1> <p>You are done.</p> <p id="moves"></p> <input id="okBtn" type="button" onclick="toggleVisablity('Message-Container')" value="Cool!" /> </div> </div> <div id="menu"> <div class="custom-select"> <select id="diffSelect"> <option value="10">Easy</option> <option value="15">Medium</option> <option value="25">Hard</option> <option value="38">Extreme</option> </select> </div> <input id="startMazeBtn" type="button" onclick="makeMaze()" value="Start" /> </div> <div id="view"> <div id="mazeContainer"> <canvas id="mazeCanvas" class="border" height="1100" width="1100"></canvas> </div> </div> </div>
CSS Code
Create a file style.css and paste the code below.
html, body { width: 100vw; height: 100vh; position: fixed; padding: 0; margin: 0; top: 0; bottom: 0; left: 0; right: 0; } #mazeContainer { transition-property: opacity; transition-duration: 1s; transition-timing-function: linear; top: 75px; opacity: 0; display: inline-block; background-color: rgba(0, 0, 0, 0.3); margin: auto; } #mazeContainer #mazeCanvas { margin: 0; display: block; border: solid 1px black; } input, select { transition-property: background-color opacity; transition-duration: 0.2s; transition-timing-function: ease-in-out; cursor: pointer; background-color: rgba(0, 0, 0, 0.3); height: 45px; width: 150px; padding: 10px; border: none; border-radius: 5px; color: white; display: inline-block; font-size: 15px; text-align: center; text-decoration: none; appearance: none; } input:hover, select:hover { background-color: rgba(0, 0, 0, 0.7); } input:active, select:active { background-color: black; } input:focus, select:focus { outline: none; } .custom-select { display: inline-block; } .custom-select select { -webkit-appearance: none; -moz-appearance: none; appearance: none; background-image: url("data:image/png; base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAh0lEQVQ4T93TMQrCUAzG8V9x8QziiYSuXdzFC7h4AcELOPQAdXYovZCHEATlgQV5GFTe1ozJlz/kS1IpjKqw3wQBVyy++JI0y1GTe7DCBbMAckeNIQKk/BanALBB+16LtnDELoMcsM/BESDlz2heDR3WePwKSLo5eoxz3z6NNcFD+vu3ij14Aqz/DxGbKB7CAAAAAElFTkSuQmCC"); background-repeat: no-repeat; background-position: 125px center; } #Message-Container { visibility: hidden; color: white; display: block; width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; bottom: 0; right: 0; background-color: rgba(0, 0, 0, 0.3); z-index: 1; } #Message-Container #message { width: 300px; height: 300px; position: fixed; top: 50%; left: 50%; margin-left: -150px; margin-top: -150px; } #page { font-family: "Segoe UI", Arial, sans-serif; text-align: center; height: auto; width: auto; margin: auto; } #page #menu { margin: auto; padding: 10px; height: 65px; box-sizing: border-box; } #page #menu h1 { margin: 0; margin-bottom: 10px; font-weight: 600; font-size: 3.2rem; } #page #view { position: absolute; top: 65px; bottom: 0; left: 0; right: 0; width: 100%; height: auto; } .border { border: 1px black solid; border-radius: 5px; } #gradient { z-index: -1; position: fixed; top: 0; bottom: 0; width: 100vw; height: 100vh; color: #fff; background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab); background-size: 400% 400%; animation: Gradient 15s ease infinite; } @keyframes Gradient { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } /* Extra small devices (phones, 600px and down) */ @media only screen and (max-width: 400px) { input, select { width: 120px; } }
JavaScript Code
Create a file script.js and paste the code below.
function rand(max) { return Math.floor(Math.random() * max); } function shuffle(a) { for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; } function changeBrightness(factor, sprite) { var virtCanvas = document.createElement("canvas"); virtCanvas.width = 500; virtCanvas.height = 500; var context = virtCanvas.getContext("2d"); context.drawImage(sprite, 0, 0, 500, 500); var imgData = context.getImageData(0, 0, 500, 500); for (let i = 0; i < imgData.data.length; i += 4) { imgData.data[i] = imgData.data[i] * factor; imgData.data[i + 1] = imgData.data[i + 1] * factor; imgData.data[i + 2] = imgData.data[i + 2] * factor; } context.putImageData(imgData, 0, 0); var spriteOutput = new Image(); spriteOutput.src = virtCanvas.toDataURL(); virtCanvas.remove(); return spriteOutput; } function displayVictoryMess(moves) { document.getElementById("moves").innerHTML = "You Moved " + moves + " Steps."; toggleVisablity("Message-Container"); } function toggleVisablity(id) { if (document.getElementById(id).style.visibility == "visible") { document.getElementById(id).style.visibility = "hidden"; } else { document.getElementById(id).style.visibility = "visible"; } } function Maze(Width, Height) { var mazeMap; var width = Width; var height = Height; var startCoord, endCoord; var dirs = ["n", "s", "e", "w"]; var modDir = { n: { y: -1, x: 0, o: "s" }, s: { y: 1, x: 0, o: "n" }, e: { y: 0, x: 1, o: "w" }, w: { y: 0, x: -1, o: "e" } }; this.map = function () { return mazeMap; }; this.startCoord = function () { return startCoord; }; this.endCoord = function () { return endCoord; }; function genMap() { mazeMap = new Array(height); for (y = 0; y < height; y++) { mazeMap[y] = new Array(width); for (x = 0; x < width; ++x) { mazeMap[y][x] = { n: false, s: false, e: false, w: false, visited: false, priorPos: null }; } } } function defineMaze() { var isComp = false; var move = false; var cellsVisited = 1; var numLoops = 0; var maxLoops = 0; var pos = { x: 0, y: 0 }; var numCells = width * height; while (!isComp) { move = false; mazeMap[pos.x][pos.y].visited = true; if (numLoops >= maxLoops) { shuffle(dirs); maxLoops = Math.round(rand(height / 8)); numLoops = 0; } numLoops++; for (index = 0; index < dirs.length; index++) { var direction = dirs[index]; var nx = pos.x + modDir[direction].x; var ny = pos.y + modDir[direction].y; if (nx >= 0 && nx < width && ny >= 0 && ny < height) { //Check if the tile is already visited if (!mazeMap[nx][ny].visited) { //Carve through walls from this tile to next mazeMap[pos.x][pos.y][direction] = true; mazeMap[nx][ny][modDir[direction].o] = true; //Set Currentcell as next cells Prior visited mazeMap[nx][ny].priorPos = pos; //Update Cell position to newly visited location pos = { x: nx, y: ny }; cellsVisited++; //Recursively call this method on the next tile move = true; break; } } } if (!move) { // If it failed to find a direction, // move the current position back to the prior cell and Recall the method. pos = mazeMap[pos.x][pos.y].priorPos; } if (numCells == cellsVisited) { isComp = true; } } } function defineStartEnd() { switch (rand(4)) { case 0: startCoord = { x: 0, y: 0 }; endCoord = { x: height - 1, y: width - 1 }; break; case 1: startCoord = { x: 0, y: width - 1 }; endCoord = { x: height - 1, y: 0 }; break; case 2: startCoord = { x: height - 1, y: 0 }; endCoord = { x: 0, y: width - 1 }; break; case 3: startCoord = { x: height - 1, y: width - 1 }; endCoord = { x: 0, y: 0 }; break; } } genMap(); defineStartEnd(); defineMaze(); } function DrawMaze(Maze, ctx, cellsize, endSprite = null) { var map = Maze.map(); var cellSize = cellsize; var drawEndMethod; ctx.lineWidth = cellSize / 40; this.redrawMaze = function (size) { cellSize = size; ctx.lineWidth = cellSize / 50; drawMap(); drawEndMethod(); }; function drawCell(xCord, yCord, cell) { var x = xCord * cellSize; var y = yCord * cellSize; if (cell.n == false) { ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x + cellSize, y); ctx.stroke(); } if (cell.s === false) { ctx.beginPath(); ctx.moveTo(x, y + cellSize); ctx.lineTo(x + cellSize, y + cellSize); ctx.stroke(); } if (cell.e === false) { ctx.beginPath(); ctx.moveTo(x + cellSize, y); ctx.lineTo(x + cellSize, y + cellSize); ctx.stroke(); } if (cell.w === false) { ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x, y + cellSize); ctx.stroke(); } } function drawMap() { for (x = 0; x < map.length; x++) { for (y = 0; y < map[x].length; y++) { drawCell(x, y, map[x][y]); } } } function drawEndFlag() { var coord = Maze.endCoord(); var gridSize = 4; var fraction = cellSize / gridSize - 2; var colorSwap = true; for (let y = 0; y < gridSize; y++) { if (gridSize % 2 == 0) { colorSwap = !colorSwap; } for (let x = 0; x < gridSize; x++) { ctx.beginPath(); ctx.rect( coord.x * cellSize + x * fraction + 4.5, coord.y * cellSize + y * fraction + 4.5, fraction, fraction ); if (colorSwap) { ctx.fillStyle = "rgba(0, 0, 0, 0.8)"; } else { ctx.fillStyle = "rgba(255, 255, 255, 0.8)"; } ctx.fill(); colorSwap = !colorSwap; } } } function drawEndSprite() { var offsetLeft = cellSize / 50; var offsetRight = cellSize / 25; var coord = Maze.endCoord(); ctx.drawImage( endSprite, 2, 2, endSprite.width, endSprite.height, coord.x * cellSize + offsetLeft, coord.y * cellSize + offsetLeft, cellSize - offsetRight, cellSize - offsetRight ); } function clear() { var canvasSize = cellSize * map.length; ctx.clearRect(0, 0, canvasSize, canvasSize); } if (endSprite != null) { drawEndMethod = drawEndSprite; } else { drawEndMethod = drawEndFlag; } clear(); drawMap(); drawEndMethod(); } function Player(maze, c, _cellsize, onComplete, sprite = null) { var ctx = c.getContext("2d"); var drawSprite; var moves = 0; drawSprite = drawSpriteCircle; if (sprite != null) { drawSprite = drawSpriteImg; } var player = this; var map = maze.map(); var cellCoords = { x: maze.startCoord().x, y: maze.startCoord().y }; var cellSize = _cellsize; var halfCellSize = cellSize / 2; this.redrawPlayer = function (_cellsize) { cellSize = _cellsize; drawSpriteImg(cellCoords); }; function drawSpriteCircle(coord) { ctx.beginPath(); ctx.fillStyle = "yellow"; ctx.arc( (coord.x + 1) * cellSize - halfCellSize, (coord.y + 1) * cellSize - halfCellSize, halfCellSize - 2, 0, 2 * Math.PI ); ctx.fill(); if (coord.x === maze.endCoord().x && coord.y === maze.endCoord().y) { onComplete(moves); player.unbindKeyDown(); } } function drawSpriteImg(coord) { var offsetLeft = cellSize / 50; var offsetRight = cellSize / 25; ctx.drawImage( sprite, 0, 0, sprite.width, sprite.height, coord.x * cellSize + offsetLeft, coord.y * cellSize + offsetLeft, cellSize - offsetRight, cellSize - offsetRight ); if (coord.x === maze.endCoord().x && coord.y === maze.endCoord().y) { onComplete(moves); player.unbindKeyDown(); } } function removeSprite(coord) { var offsetLeft = cellSize / 50; var offsetRight = cellSize / 25; ctx.clearRect( coord.x * cellSize + offsetLeft, coord.y * cellSize + offsetLeft, cellSize - offsetRight, cellSize - offsetRight ); } function check(e) { var cell = map[cellCoords.x][cellCoords.y]; moves++; switch (e.keyCode) { case 65: case 37: // west if (cell.w == true) { removeSprite(cellCoords); cellCoords = { x: cellCoords.x - 1, y: cellCoords.y }; drawSprite(cellCoords); } break; case 87: case 38: // north if (cell.n == true) { removeSprite(cellCoords); cellCoords = { x: cellCoords.x, y: cellCoords.y - 1 }; drawSprite(cellCoords); } break; case 68: case 39: // east if (cell.e == true) { removeSprite(cellCoords); cellCoords = { x: cellCoords.x + 1, y: cellCoords.y }; drawSprite(cellCoords); } break; case 83: case 40: // south if (cell.s == true) { removeSprite(cellCoords); cellCoords = { x: cellCoords.x, y: cellCoords.y + 1 }; drawSprite(cellCoords); } break; } } this.bindKeyDown = function () { window.addEventListener("keydown", check, false); $("#view").swipe({ swipe: function ( event, direction, distance, duration, fingerCount, fingerData ) { console.log(direction); switch (direction) { case "up": check({ keyCode: 38 }); break; case "down": check({ keyCode: 40 }); break; case "left": check({ keyCode: 37 }); break; case "right": check({ keyCode: 39 }); break; } }, threshold: 0 }); }; this.unbindKeyDown = function () { window.removeEventListener("keydown", check, false); $("#view").swipe("destroy"); }; drawSprite(maze.startCoord()); this.bindKeyDown(); } var mazeCanvas = document.getElementById("mazeCanvas"); var ctx = mazeCanvas.getContext("2d"); var sprite; var finishSprite; var maze, draw, player; var cellSize; var difficulty; // sprite.src = 'media/sprite.png'; window.onload = function () { let viewWidth = $("#view").width(); let viewHeight = $("#view").height(); if (viewHeight < viewWidth) { ctx.canvas.width = viewHeight - viewHeight / 100; ctx.canvas.height = viewHeight - viewHeight / 100; } else { ctx.canvas.width = viewWidth - viewWidth / 100; ctx.canvas.height = viewWidth - viewWidth / 100; } //Load and edit sprites var completeOne = false; var completeTwo = false; var isComplete = () => { if (completeOne === true && completeTwo === true) { console.log("Runs"); setTimeout(function () { makeMaze(); }, 500); } }; sprite = new Image(); sprite.src = "https://image.ibb.co/dr1HZy/Pf_RWr3_X_Imgur.png" + "?" + new Date().getTime(); sprite.setAttribute("crossOrigin", " "); sprite.onload = function () { sprite = changeBrightness(1.2, sprite); completeOne = true; console.log(completeOne); isComplete(); }; finishSprite = new Image(); finishSprite.src = "https://image.ibb.co/b9wqnJ/i_Q7m_U25_Imgur.png" + "?" + new Date().getTime(); finishSprite.setAttribute("crossOrigin", " "); finishSprite.onload = function () { finishSprite = changeBrightness(1.1, finishSprite); completeTwo = true; console.log(completeTwo); isComplete(); }; }; window.onresize = function () { let viewWidth = $("#view").width(); let viewHeight = $("#view").height(); if (viewHeight < viewWidth) { ctx.canvas.width = viewHeight - viewHeight / 100; ctx.canvas.height = viewHeight - viewHeight / 100; } else { ctx.canvas.width = viewWidth - viewWidth / 100; ctx.canvas.height = viewWidth - viewWidth / 100; } cellSize = mazeCanvas.width / difficulty; if (player != null) { draw.redrawMaze(cellSize); player.redrawPlayer(cellSize); } }; function makeMaze() { //document.getElementById("mazeCanvas").classList.add("border"); if (player != undefined) { player.unbindKeyDown(); player = null; } var e = document.getElementById("diffSelect"); difficulty = e.options[e.selectedIndex].value; cellSize = mazeCanvas.width / difficulty; maze = new Maze(difficulty, difficulty); draw = new DrawMaze(maze, ctx, cellSize, finishSprite); player = new Player(maze, mazeCanvas, cellSize, displayVictoryMess, sprite); if (document.getElementById("mazeContainer").style.opacity < "100") { document.getElementById("mazeContainer").style.opacity = "100"; } }
Final Output
Written by: Piyush Patil
Code Credits: @TheCodeDepository
If you have any doubts or any project ideas feel free to Contact Us
Hope you find this post helpful💖