I am currently having issues with a game I am making for fun. I am quite new to Javascript, HTML, and CSS, hence the code that will be shown will not be very good. Anyway, the issue I am experiencing is the button activation part of my code not functioning. Here is the code (in case there are other errors), and the specific problematic area is highlighted.
//Variables and Other Basic Things
var Specs = ["Basic", "Advanced", "Insane", "Mythical", "Godly"];
var PlayerRanks = ["Begginer Grinder", "Advanced Grinder", "Insane Grinder", "Mythic Grinder", "Godlike Grinder"];
var Random = 1;
//Random Numbers
function RandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
//Player Things
var Player = {
spec: "Plain",
rank: "Begginer Grinder",
points: 1000,
pointIncreaseAmount: 1,
timeToIncrease: 10000,
levelIncrease: function() {
this.points += this.pointIncreaseAmount
}
}
//Stats of different specs
function StatChange() {
if (Player.spec == "Basic") {
Player.pointIncreaseAmount = 2;
Player.timeToIncrease = 5000;
} else if (Player.spec == "Advanced") {
Player.pointIncreaseAmount = 5;
Player.timeToIncrease = 4000;
} else if (Player.spec == "Epic") {
Player.pointIncreaseAmount = 10;
Player.timeToIncrease = 3000;
} else if (Player.spec == "Mythical") {
Player.pointIncreaseAmount = 25;
Player.timeToIncrease = 2000;
} else if (Player.spec == "Godly") {
Player.pointIncreaseAmount = 50;
Player.timeToIncrease = 1000;
}
document.getElementById("SpecDisplay").innerHTML = "Your current spec is " + Player.spec;
}
function OpenBasicCrate() {
Random = RandomInt(1, 129);
if (Random < 75) {
Player.spec = "Basic";
Random = 1;
} else if (Random >= 75 && Random < 120) {
Player.spec = "Advanced";
Random = 1;
} else if (Random >= 120 && Random < 129) {
Player.spec = "Epic";
Random = 1;
}
StatChange();
}
function OpenBetterCrate() {
Random = RandomInt(1, 105);
if (Random < 30) {
Player.spec = "Basic";
Random = 1;
} else if (Random >= 30 && Random < 85) {
Player.spec = "Advanced";
Random = 1;
} else if (Random >= 85 && Random <= 105) {
Player.spec = "Epic";
Random = 1;
}
StatChange();
}
function OpenAdvancedCrate() {
Random = RandomInt(1, 80);
if (Random < 30) {
Player.spec = "Advanced";
Random = 1;
} else if (Random >= 30 && Random <= 70) {
Player.spec = "Epic";
Random = 1;
} else if (Random >= 70 && Random < 80) {
PLayer.spec = "Mythical";
Random = 1;
}
StatChange();
}
function OpenBetterAdvancedCrate() {
Random = RandomInt(1, 85);
if (Random < 80) {
Player.spec = "Mythical";
Random = 1;
} else if (Random >= 80 && Random <= 85) {
Player.spec = "Epic";
Random = 1;
}
StatChange();
}
function OpenMythicalCrate() {
Random = RandomInt(1, 100);
if (Random < 95) {
Player.spec = "Mythical";
Random = 1;
} else if (Random >= 95 && Random < 100) {
Player.spec = "Godly";
Random = 1;
}
}
//Start Command also Repeating Code
function Start() {
const pointGain = setInterval(function() {
Player.levelIncrease()
}, Player.timeToIncrease);
const alertPoints = setInterval(function() {
document.getElementById("Score").innerHTML = "Score: " + Player.points
}, 101);
}
//Checking button clicks
if (document.getElementById('Start').clicked == true) {
Start(); //Start button
}
//Checking crates and if the buttons are pressed
//HERE
if (document.getElementById("OpenCrateA").clicked == true) {
if (Player.points >= 50) {
OpenBasicCrate();
Player.points -= 50;
} else if (Player.points < 50) {
document.getElementById("DisplayError").style.display = "block";
setTimeout(function() {
document.getElementById("DisplayError").style.display = "none";
}, 3000);
}
}
if (document.getElementById("OpenCrateB").clicked == true) {
if (Player.points >= 125) {
OpenBetterCrate();
Player.points -= 125;
} else if (Player.points < 125) {
document.getElementById("DisplayError").style.display = "block";
setTimeout(function() {
document.getElementById("DisplayError").style.display = "none";
}, 3000); // Come back here later
}
}
if (document.getElementById("OpenCrateC").clicked == true) {
if (Player.points >= 300) {
OpenAdvancedCrate();
Player.points -= 300;
} else if (Player.points < 300) {
document.getElementById("DisplayError").style.display = "block";
setTimeout(function() {
document.getElementById("DisplayError").style.display = "none";
}, 3000);
}
}
if (document.getElementById("OpenCrateD").clicked == true) {
if (Player.points >= 1500) {
OpenBetterAdvancedCrate();
Player.points -= 1500;
} else if (Player.points < 1500) {
document.getElementById("DisplayError").style.display = "block";
setTimeout(function() {
document.getElementById("DisplayError").style.display = "none";
}, 3000);
}
}
if (document.getElementById("OpenCrateE").clicked == true) {
if (Player.points >= 15000) {
OpenMythicalCrate();
Player.points -= 15000;
} else if (Player.points < 15000) {
document.getElementById("DisplayError").style.display = "block";
setTimeout(function() {
document.getElementById("DisplayError").style.display = "none";
}, 3000);
}
}
//TO HERE
body {
background-image: url(https://cdn.discordapp.com/attachments/656847228219949067/855371548860350474/backgroundImage.png);
height: 500px;
width: 800px;
font-family: "Lucida Console", "Courier New", monospace;
}
img {
position: absolute;
right: 5px;
top: 375px;
width: 150px;
height: 150px;
outline: 3px dotted black;
}
.OpenCrateA {
background-image: url(https://cdn.discordapp.com/attachments/656847228219949067/855379404020121620/backgroundImage.png);
width: 100px;
height: 100px;
position: absolute;
top: 425px;
left: 5px;
outline: 2px solid black;
}
.OpenCrateB {
background-image: url(https://cdn.discordapp.com/attachments/656847228219949067/855379943093829642/backgroundImage.png);
width: 100px;
height: 100px;
position: absolute;
top: 425px;
left: 110px;
outline: 2px solid black;
}
.OpenCrateC {
background-image: url(https://cdn.discordapp.com/attachments/656847228219949067/855379735671865344/backgroundImage.png);
width: 100px;
height: 100px;
position: absolute;
top: 425px;
left: 215px;
outline: 2px solid black;
}
.OpenCrateD {
background-image: url(https://cdn.discordapp.com/attachments/656847228219949067/855380083225526282/backgroundImage.png);
width: 100px;
height: 100px;
position: absolute;
top: 425px;
left: 320px;
outline: 2px solid black;
}
.OpenCrateE {
background-image: url(https://cdn.discordapp.com/attachments/656847228219949067/855380283788492810/backgroundImage.png);
width: 100px;
height: 100px;
position: absolute;
top: 425px;
left: 425px;
outline: 2px solid black;
}
.Start {
width: 100;
height: 30;
font-family: "Lucida Console", "Courier New", monospace;
background-color: red;
outline: 2px solid black;
}
.InstructionMenu {
background-color: blue;
outline: 2px solid black
}
h1 {
font-family: "Lucida Console", "Courier New", monospace;
}
.RankDisplay {
position: absolute;
top: 375px;
background-color: blue;
outline: 3px solid black;
}
<script src="script.js"></script>
<h1 id="welcomingScreen">Welcome to "A Bad Grinding Game!"</h1>
<button id="StartButton" class="Start" onclick="Start()">Start</button>
<p id="Score"> Score: </p>
<p id="RankDisplay" class="RankDisplay"> Your current rank is: "Begginer Grinder"</p>
<p id="SpecDisplay" class="SpecDisplay"> Your current spec is "Plain"</p>
<h2 id="InstructionsMenu" class="InstructionMenu" style="display:none">Instrutions:</h2>
<p id="InstructionsMenu" class="InstructionMenu" style="display:none"> This is a simple grinding game. You have a "spec", which allows you to gain a specific amount of "points" per a specific amount of time. The longer you grind, the better your rank becomes, and a better rank gives a slight point increase. </p>
<p id="DisplayError" style="display:none"> You do not have enough money to purchase this crate!</p>
<img src="https://cdn.discordapp.com/attachments/656847228219949067/855161969615175680/ABGG_icon.png"></img>
<button type="button" class="OpenCrateA" id="OpenCrateA">Open Crate 1</p>
<button type="button" class="OpenCrateB" id="OpenCrateB">Open Crate 2 </button>
<button type="button" class="OpenCrateC" id="OpenCrateC">Open Crate 3 </button>
<button type="button" class="OpenCrateD" id="OpenCrateD">Open Crate 4 </button>
<button type="button" class="OpenCrateE" id="OpenCrateE">Open Crate 5 </button>
Your button activation logic is not working because you're checking if button.clicked == true. As far as I am aware, button HTML events don't even have a clicked property.
Even if they did, while you are indeed correct that that would check if a button is pressed, it would only so once, right when the user first loads the page, so any subsequent presses would be ignored.
The method you are looking for is button.onclick, which you can read about here. With it, your code would look something like:
document.getElementById("OpenCrateA").onclick = function(){
if (Player.points >= 50){
OpenBasicCrate();
Player.points -= 50;
}
else if (Player.points < 50){
document.getElementById("DisplayError").style.display = "block";
setTimeout(function(){ document.getElementById("DisplayError").style.display = "none"; }, 3000);
}
}
This registers a listener for the button's click event, which will trigger whenever the button is pressed and call the logic that you define.
Another issue you may face is that the button element you are trying to select is not defined. This would occur due to your <script> tag being at the top of your HTML, so it runs before any of your HTML is even rendered. I would suggest moving it to the bottom of your HTML <body>
Related
I am currently constructing a roulette system programme ( this is more to keep me from betting than to bet! ) and am just doing the basic framework but already hit a problem with the main window '#results' not scrolling when it is filled with the results. The scroll needs to follow the latest line of content so the latest returned from the input in the modal box is always showing at the bottom. I have spent hours on lots of possible solutions to no avail.
Here is the code: ( i apologise for the length of the full script )
<!DOCTYPE html>
<html>
<body>
<div id="results">
</div>
<div id="modal">
<div id="modal-content">
<p>Select a number between 0 and 36:</p>
<div id="numberButtons"></div>
<button id="close-button" onclick="closeModal()">Close</button>
</div>
</div>
</div>
<style>
/* The modal background */
#modal {
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
/* The modal content */
#modal-content {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #fefefe;
padding: 20px;
width: 18%;
border: 3px solid black;
}
/* The close button */
#close-button {
display: block;
margin: 0 auto;
}
#numberButtons button {
color: white;
width: 50px;
height: 50px;
font-size:30px;
font-weight:600;
}
#modal.inactive{
opacity: 0.2;
}
</style>
<script>
var bankRoll = parseFloat(prompt("Please enter your starting bankroll:"));
if(isNaN(bankRoll)){
bankRoll = parseFloat(prompt("Invalid input. Please enter a valid number for your starting bankroll:"));
}
bankRoll = bankRoll.toFixed(2);
var spinNumber=0;
var backline="";
var isDragging = false;
var currentX;
var currentY;
var initialX;
var initialY;
var xOffset = 0;
var yOffset = 0;
const modalContent = document.querySelector("#modal-content");
modalContent.addEventListener("mousedown", dragStart);
modalContent.addEventListener("mouseup", dragEnd);
modalContent.addEventListener("mousemove", drag);
function dragStart(e) {
initialX = e.clientX - xOffset;
initialY = e.clientY - yOffset;
if (e.target === modalContent) {
isDragging = true;
}
}
let inactivityTimeout;
function dragEnd(e) {
initialX = currentX;
initialY = currentY;
isDragging = false;
clearTimeout(inactivityTimeout);
inactivityTimeout = setTimeout(() => {
modal.classList.add("inactive")
}, 15000)
}
function drag(e) {
if (e.buttons === 1) {
e.preventDefault();
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
xOffset = currentX;
yOffset = currentY;
setTranslate(currentX, currentY, modalContent);
clearTimeout(inactivityTimeout);
modal.classList.remove("inactive")
}
}
function setTranslate(xPos, yPos, el) {
el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
}
function getNumberType(number) {
if (number === 0) {
return "green";
} else if (number % 2 === 0) {
return "even";
} else {
return "odd";
}
}
function roulette(number) {
// Determine the color of the number
var color;
if (number === 0) {
color = "Green";
} else if (number === 1 || number === 3 || number === 5 || number === 7 || number === 9 || number === 12 || number === 14 || number === 16 || number === 18 || number === 19 || number === 21 || number === 23 || number === 25 || number === 27 || number === 30 || number === 32 || number === 34 || number === 36) {
color = "Red";
} else {
color = "Black";
}
// Map the color names to CSS color values
if (color === "Green") {
return "rgb(0, 128, 0)";
} else if (color === "Red") {
return "rgb(255, 0, 0)";
} else {
return "rgb(0, 0, 0)";
}
}
function backgroundline() {
if (spinNumber % 2 === 0) {
backline="#D3D3D3"
} else {
backline="#E5E4E2";
}
}
function spin(number) {
// Determine the color of the number
var color = roulette(number);
spinNumber= spinNumber+1;
bankRoll=bankRoll-10;
backgroundline();
// Display the result
var resultsDiv = document.getElementById("results");
var resultHTML = `${number}`;
resultHTML = `<div style="padding:10px 0; background: ${backline};vertical-align:middle;margin-bottom:- 20px;">
<div style="padding:5px; display: inline-block; background: yellow; color:black;vertical-align:middle; width:30px; text-align:right;">${spinNumber}</div>
<div style="margin: 0 10px; display:inline-block; width: 70px; text-align:center;vertical-align:middle">£ ${bankRoll}</div>
<div style="color: white; padding: 5px; display: inline-block; width:30px; padding-top:15px;vertical-align:middle; font-size: 25px; font-weight:600; height:30px; text-align:center; background-color: ${color}; ">${resultHTML}</div>
</div>
<br style="height:0px;"/>`;
resultsDiv.innerHTML += resultHTML;
}
// Set up the buttons
for (let i = 0; i <= 36; i++) {
let button = document.createElement("button");
button.innerHTML = i;
button.style.backgroundColor = roulette(i);
button.addEventListener("click", function() {
spin(i);
});
document.getElementById("numberButtons").appendChild(button);
}
function closeModal() {
// Get the modal element
var modal = document.getElementById("modal");
// Remove the modal element from the DOM
modal.remove();
}
</script>
</body>
</html>
I have tried lots of solutions on Stack Overflow and across the Internet further field that I thought might work but it just doesn't seem to want to do it.
after adding element in Results div you have to call this function.
add this function
window.scrollTo(0, document.body.scrollHeight)
after this line
resultsDiv.innerHTML += resultHTML;
My issue is with function onBall3Click1 (The code is at the bottom).
The ball, on click, is supposed to function as a lightbulb: when it's ON -> YELLOW color within ball, when it's OFF -> GRAY.
I have been covering the logic behind it for way too long for something so simple, and I just can't find the issue..
When I click on it, it changes the text to 'ON', but the colour remains gray..when it should be yellow.
Thanks in advance!
<html>
<head>
<style>
body {
background-color: black;
text-align: center;
}
h1 {
color: white;
}
div {
width: 100px;
height: 100px;
margin: auto;
margin-bottom: 10px;
border-radius: 50%;
transition: 0.3s;
line-height: 50px;
color: black
}
.ball1 {
background-color: yellow;
border: 6px solid gray;
color: black
}
.ball2 {
background-color: orange;
}
.ball3 {
background-color: gray;
}
.ball4 {
background-color: brown;
}
</style>
</head>
<body>
<h1>The Ball</h1>
<div class="ball1" onclick="onBall1Click()">
GROW 250 ORANGE
</div>
<div class="ball2" onclick="onBall2Click()">
GROW+50 SHRINK-50
</div>
<div class="ball3" onclick="onBall3Click1()">
OFF
</div>
<div class="ball4" onclick="onBall4Click()">
PROMPT
</div>
<script>
var ball1Size = 100;
var ball1SizeStep = 50;
function onBall1Click() {
var ball1 = document.querySelector('.ball1');
ball1Size = ball1Size + 50;
if (ball1Size > 400) {
ball1Size = 100;
}
ball1.innerText = ball1Size;
ball1.style.width = ball1Size;
ball1.style.height = ball1Size;
ball1.innerText = ball1Size;
if (ball1Size == 250) {
ball1.style.color = 'Orange';
} else {
ball1.style.color = 'black'
}
}
var ball2Size = 100;
var ball2SizeStep = 50;
function onBall2Click() {
var ball2 = document.querySelector('.ball2');
ball2Size += ball2SizeStep;
if (ball2Size === 400) {
ball2SizeStep = -50;
} else if (ball2Size === 100) {
ball2SizeStep = 50;
}
if (ball2Size > 100) {
ball2.style.backgroundColor = 'red';
} else if (ball2Size === 100) {
ball2.style.backgroundColor = 'Orange';
}
ball2.innerText = ball2Size;
ball2.style.width = ball2Size;
ball2.style.height = ball2Size;
}
function onBall3Click1() {
var ball3 = document.querySelector('.ball3');
console.log("HII0");
if (ball3.innerText == 'OFF') {
ball3.innerText = 'ON';
} else if (ball3.innerText == 'ON') {
ball3.innerText = 'OFF'
}
console.log(ball3.style.backgroundColor)
if (ball3.style.backgroundColor === 'gray') {
console.log("HII1");
ball3.style.backgroundColor = 'Yellow';
} else if (ball3.style.backgroundColor == 'Yellow') {
console.log("HII1");
ball3.style.backgroundColor = 'gray'
}
}
var ball4Size = 100;
function onBall4Click() {
var ball4 = document.querySelector('.ball4');
var user_input = prompt('Write ball size number 4 but do not exaggerate : ')
let user_input_int = parseInt(user_input)
console.log(user_input_int);
if (user_input_int < 1000) {
ball4.style.width = user_input_int;
ball4.style.height = user_input_int;
} else {
alert("Too big!");
}
}
</script>
</body>
</html>
You could merge the two if/elseif chains in the onBall3Click1 function like so:
function onBall3Click1() {
var ball3 = document.querySelector('.ball3');
console.log("HII0");
if (ball3.innerText == 'OFF') {
ball3.innerText = 'ON';
ball3.style.backgroundColor = 'yellow';
} else if (ball3.innerText == 'ON') {
ball3.innerText = 'OFF'
ball3.style.backgroundColor = 'gray'
}
console.log(ball3.style.backgroundColor)
}
I have a graph that is rendering its values as a div inside the body element with a class according to their number values. This is working fine. But next I need to sort the divs according to their number values or background color. BUT, it needs to start on the lower left corner of the page and fan out upwards to towards the right as the numbers increase. Basically just like a line graph.
I'd like to stay away from libraries if at all possible.
How would I approach this? Thank you all.
let interval = setInterval(makeDivs, 5);
function makeDivs(){
let cont = checkHeight();
if(cont){
let div = document.createElement('div');
let randNum = Math.random() * 100;
if(randNum < 20) { div.classList.add('blue') }
if(randNum >= 20 && randNum < 40) { div.classList.add('green') }
if(randNum >= 40 && randNum < 60) { div.classList.add('yellow') }
if(randNum >= 60 && randNum < 80) { div.classList.add('orange') }
if(randNum >= 80 && randNum < 101) { div.classList.add('red') }
div.textContent = randNum.toFixed(2);
document.querySelector('body').appendChild(div);
} else {
alert('done');
clearInterval(interval);
sortDivs(); // Begin sorting divs
}
}
function checkHeight(){
let w = window.innerHeight;
let b = document.querySelector('body').offsetHeight;
if(b < w) {
return true;
} else {
return false;
}
}
function sortDivs(){
document.querySelector("body div:last-child").remove();
alert('sorting now...')
}
* { box-sizing: border-box;}
body { width: 100vw; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: end;}
body div { width: calc(10% + 1px); text-align: center; border: 1px solid #ddd; margin: -1px 0 0 -1px; padding: 10px;}
body div.blue { background: aqua; }
body div.green { background: green; }
body div.yellow { background: yellow; }
body div.orange { background: orange; }
body div.red { background: red; }
UPDATE!!!
So I have this so far based on the feed back down below. The problem now is the sorting is only happening laterally and not on an angle (spreading right and to the top).
let interval = setInterval(makeDivs, 10);
function makeDivs(){
let cont = checkHeight();
if(cont){
let div = document.createElement('div');
let randNum = Math.random() * 100;
if(randNum < 20) { div.classList.add('blue') }
if(randNum >= 20 && randNum < 40) { div.classList.add('green') }
if(randNum >= 40 && randNum < 60) { div.classList.add('yellow') }
if(randNum >= 60 && randNum < 80) { div.classList.add('orange') }
if(randNum >= 80 && randNum < 101) { div.classList.add('red') }
div.textContent = randNum.toFixed(2);
document.querySelector('.outPut').appendChild(div);
} else {
clearInterval(interval);
document.querySelector(".outPut div:last-child").remove();
compileArrays(); // Begin sorting divs
}
}
function checkHeight(){
let w = window.innerHeight;
let b = document.querySelector('.outPut').offsetHeight;
if(b < w) {
return true;
} else {
return false;
}
}
function compileArrays(){
let divs = document.querySelectorAll('.outPut div');
let bArr = [], gArr = [], yArr = [], oArr = [], rArr = [];
divs.forEach( (d) => {
if( d.classList.contains('blue') ){ bArr.push(d) }
if( d.classList.contains('green') ){ gArr.push(d) }
if( d.classList.contains('yellow') ){ yArr.push(d) }
if( d.classList.contains('orange') ){ oArr.push(d) }
if( d.classList.contains('red') ){ rArr.push(d) }
});
let finalArr = sortArray(bArr).concat(sortArray(gArr)).concat(sortArray(yArr)).concat(sortArray(oArr)).concat(sortArray(rArr));
newDom(finalArr);
}
function sortArray(arr){
let newArr = arr;
newArr.sort( (a, b) => {
return a.innerText - b.innerText;
});
return newArr;
}
function newDom(arr){
let b = document.querySelector('.outPut');
b.innerHTML = '';
arr.reverse();
arr.forEach((a) => {
b.appendChild(a);
});
}
* { box-sizing: border-box;}
body { width: 100vw; height: 100vh; margin: 0; padding: 0; display: flex; align-items: flex-end;}
body .outPut { flex: 1; display: flex; flex-wrap: wrap; flex-direction:row-reverse; }
body .outPut div { width: calc(10% + 1px); text-align: center; border: 1px solid #ddd; margin: -1px 0 0 -1px; padding: 10px;}
body .outPut div.blue { background: aqua; }
body .outPut div.green { background: #44df15; }
body .outPut div.yellow { background: yellow; }
body .outPut div.orange { background: orange; }
body .outPut div.red { background: red; }
<div class="outPut"></div>
Supposed you already have a mechanism to organise such DIVs in a grid as shown, the following should give you what you are looking for:
var items = divList.filter((div) => div.nodeType == 1); // get rid of the whitespace text nodes
items.sort(function(a, b) {
return a.innerHTML == b.innerHTML
? 0
: (a.innerHTML > b.innerHTML ? 1 : -1);
});
Then, place them back in the DOM as needed, example:
for (i = 0; i < items.length; ++i) {
divList.appendChild(items[i]);
}
This worked with the first code example!!!
try this sortDivs function:
function sortDivs() {
document.querySelector("body div:last-child").remove();
alert('sorting now...')
let toSort = document.getElementsByTagName("div")
toSort = Array.prototype.slice.call(toSort, 0)
toSort.sort((a, b) => {
let aord = parseFloat(a.textContent);
let bord = parseFloat(b.textContent);
return bord - aord;
})
document.body.innerHTML = ""
for(var i = 0, l = toSort.length; i < l; i++) {
document.querySelector('body').appendChild(toSort[i]);
}
}
and in the css file set flex-wrap to wrap-reverse. Hope I could help :)
PS: please, implement some else if instead of doing only if
Here is a small fiddle with my sample code demonstrating a simple solution in pure JavaScript and absolute CSS positioning for what you are trying to achieve. Link
As some pointed out already, there might be a library, that already provides a better and complete solution for this - I did not research if it is so.
Code:
file.js
var container = document.getElementById("container")
var results = [1,2,3,4,5,6,7,8]
//you can pre-calculate the order of the distances
//here already orderdered array [distanec][X-axis][Y-axis]
var distances =[[0,0,0],
[1,1,0],
[1,0,1],
[1.414, 1,1],
[2,0,2],
[2,2,0],
[2.234, 2,1],
[2.234, 1,2]]
for (i = 0; i < results.length; i++){
var newDiv = document.createElement("div")
newDiv.className = "result"
newDiv.innerHTML = results[i]
newDiv.style.left = distances[i][1]*20 + "px"
newDiv.style.bottom = distances[i][2]*20 + "px"
container.appendChild(newDiv)
}
function setColor(element){
// set class based on value - you already have this part
}
style.css
#container {
border: 4px;
border-color: red;
border-style: solid;
height: 200px;
width: 200px;
position: relative;
}
.result{
border: 2px;
width: 20px;
height: 20px;
position: absolute;
border-color: blue;
border-style: solid;
text-align: center;
}
site.html
<div id="container">
</div>
Output:
I would like to make the face of this snake an image. Currently, it using a fill style with a color but I would like it to be an image. How can I do it with this code?
In addition, I want to find out how to add arrows so that it could work on a mobile phone. Thank you for anyone who can help or provide insight.
(function() {
/////////////////////////////////////////////////////////////
// Canvas & Context
var canvas;
var ctx;
// Snake
var snake;
var snake_dir;
var snake_next_dir;
var snake_speed;
// Food
var food = {
x: 0,
y: 0
};
// Score
var score;
// Wall
var wall;
// HTML Elements
var screen_snake;
var screen_menu;
var screen_setting;
var screen_gameover;
var button_newgame_menu;
var button_newgame_setting;
var button_newgame_gameover;
var button_setting_menu;
var button_setting_gameover;
var ele_score;
var speed_setting;
var wall_setting;
/////////////////////////////////////////////////////////////
var activeDot = function(x, y) {
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(x * 10, y * 10, 10, 10);
}
/////////////////////////////////////////////////////////////
var changeDir = function(key) {
if (key == 38 && snake_dir != 2) {
snake_next_dir = 0;
} else {
if (key == 39 && snake_dir != 3) {
snake_next_dir = 1;
} else {
if (key == 40 && snake_dir != 0) {
snake_next_dir = 2;
} else {
if (key == 37 && snake_dir != 1) {
snake_next_dir = 3;
}
}
}
}
}
/////////////////////////////////////////////////////////////
var addFood = function() {
food.x = Math.floor(Math.random() * ((canvas.width / 10) - 1));
food.y = Math.floor(Math.random() * ((canvas.height / 10) - 1));
for (var i = 0; i < snake.length; i++) {
if (checkBlock(food.x, food.y, snake[i].x, snake[i].y)) {
addFood();
}
}
}
/////////////////////////////////////////////////////////////
var checkBlock = function(x, y, _x, _y) {
return (x == _x && y == _y) ? true : false;
}
/////////////////////////////////////////////////////////////
var altScore = function(score_val) {
ele_score.innerHTML = String(score_val);
}
/////////////////////////////////////////////////////////////
var mainLoop = function() {
var _x = snake[0].x;
var _y = snake[0].y;
snake_dir = snake_next_dir;
// 0 - Up, 1 - Right, 2 - Down, 3 - Left
switch (snake_dir) {
case 0:
_y--;
break;
case 1:
_x++;
break;
case 2:
_y++;
break;
case 3:
_x--;
break;
}
snake.pop();
snake.unshift({
x: _x,
y: _y
});
// --------------------
// Wall
if (wall == 1) {
// On
if (snake[0].x < 0 || snake[0].x == canvas.width / 10 || snake[0].y < 0 || snake[0].y == canvas.height / 10) {
showScreen(3);
return;
}
} else {
// Off
for (var i = 0, x = snake.length; i < x; i++) {
if (snake[i].x < 0) {
snake[i].x = snake[i].x + (canvas.width / 10);
}
if (snake[i].x == canvas.width / 10) {
snake[i].x = snake[i].x - (canvas.width / 10);
}
if (snake[i].y < 0) {
snake[i].y = snake[i].y + (canvas.height / 10);
}
if (snake[i].y == canvas.height / 10) {
snake[i].y = snake[i].y - (canvas.height / 10);
}
}
}
// --------------------
// Autophagy death
for (var i = 1; i < snake.length; i++) {
if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
showScreen(3);
return;
}
}
// --------------------
// Eat Food
if (checkBlock(snake[0].x, snake[0].y, food.x, food.y)) {
snake[snake.length] = {
x: snake[0].x,
y: snake[0].y
};
score += 1;
altScore(score);
addFood();
activeDot(food.x, food.y);
}
// --------------------
ctx.beginPath();
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// --------------------
for (var i = 0; i < snake.length; i++) {
activeDot(snake[i].x, snake[i].y);
}
// --------------------
activeDot(food.x, food.y);
// Debug
//document.getElementById("debug").innerHTML = snake_dir + " " + snake_next_dir + " " + snake[0].x + " " + snake[0].y;
setTimeout(mainLoop, snake_speed);
}
/////////////////////////////////////////////////////////////
var newGame = function() {
showScreen(0);
screen_snake.focus();
snake = [];
for (var i = 4; i >= 0; i--) {
snake.push({
x: i,
y: 15
});
}
snake_next_dir = 1;
score = 0;
altScore(score);
addFood();
canvas.onkeydown = function(evt) {
evt = evt || window.event;
changeDir(evt.keyCode);
}
mainLoop();
}
/////////////////////////////////////////////////////////////
// Change the snake speed...
// 150 = slow
// 100 = normal
// 50 = fast
var setSnakeSpeed = function(speed_value) {
snake_speed = speed_value;
}
/////////////////////////////////////////////////////////////
var setWall = function(wall_value) {
wall = wall_value;
if (wall == 0) {
screen_snake.style.borderColor = "#606060";
}
if (wall == 1) {
screen_snake.style.borderColor = "#FFFFFF";
}
}
/////////////////////////////////////////////////////////////
// 0 for the game
// 1 for the main menu
// 2 for the settings screen
// 3 for the game over screen
var showScreen = function(screen_opt) {
switch (screen_opt) {
case 0:
screen_snake.style.display = "block";
screen_menu.style.display = "none";
screen_setting.style.display = "none";
screen_gameover.style.display = "none";
break;
case 1:
screen_snake.style.display = "none";
screen_menu.style.display = "block";
screen_setting.style.display = "none";
screen_gameover.style.display = "none";
break;
case 2:
screen_snake.style.display = "none";
screen_menu.style.display = "none";
screen_setting.style.display = "block";
screen_gameover.style.display = "none";
break;
case 3:
screen_snake.style.display = "none";
screen_menu.style.display = "none";
screen_setting.style.display = "none";
screen_gameover.style.display = "block";
break;
}
}
/////////////////////////////////////////////////////////////
window.onload = function() {
canvas = document.getElementById("snake");
ctx = canvas.getContext("2d");
// Screens
screen_snake = document.getElementById("snake");
screen_menu = document.getElementById("menu");
screen_gameover = document.getElementById("gameover");
screen_setting = document.getElementById("setting");
// Buttons
button_newgame_menu = document.getElementById("newgame_menu");
button_newgame_setting = document.getElementById("newgame_setting");
button_newgame_gameover = document.getElementById("newgame_gameover");
button_setting_menu = document.getElementById("setting_menu");
button_setting_gameover = document.getElementById("setting_gameover");
// etc
ele_score = document.getElementById("score_value");
speed_setting = document.getElementsByName("speed");
wall_setting = document.getElementsByName("wall");
// --------------------
button_newgame_menu.onclick = function() {
newGame();
};
button_newgame_gameover.onclick = function() {
newGame();
};
button_newgame_setting.onclick = function() {
newGame();
};
button_setting_menu.onclick = function() {
showScreen(2);
};
button_setting_gameover.onclick = function() {
showScreen(2)
};
setSnakeSpeed(150);
setWall(1);
showScreen("menu");
// --------------------
// Settings
// speed
for (var i = 0; i < speed_setting.length; i++) {
speed_setting[i].addEventListener("click", function() {
for (var i = 0; i < speed_setting.length; i++) {
if (speed_setting[i].checked) {
setSnakeSpeed(speed_setting[i].value);
}
}
});
}
// wall
for (var i = 0; i < wall_setting.length; i++) {
wall_setting[i].addEventListener("click", function() {
for (var i = 0; i < wall_setting.length; i++) {
if (wall_setting[i].checked) {
setWall(wall_setting[i].value);
}
}
});
}
document.onkeydown = function(evt) {
if (screen_gameover.style.display == "block") {
evt = evt || window.event;
if (evt.keyCode == 32) {
newGame();
}
}
}
}
})();
::selection {
color: #FFFFFF;
background: transparent;
}
::-moz-selection {
color: #FFFFFF;
background: transparent;
}
* {
margin: 0;
padding: 0;
font-family: "VT323";
}
body {
background-color: #000000;
}
.wrap {
margin-left: auto;
margin-right: auto;
}
header {
width: 340px;
font-size: 0;
}
canvas {
display: none;
border-style: solid;
border-width: 10px;
border-color: #FFFFFF;
}
canvas:focus {
outline: none;
}
/* Top Styles */
h1 {
display: inline-block;
width: 100px;
font-size: 32px;
color: #FFFFFF;
}
.score {
display: inline-block;
width: 240px;
font-size: 20px;
color: #FFFFFF;
text-align: right;
}
.score_value {
font-size: inherit;
}
/* All screens style */
#gameover a,
#setting a,
#menu a {
display: block;
}
#gameover a,
#setting a:hover,
#menu a:hover {
cursor: pointer;
}
#gameover a:hover::before,
#setting a:hover::before,
#menu a:hover::before {
content: ">";
margin-right: 10px;
}
/* Menu Screen Style */
#menu {
display: block;
width: 340px;
padding-top: 95px;
padding-bottom: 95px;
font-size: 40px;
margin-left: auto;
margin-right: auto;
text-align: center;
color: #FFF;
}
#menu h2 {
-webkit-animation: logo-ani 1000ms linear infinite;
animation: logo-ani 1000ms linear infinite;
margin-bottom: 30px;
}
#menu a {
font-size: 30px;
}
#-webkit-keyframes logo-ani {
50% {
-webkit-transform: scale(1.3, 1.3);
}
100% {
-webkit-transform: scale(1.0, 1.0);
}
}
#keyframes logo-ani {
50% {
transform: scale(1.3, 1.3);
}
100% {
transform: scale(1.0, 1.0);
}
}
/* Game Over Screen Style */
#gameover {
display: none;
width: 340px;
padding-top: 95px;
padding-bottom: 95px;
margin-left: auto;
margin-right: auto;
text-align: center;
font-size: 30px;
color: #FFF;
}
#gameover p {
margin-top: 25px;
font-size: 20px;
}
/* Settings Screen Style */
#setting {
display: none;
width: 340px;
margin-left: auto;
margin-right: auto;
padding-top: 85px;
padding-bottom: 85px;
font-size: 30px;
color: #FFF;
text-align: center;
}
#setting h2 {
margin-bottom: 15px;
}
#setting p {
margin-top: 10px;
}
#setting input {
display: none;
}
#setting label {
cursor: pointer;
}
#setting input:checked+label {
background-color: #FFF;
color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet">
<header class="wrap">
<h1>Snake</h1>
<p class="score">Score: <span id="score_value">0</span></p>
</header>
<canvas class="wrap" id="snake" width="320" height="320" tabindex="1"></canvas>
<!-- Game Over Screen -->
<div id="gameover">
<h2>Game Over</h2>
<p>press <span style="background-color: #FFFFFF; color: #000000">space</span> to begin a</p>
<a id="newgame_gameover">new game</a>
<a id="setting_gameover">settings</a>
</div>
<!-- Setting screen -->
<div id="setting">
<h2>Settings</h2>
<a id="newgame_setting">new game</a>
<p>Speed:
<input id="speed1" type="radio" name="speed" value="120" checked/>
<label for="speed1">Slow</label>
<input id="speed2" type="radio" name="speed" value="75" />
<label for="speed2">Normal</label>
<input id="speed3" type="radio" name="speed" value="35" />
<label for="speed3">Fast</label>
</p>
<p>Wall:
<input id="wallon" type="radio" name="wall" value="1" checked/>
<label for="wallon">On</label>
<input id="walloff" type="radio" name="wall" value="0" />
<label for="walloff">Off</label>
</p>
</div>
<!-- Main Menu Screen -->
<div id="menu">
<h2>Snake</h2>
<a id="newgame_menu">new game</a>
<a id="setting_menu">settings</a>
</div>
Convert your image to a base64 string, then for the first dot/head use the image instead:
var img = new Image(); // Create new img element
img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA21BMVEXoTTvqTTzpUD7nTjzmTTvrUkDpTjzmSznUPSrVPCrnTDrSOSfTOizlTDrvoJnoqJ/pVkTmU0P5urH1p53mSTjjPiv7nZF0f4NZaGvpn5b9s6qDl5iira/+nI/jPirkPyz7lop+iYtleHzsnpT7raOTpqqqtbf4lovnSjf0lorylonpSDbnTDj5oZf2mIzlSDXkOyjIY1vrd2rrWEbZZ1zYQDLsTTroTz/lRjPalY7+///////j19fVSz7tTjvmTjntRjPialzZhH3sVkXsSzniRTTYQTDmSTbmTT3qb45jAAAAAWJLR0Q7OQ70bAAAAAd0SU1FB+QEDw4AEYzMSFoAAABvSURBVAjXY2BgZGJiZmFlZWNgYGDn4GTn4ubhBTJZ+PgFBIWERdgYRMXEJSSlpGVk5RjkFRSVlFVU1dTlGRg0NLW0dXT19JkZGNgMDI2MTUzNgNrMLSytrG1s7eyBbGYHRydnFwYwYHN1c/dgYAAAtKsKjnGo4BwAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDQtMTVUMTQ6MDA6MTctMDQ6MDAVi7z/AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTA0LTE1VDE0OjAwOjE3LTA0OjAwZNYEQwAAAABJRU5ErkJggg==";
for (var i = 0; i < snake.length; i++) {
if (!i) {
ctx.drawImage(img, snake[i].x * 10, snake[i].y * 10);
} else {
activeDot(snake[i].x, snake[i].y);
}
}
I've created a snake game, and when the snake hit the wall or itself, it still wont stop moving. I figured out if I used the clearTimeout(), it would help. but it didn't.
Is there a way to stop the loop? or it is another issue?
jQuery(document).ready(function($) {
init();
});
var move;
function init() {
board.initBoard();
drawSnake();
food.createFood();
}
function play() {
$('.newGame').css('visibility', 'hidden');
$('.playgame').css('visibility', 'hidden');
moveSnake();
getSnakeDir();
}
function gameover() {
clearTimeout(move);
$('.newGame').css('visibility', 'visible');
}
function playGame() {
$('#gameboard').empty();
$('.newGame').hide();
init();
play();
}
var board = {
DIM: 20,
initBoard: function() {
for (var i = 0; i < board.DIM; i++) {
var row = $('<div class="row-' + i + '"></div>');
for (var j = 0; j < board.DIM; j++) {
var col = ('<div class="col-' + j + '-' + i + '"></div>');
$(row).append(col);
}
$("#gameboard").append(row);
}
}
}
var snake = {
position: ['10-10', '10-11', '10-12'],
direction: 'r',
speed: 200,
};
function drawSnake() {
$('.col-10-10').addClass('snake');
$('.col-11-10').addClass('snake');
}
function getSnakeDir() {
$(document).keydown(function(event) {
//event.preventDefault();
if (event.which == 38) {
snake.direction = 'u';
} else if (event.which == 39) {
snake.direction = 'r';
} else if (event.which == 40) {
snake.direction = 'd';
} else if (event.which == 37) {
snake.direction = 'l';
}
});
}
function moveSnake() {
var tail = snake.position.pop();
$('.col-' + tail).removeClass('snake');
var coords = snake.position[0].split('-');
var x = parseInt(coords[0]);
var y = parseInt(coords[1]);
if (snake.direction == 'r') {
x = x + 1;
} else if (snake.direction == 'd') {
y = y + 1;
} else if (snake.direction == 'l') {
x = x - 1;
} else if (snake.direction == 'u') {
y = y - 1;
}
var currentcoords = x + '-' + y;
snake.position.unshift(currentcoords);
$('.col-' + currentcoords).addClass('snake');
//when snake eats food
if (currentcoords == food.coords) {
console.log('true');
$('.col-' + food.coords).removeClass('food');
snake.position.push(tail);
food.createFood();
}
//game over
if (x < 0 || y < 0 || x > board.DIM || y > board.DIM) {
gameover();
}
//if snake touch itself
if (hitItself(snake.position) == true) {
gameover();
}
move=setTimeout(moveSnake, 200);
}
var food = {
coords: "",
createFood: function() {
var x = Math.floor(Math.random() * (board.DIM-1)) + 1;
var y = Math.floor(Math.random() * (board.DIM-1)) + 1;
var fruitCoords = x + '-' + y;
$('.col-' + fruitCoords).addClass('food');
food.coords = fruitCoords;
},
}
function hitItself(array) {
var valuesSoFar = Object.create(null);
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (value in valuesSoFar) {
return true;
}
valuesSoFar[value] = true;
}
return false;
}
.buttonnewgame {
position: relative;
}
.newGame {
position: absolute;
top: 45%;
left: 25%;
padding: 15px;
font-size: 1em;
font-family: arial;
visibility: hidden;
}
.gameContainer{
width: 100%;
}
#gameboard {
background-color:#eee;
padding:3px;
}
.playgame {
position: absolute;
top: 45%;
left: 20%;
padding: 15px;
font-size: 1em;
font-family: arial;
}
/* styling the board */
div[class^='row'] {
height: 15px;
text-align: center;
}
div[class*='col']{
display: inline-block;
border: 1px solid grey;
width: 15px;
height: 15px;
}
/*display the snake*/
.snake {
background-color: blue;
z-index: 99;
}
.food {
background: red;
z-index: 99;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="game">
<div class="buttonnewgame">
<input type="button" name="new game" value="new game" class="newGame" onclick="playGame()" />
<button class="playgame" onclick="play()">Play Game</button>
<div class="gameContainer">
<div id="gameboard">
<!-- snake game in here -->
</div>
</div>
</div>
</div>
There were a few problems, but here is the 'working version' (there are more bugs).
1) I renamed drawSnake to createSnake. You weren't fully reinitializing the snake when you called init(). The snakes position was not being reset in the previous drawSnake method, so it would seem like the game was not playable.
After that there were 2 more bugs.
2) You have to return after you call gameOver or the game never really ends does it? Once you clear the timeout in gameover, you immediately set another Timeout for on the last line of moveSnake() because you didn't return once the game was over. That lead to weird results that made it seem like the game was unresponsive.
3) You were using a combination of visibility none or visible and $.hide(). $.hide() uses display: none, so when you tried to show it again with the visibility style change, its still display: none so the new game button would stop appearing.
My advice to any game coder is to learn how to separate the code that handles how the game works (logic of the game, how the clock ticks, initialization of game state, etc) , and how it is displayed (the html and css). Modeling the game logic after a cleanly written system is easy to read and debug. The code becomes harder to understand and modify when the display code is mixed in with game logic. In theory, our game should work perfectly without any kind of rendering. Then we could write a renderer that produces an HTML canvas, html DOM, text in the command line, or OpenGL.
Heres an old project I never finished that should illustrate a separation between model and view.
http://tando.us/ganix/ganix.htm
jQuery(document).ready(function($) {
init();
});
var move;
function init() {
board.initBoard();
createSnake();
food.createFood();
}
function play() {
$('.newGame').hide();
$('.playgame').hide();
moveSnake();
getSnakeDir();
}
function gameover() {
clearTimeout(move);
$('.newGame').show();
}
function playGame() {
$('#gameboard').empty();
$('.newGame').hide();
init();
play();
}
var board = {
DIM: 20,
initBoard: function() {
for (var i = 0; i < board.DIM; i++) {
var row = $('<div class="row-' + i + '"></div>');
for (var j = 0; j < board.DIM; j++) {
var col = ('<div class="col-' + j + '-' + i + '"></div>');
$(row).append(col);
}
$("#gameboard").append(row);
}
}
}
var snake = {
position: ['10-10', '10-11', '10-12'],
direction: 'r',
speed: 200,
};
function createSnake() {
$('.col-10-10').addClass('snake');
$('.col-11-10').addClass('snake');
snake.position = ['10-10', '10-11', '10-12'];
}
function getSnakeDir() {
$(document).keydown(function(event) {
//event.preventDefault();
if (event.which == 38) {
snake.direction = 'u';
} else if (event.which == 39) {
snake.direction = 'r';
} else if (event.which == 40) {
snake.direction = 'd';
} else if (event.which == 37) {
snake.direction = 'l';
}
});
}
function moveSnake() {
var tail = snake.position.pop();
$('.col-' + tail).removeClass('snake');
var coords = snake.position[0].split('-');
var x = parseInt(coords[0]);
var y = parseInt(coords[1]);
if (snake.direction == 'r') {
x = x + 1;
} else if (snake.direction == 'd') {
y = y + 1;
} else if (snake.direction == 'l') {
x = x - 1;
} else if (snake.direction == 'u') {
y = y - 1;
}
var currentcoords = x + '-' + y;
snake.position.unshift(currentcoords);
$('.col-' + currentcoords).addClass('snake');
//when snake eats food
if (currentcoords == food.coords) {
console.log('true');
$('.col-' + food.coords).removeClass('food');
snake.position.push(tail);
food.createFood();
}
//game over
if (x < 0 || y < 0 || x > board.DIM || y > board.DIM) {
gameover();
return;
}
//if snake touch itself
if (hitItself(snake.position) == true) {
gameover();
return;
}
move=setTimeout(moveSnake, 200);
}
var food = {
coords: "",
createFood: function() {
var x = Math.floor(Math.random() * (board.DIM-1)) + 1;
var y = Math.floor(Math.random() * (board.DIM-1)) + 1;
var fruitCoords = x + '-' + y;
$('.col-' + fruitCoords).addClass('food');
food.coords = fruitCoords;
},
}
function hitItself(array) {
var valuesSoFar = Object.create(null);
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (value in valuesSoFar) {
return true;
}
valuesSoFar[value] = true;
}
return false;
}
.buttonnewgame {
position: relative;
}
.newGame {
position: absolute;
top: 45%;
left: 25%;
padding: 15px;
font-size: 1em;
font-family: arial;
}
.gameContainer{
width: 100%;
}
#gameboard {
background-color:#eee;
padding:3px;
}
.playgame {
position: absolute;
top: 45%;
left: 20%;
padding: 15px;
font-size: 1em;
font-family: arial;
}
/* styling the board */
div[class^='row'] {
height: 15px;
text-align: center;
}
div[class*='col']{
display: inline-block;
border: 1px solid grey;
width: 15px;
height: 15px;
}
/*display the snake*/
.snake {
background-color: blue;
z-index: 99;
}
.food {
background: red;
z-index: 99;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="game">
<div class="buttonnewgame">
<input type="button" name="new game" value="new game" class="newGame" style="display:none;" onclick="playGame()" />
<button class="playgame" onclick="play()">Play Game</button>
<div class="gameContainer">
<div id="gameboard">
<!-- snake game in here -->
</div>
</div>
</div>
You could try not to initiate a new setTimeout call at the and of the moveSnake function, but instead using.
function play() {
$('.newGame').css('visibility', 'hidden');
$('.playgame').css('visibility', 'hidden');
move = setInterval(moveSnake, 200);
getSnakeDir();
}
and remove the
move = setTimeout(moveSnake, 200)
from the moveSnake function and do
function gameover() {
clearInterval(move);
$('.newGame').css('visibility', 'visible');
}