cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              
<header>
		<h1>Snake Game</h1>
</header>
<div class="leftColumn">
		<div id="container">
				<canvas id="canvas" width="840" height="600"></canvas>
				<div id="overlay" width="840" height="600">
						<p id="statusMessage">Placeholder Text</p>
				</div>
		</div>

</div>
<div class="rightColumn">
		<div class="controls">
				<button id="startButton" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/313305/play.png')" alt="Start"></button>
				<button id="pauseButton" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/313305/pause.png')" alt="Pause"></button>
				<button id="resumeButton" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/313305/play.png')" alt="Resume"></button>
				<button id="stopButton" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/313305/stop.png')" alt="Stop"></button>
				<br>
				<br /> Speed:
				<input type="range" id="speedRange" min="0" max="120" step="1" value="60" />
				<br />
		</div>
		<div class="status">
				<p>Points:</p>
				<p id="points">0</p>
				<br />
				<p>Score:</p>
				<p id="score">0</p>
				<br />
				<p>Level:</p>
				<p id="level">1</p>
		</div>
		<div class="instructions">
				<p>Use the arrow keys to control the snake to eat the food.</p>
				<p>Press the enter key to Start/Stop the game.</p>
				<p>Press the spacebar to Pause/Resume the game.</p>
				<p>The score is calculated based on how much food the snake has eaten, and the speed of the snake. The faster the speed, the faster your score increases!</p>
				<p>This is game is being used for educational purposes and is not to be sold.</p>
		</div>
</div>
<div class="scores">
		<h2 id="highScore">High Score: 0</h2>
		<p>Your previous scores: </p>
		<p id="firstScore">&nbsp;</p>
		<p id="secondScore">&nbsp;</p>
		<p id="thirdScore">&nbsp;</p>
		<p id="fourthScore">&nbsp;</p>
		<p id="fifthScore">&nbsp;</p>
</div>
            
          
!
            
              header {
		height: 30px;
		background-color: #A1D490;
}

h1 {
		font-size: 1.5em;
		text-align: center;
		margin: 0;
		color: #00698C;
}

body {
		font-family: sans-serif;
		margin: 0;
		padding: 0;
}

.leftColumn,
.rightColumn {
		float: left;
		width: 20%;
		text-align: center;
}

.leftColumn {
		width: 885px;
		margin: 10px 10px 10px 40px;
}

.scores {
		float: left;
		width: 100%;
		background-color: #E0FFD6;
}

.scores h2,
.scores p:first-of-type {
		margin-left: 40px;
}

.scores p {
		display: inline-block;
		margin: 0 10px 20px 10px;
}

#container {
		position: relative;
		width: 840px;
		height: 600px;
}

.instructions {
		margin: 20px 5%;
		text-align: left;
}

#canvas,
#overlay {
		width: 100%;
		height: 100%;
}

#overlay {
		background-color: black;
		background-color: rgba(0, 0, 0, 0.5);
		position: absolute;
		top: 0;
		left: 0;
}

#statusMessage {
		color: white;
		text-align: center;
		font-size: 42px;
		display: inline-block;
		width: 100%;
		margin-top: 30%;
}

.controls {
		margin: 20px 0;
		width: 95%;
}

#speedRange {
		width: 300px;
		cursor: pointer;
}

#startButton,
#stopButton,
#pauseButton,
#resumeButton {
		width: 60px;
		height: 60px;
		background-size: 100% 100%;
		background-color: transparent;
		border: none;
		cursor: pointer;
}

.status p {
		display: inline-block;
		font-size: 2em;
		text-align: right;
		margin: 10px 0;
}

#points,
#score,
#level {
		font-weight: bold;
		text-align: left;
		color: #BD005E;
}

@media screen and (max-width: 1200px) {
		.leftColumn, .rightColumn {
				clear: both;
				width: 100%;
		}
		.controls,
		.status,
		.instructions {
				width: 100%;
		}
}

.clearfix:after {
		content: "";
		display: table;
		clear: both;
}
            
          
!
            
              $(document).ready(function() {
		//canvas build
		var pointsStatus = $("#points");
		var scoreStatus = $("#score");
		var levelStatus = $("#level");

		var speedRange = $("#speedRange");
		var startButton = $("#startButton");
		var stopButton = $("#stopButton");
		var pauseButton = $("#pauseButton");
		var resumeButton = $("#resumeButton");

		var overlay = $("#overlay");
		var statusMessage = $("#statusMessage");
		var canvas = $("#canvas")[0];
		var ctx = canvas.getContext("2d");
		var w = Math.round($("#canvas").width());
		var h = Math.round($("#canvas").height());

		//Let's save the cell width in a variable for easy control
		var cw = 15;
		var d = null; //direction
		var currentDirection = null;
		var food;
		var points;
		var score;
		var level;
		var levelChange;
		var levelFrequency = 10;
		var speed = 60;
		var gameStarted = false;
		var gamePaused = false;
		var snakeLength = 5; //length of the snake

		//Colours
		var snakeHeadColor = "#103D09";
		var snakeHeadOutline = "#1B660E";
		var snakeBodyColor = "#1B660E";
		var snakeBodyOutline = "white";
		var foodColor = "black";
		var foodOutline = "black";
		var canvasLevelColors = ["#EBFAE8", "#93DFB8", "#FFC8BA", "#CFF09E", "#E3AAD6", "#A8DBA8", "#B5D8EB", "#79BD9A", "#FFBDD8", "#469999", "#1C78AD"];
		var canvasColor = canvasLevelColors[0];

		//Storing Scores
		var highScoreText = $("#highScore");
		var firstScoreText = $("#firstScore");
		var secondScoreText = $("#secondScore");
		var thirdScoreText = $("#thirdScore");
		var fourthScoreText = $("#fourthScore");
		var fifthScoreText = $("#fifthScore");
		var highScore;
		var firstScore;
		var secondScore;
		var thirdScore;
		var fourthScore;
		var fifthScore;

		//Load Audio
		var gameOver = new Audio("https://s3-us-west-2.amazonaws.com/s.cdpn.io/313305/gameOver.wav");
		gameOver.loop = false;
		gameOver.volume = 1;
		gameOver.load();
		var chomp = new Audio("https://s3-us-west-2.amazonaws.com/s.cdpn.io/313305/chomp.wav");
		chomp.loop = false;
		chomp.volume = 1;
		chomp.load();
		var levelUp = new Audio("https://s3-us-west-2.amazonaws.com/s.cdpn.io/313305/level.wav");
		levelUp.loop = false;
		levelUp.volume = 1;
		levelUp.load();

		//Listen for Buttons
		startButton.click(function() {
				startGame();
		});
		stopButton.click(function() {
				endGame();
		});
		pauseButton.click(function() {
				pauseGame();
		});
		resumeButton.click(function() {
				resumeGame();
		});

		//Listen for speed control changes
		speedRange.change(function(event) {
				pauseGame();
				console.log("change speed");
				//Determine speed
				var target = event.target;
				speed = 120 - target.value;
		});

		//Let's build the snake
		var snake_array; //an array of cells to make up the snake

		function init() {
				d = "right"; //default direction
				create_snake();
				create_food(); //now we can see the food particle
				//let's display the score
				points = 0;
				score = 0;
				level = 1;
				levelChange = levelFrequency;
				canvasColor = canvasLevelColors[0];

				//Let's move the snake now using a timer which will trigger the paint function every #ms
				if (typeof game_loop != "undefined") clearInterval(game_loop);
				game_loop = setInterval(paint, speed);
		}
		startButton.show();
		stopButton.hide();
		pauseButton.hide();
		resumeButton.hide();
		overlay.show();
		statusMessage.text("Start Game");

		//Retrieving the scores
		function getScores() {
				highScore = localStorage.getItem("highScore");
				firstScore = localStorage.getItem("firstScore");
				secondScore = localStorage.getItem("secondScore");
				thirdScore = localStorage.getItem("thirdScore");
				fourthScore = localStorage.getItem("fourthScore");
				fifthScore = localStorage.getItem("fifthScore");
		}

		//Updating the scores text
		function updateScores() {
				highScoreText.text("High Score: " + highScore);
				firstScoreText.text(firstScore);
				secondScoreText.text(secondScore);
				thirdScoreText.text(thirdScore);
				fourthScoreText.text(fourthScore);
				fifthScoreText.text(fifthScore);
		}

		//Storing the scores
		function setScores() {
				getScores();
				if (score > highScore) {
						highScore = score;
						localStorage.setItem("highScore", score);
						alert("Your new personal high score is: " + score + "! Congratulations!");
				}
				fifthScore = fourthScore;
				fourthScore = thirdScore;
				thirdScore = secondScore;
				secondScore = firstScore;
				firstScore = score;
				localStorage.setItem("fifthScore", fifthScore);
				localStorage.setItem("fourthScore", fourthScore);
				localStorage.setItem("thirdScore", thirdScore);
				localStorage.setItem("secondScore", secondScore);
				localStorage.setItem("firstScore", firstScore);
				updateScores();
		}
		highScore = 0;
		getScores();
		updateScores();

		function enableDisableButtons(status) {
				if (gameStarted) {
						if (gamePaused) {
								startButton.hide();
								stopButton.show();
								pauseButton.hide();
								resumeButton.show();
								overlay.show();
								statusMessage.text("Game Paused");
						} else {
								startButton.hide();
								stopButton.show();
								pauseButton.show();
								resumeButton.hide();
								overlay.hide();
						}
				} else {
						startButton.show();
						stopButton.hide();
						pauseButton.hide();
						resumeButton.hide();
						overlay.show();
						statusMessage.text("GAME OVER");
				}
		}

		function startGame() {
				console.log("START GAME");
				gameStarted = true;
				gamePaused = false;
				points = 0;
				score = 0;
				level = 1;
				pointsStatus.text(points);
				scoreStatus.text(score);
				levelStatus.text(level);
				init();
				enableDisableButtons();
		}

		function endGame() {
				console.log("GAME OVER");
				gameStarted = false;
				// init();
				clearInterval(game_loop);
				enableDisableButtons();

				gameOver.play();

				setScores();
		}

		function pauseGame() {
				gamePaused = true;
				clearInterval(game_loop);
				console.log("Game Paused");
				enableDisableButtons();
		}

		function resumeGame() {
				gamePaused = false;
				clearInterval(game_loop);
				game_loop = setInterval(paint, speed);
				console.log("Game Resumed");
				enableDisableButtons();
		}

		//Updating the score
		function updateScore() {
				var speedLevel = 10 - Math.round(speed / 12);
				score += speedLevel;
				scoreStatus.text(score);
		}

		//Changing the level
		function changeLevel(thisLevel) {
				console.log(thisLevel);
				level = thisLevel;
				console.log(level);
				if (level >= 11) {
						canvasColor = canvasLevelColors[10];
						levelStatus.text("Awesome!");
				} else {
						canvasColor = canvasLevelColors[thisLevel - 1];
						levelStatus.text(level);
				}
		}

		//Let's create the snake
		function create_snake() {
				snake_array = []; //empty array to start with
				for (var i = snakeLength - 1; i >= 0; i--) {
						//this will create a horizontal snake starting from top left
						snake_array.push({
								x: i,
								y: 0
						});
				}
		}

		//Let's create the food now
		function create_food() {
				//This will create a cell with x/y between 0-44 because there are 45(450/10) positions across the rows and columns
				food = {
						x: Math.round(Math.random() * (w - cw) / cw),
						y: Math.round(Math.random() * (h - cw) / cw)
				};
		}

		//Let's paint the snake now
		function paint() {
				console.log("Paint function");
				//To avoid the snake trail we need to paint the BG on every frame
				//Let's paint the canvas now
				ctx.fillStyle = canvasColor;
				ctx.fillRect(0, 0, w, h);
				ctx.strokeStyle = "black";
				ctx.strokeRect(0, 0, w, h);

				//The movement code for the snake to come here.
				//The logic is simple: pop out the tail cell and place it in front of the head cell
				var nx = snake_array[0].x;
				var ny = snake_array[0].y;
				//these were the position of the head cell
				//we will increment it to get the new head position
				//Let's add proper direction based movement now
				if (gameStarted) {
						if (currentDirection != d) currentDirection = d;
						if (currentDirection == "right") nx++;
						else if (currentDirection == "left") nx--;
						else if (currentDirection == "up") ny--;
						else if (currentDirection == "down") ny++;
				}

				//Let's add the game over clause now
				//this will end the game if the snake hits the wall
				//Let's add the code for body collision
				//now if the head of the snake bumps into the body, the game will end
				if (nx == -1 || nx == (w / cw) || ny == -1 || ny == (h / cw) || check_collision(nx, ny, snake_array)) {
						//end game
						endGame();
						//Let's organize the code a bit now
						//return;
				}

				//Let's write the code to make the snake eat the food
				//The logic is simple: if the new head position matches with that of the food, create a new head instead of moving the tail
				var tail;
				if (nx == food.x && ny == food.y) {
						tail = {
								x: nx,
								y: ny
						};
						var prevPoints = points;
						points++;
						pointsStatus.text(points);
						updateScore();

						chomp.play();

						if (points == levelChange) {
								console.log("change level");
								level++;
								levelChange += levelFrequency;
								changeLevel(level);

								levelUp.play();
						}

						//create new food
						create_food();
				} else {
						tail = snake_array.pop(); //pops out the last cell
						tail.x = nx;
						tail.y = ny;
				} //the snake can now eat the food

				snake_array.unshift(tail); //puts back the tail as the first cell

				//Let's paint the level
				var level_text = "Level: " + level;
				ctx.font = "normal normal 170px sans-serif";
				if (level >= 11) {
						level_text = "Awesome!";
						ctx.font = "normal normal 150px sans-serif";
				}
				ctx.fillStyle = "rgba(255,255,255,0.3)";
				ctx.strokeStyle = "rgba(0,0,0,0.2)";
				ctx.fillText(level_text, w / 8, h / 1.75);
				ctx.strokeText(level_text, w / 8, h / 1.75);

				for (var i = 0; i < snake_array.length; i++) {
						var c = snake_array[i];
						//Let's paint 10px wide cells
						if (i === 0) {
								paint_cell(c.x, c.y, "snakeHead");
						} else {
								paint_cell(c.x, c.y, "snake");
						}
				}

				//Let's paint the food
				paint_cell(food.x, food.y, "food");

		}

		//Let's first create a generic function to paint cells
		function paint_cell(x, y, object) {
				if (object == "snakeHead") {
						ctx.fillStyle = snakeHeadColor;
						ctx.strokeStyle = snakeHeadOutline;
				} else if (object == "snake") {
						ctx.fillStyle = snakeBodyColor;
						ctx.strokeStyle = snakeBodyOutline;
				} else if (object == "food") {
						ctx.fillStyle = foodColor;
						ctx.strokeStyle = foodOutline;
				}
				ctx.fillRect(x * cw, y * cw, cw, cw);
				ctx.strokeRect(x * cw, y * cw, cw, cw);
		}

		function check_collision(x, y, array) {
				//This function will check if the provided x/y coordinates exists in an array of cells or not
				for (var i = 0; i < array.length - 1; i++) {
						if (array[i].x == x && array[i].y == y) {
								return true;
						}
				}
				return false;
		}

		//Let's add the keyboard controls
		$(document).keydown(function(event) {
				var key = event.which;

				switch (key) {
						// key code for left arrow
						case 37:
								//we will add another clause to prevent reverse gear
								event.preventDefault();
								if (currentDirection != "right") d = "left";
								break;

								// key code for right arrow
						case 39:
								event.preventDefault();
								if (currentDirection != "left") d = "right";
								break;

								// key code for up arrow
						case 38:
								event.preventDefault();
								if (currentDirection != "down") d = "up";
								break;

								// key code for down arrow
						case 40:
								event.preventDefault();
								if (currentDirection != "up") d = "down";
								break;

								// key code for spacebar key
						case 32:
								event.preventDefault();
								if (!gamePaused) {
										pauseGame();
								} else if (gamePaused) {
										resumeGame();
								}
								break;

								// key code for enter key
						case 13:
								event.preventDefault();
								if (!gameStarted) {
										startGame();
								} else if (gameStarted) {
										endGame();
								}
								break;
				}
				//the snake is now keyboard controlled
				return false;
		});

});
            
          
!
999px
Loading ..................

Console