I recently made this game and wanted to ask how to improve it. I made an alert box inside the javascript for when the game ends. It works but it's not beautiful. so I wanted to ask how can I change the Color and the message on the top of the alert box? right now a webpage message has been written.
And I wanted to add that it could be played from the phone something like the arrow buttons. I found something for java but nothing for javascript and wanted to know if its possible and how do I doit?
here is the code:
<html>
<head>
<meta charset='utf-8'/>
<link rel="stylesheet" href="css/style.css">
<h1> <p align="left"><font color="rebeccapurple"> Snake developed by agente00mcm </font></p> </h1>
</head>
<body>
<div class= 'game'>
<div id = 'home'>
<canvas id='mycanvas' width='800' height='800'>
</canvas>
</div>
<p>Press start to start the game!</p>
<button id='btn'>START</button>
</div>
<script>
var mycanvas = document.getElementById('mycanvas');
var ctx = mycanvas.getContext('2d');
var snakeSize = 10;
var w = 800;
var h = 800;
var score = 0;
var snake;
var snakeSize = 10;
var food;
var drawModule = (function () {
var bodySnake = function(x, y) {
ctx.fillStyle = 'green';
ctx.fillRect(x*snakeSize, y*snakeSize, snakeSize, snakeSize);
ctx.strokeStyle = 'darkgreen';
ctx.strokeRect(x*snakeSize, y*snakeSize, snakeSize, snakeSize);
}
var pizza = function(x, y) {
ctx.fillStyle = 'yellow';
ctx.fillRect(x*snakeSize, y*snakeSize, snakeSize, snakeSize);
ctx.fillStyle = 'red';
ctx.fillRect(x*snakeSize+1, y*snakeSize+1, snakeSize-2, snakeSize-2);
}
var scoreText = function() {
var score_text = "Score: " + score;
ctx.fillStyle = 'blue';
ctx.fillText(score_text, 145, h-5);
}
var drawSnake = function() {
var length = 4;
snake = [];
for (var i = length-1; i>=0; i--) {
snake.push({x:i, y:0});
}
}
var paint = function(){
ctx.fillStyle = 'lightgray';
ctx.fillRect(0, 0, w, h);
ctx.strokeStyle = 'black';
ctx.strokeRect(0, 0, w, h);
btn.setAttribute('disabled', true);
var snakeX = snake[0].x;
var snakeY = snake[0].y;
if (direction == 'right') {
snakeX++; }
else if (direction == 'left') {
snakeX--; }
else if (direction == 'up') {
snakeY--;
} else if(direction == 'down') {
snakeY++; }
if (snakeX == -1 || snakeX == w/snakeSize || snakeY == -1 || snakeY == h/snakeSize || checkCollision(snakeX, snakeY, snake)) {
//restart game
alert("Game Over \nYour Score: "+score);
document.location.reload();
btn.removeAttribute('disabled', true);
ctx.clearRect(0,0,w,h);
gameloop = clearInterval(gameloop);
return;
}
if(snakeX == food.x && snakeY == food.y) {
var tail = {x: snakeX, y: snakeY}; //Create a new head instead of moving the tail
score ++;
createFood(); //Create new food
} else {
var tail = snake.pop(); //pops out the last cell
tail.x = snakeX;
tail.y = snakeY;
}
//The snake can now eat the food.
snake.unshift(tail); //puts back the tail as the first cell
for(var i = 0; i < snake.length; i++) {
bodySnake(snake[i].x, snake[i].y);
}
pizza(food.x, food.y);
scoreText();
}
var createFood = function() {
food = {
x: Math.floor((Math.random() * 30) + 1),
y: Math.floor((Math.random() * 30) + 1)
}
for (var i=0; i>snake.length; i++) {
var snakeX = snake[i].x;
var snakeY = snake[i].y;
if (food.x===snakeX && food.y === snakeY || food.y === snakeY && food.x===snakeX) {
food.x = Math.floor((Math.random() * 30) + 1);
food.y = Math.floor((Math.random() * 30) + 1);
}
}
}
var checkCollision = function(x, y, array) {
for(var i = 0; i < array.length; i++) {
if(array[i].x === x && array[i].y === y)
return true;
}
return false;
}
var init = function(){
direction = 'down';
drawSnake();
createFood();
gameloop = setInterval(paint, 80);
}
return {
init : init
};
}());
(function (window, document, drawModule, undefined) {
var btn = document.getElementById('btn');
btn.addEventListener("click", function(){ drawModule.init();});
document.onkeydown = function(event) {
keyCode = window.event.keyCode;
keyCode = event.keyCode;
switch(keyCode) {
case 37:
if (direction != 'right') {
direction = 'left';
}
console.log('left');
break;
case 39:
if (direction != 'left') {
direction = 'right';
console.log('right');
}
break;
case 38:
if (direction != 'down') {
direction = 'up';
console.log('up');
}
break;
case 40:
if (direction != 'up') {
direction = 'down';
console.log('down');
}
break;
}
}
})(window, document, drawModule);
</script>
</body>
</html>
and besides the Problem I wanted to ask how do you guys find it and if it Needs any improvement beside the alert box style.
thanks for your support!
The alert box is a system object and cannot be styled with css. You need to create an element in your page that replicates the behavior of the alert if you want to style it. You can find plenty of libraries that do this such as:
SweetAlert
jQueryUi dialog
AlertifyJs
Have fun developing games :)
Related
I was making a snake game. I have a basic game but I wanted to move the snake more smoothly and specially I wanted to turn the direction of the snake more smoothly.
The problem until now is that I have been removing the tail of the snake and adding it to the head for the movement part.
Moving the snake smoothly is rather easy by reducing the interval for calling the draw function and incrementing the x and y values by small amounts but what I am having problem is with turning the snake smoothly,it is exactly where I am lost/confused as to how to do it like done here (only the turning of snake part and not the changing of head when snake gets blocked)
can anyone help out please? here is my code:
let cvs = "";
let ctx = "";
let size = [];
var direction = 'b';
var speed = 200;
//moving lines on arrow click
window.addEventListener("keydown", moveSomething, false);
function moveSomething(e) {
switch (e.keyCode) {
case 37:
//left
if (direction != 'r') {
direction = 'l';
}
break;
case 38:
//up
if (direction != 'b') {
direction = 't';
}
break;
case 39:
//right
if (direction != 'l') {
direction = 'r';
}
break;
case 40:
//bottom
if (direction != 't') {
direction = 'b';
}
break;
}
}
let food = {
x: Math.floor(Math.random() * 220),
y: Math.floor(Math.random() * 400),
s: 20,
draw: function() {
//this if block rounds off the x and y values
if ((this.x % 20) != 0 || (this.y % 20) != 0) {
if ((this.x % 20) != 0) {
let e = this.x % 20;
e = 20 - e;
this.x = this.x + e;
}
if ((this.y % 20) != 0) {
let e = this.y % 20;
e = 20 - e;
this.y = this.y + e;
}
};
ctx.fillStyle = "red";
ctx.fillRect(this.x, this.y, this.s, this.s);
},
newfood: function() {
this.x = Math.floor(Math.random() * 220);
this.y = Math.floor(Math.random() * 400);
this.draw();
}
}
const snake = {
s: 20,
draw: function(x, y) {
ctx.fillStyle = "green";
ctx.fillRect(this.s * x, this.s * y, this.s, this.s);
ctx.strokeStyle = "black";
ctx.strokeRect(this.s * x, this.s * y, this.s, this.s);
},
snakeInit: function() {
for (let i = 8; i >= 4; i--) {
size.push({
x: i,
y: 6
})
}
},
callDraw: function() {
for (let i = 0; i < size.length; i++) {
this.draw(size[i].x, size[i].y);
}
},
move: function() {
var snakeX = size[0].x;
var snakeY = size[0].y;
if (direction == 'r') {
snakeX++;
} else if (direction == 'l') {
snakeX--;
} else if (direction == 't') {
snakeY--;
} else if (direction == 'b') {
snakeY++;
}
//console.log("Inside move1", speed);
if (snakeX == -1 || snakeX == cvs.width / this.s || snakeY == -1 || snakeY == Math.floor(cvs.height / this.s) || this.checkSelfCollision(snakeX, snakeY, size)) {
ctx.clearRect(0, 0, cvs.width, cvs.height);
gameloop = clearInterval(gameloop);
return;
} else {
ctx.clearRect(0, 0, cvs.width, cvs.height);
food.draw();
}
if (snakeX * 20 == food.x && snakeY * 20 == food.y) {
var tail = {
x: snakeX,
y: snakeY
};
food.eaten();
speed += 200;
food.newfood();
} else {
var tail = size.pop();
tail.x = snakeX;
tail.y = snakeY;
}
size.unshift(tail);
for (let i = 0; i < size.length; i++) {
this.draw(size[i].x, size[i].y);
}
},
checkSelfCollision: function(x, y, arr) {
for (let i = 0; i < arr.length; i++) {
if (arr[i].x == x && arr[i].y == y) {
return true;
}
}
return false;
}
}
function loop() {
const cvsL = document.getElementById("snakes");
const ctxL = cvsL.getContext('2d');
cvs = cvsL;
ctx = ctxL;
snake.snakeInit();
snake.callDraw();
food.draw();
gameloop = setInterval(function() {
snake.move();
}, speed);
}
<body onload="loop();">
<canvas id="snakes" width=240px height=420px style="border: 1px solid black;display: block;"></canvas>
</body>
This snake style game is opened in a popup when you click a button on a page, then you are given a start screen and instructions, you click start to begin the game, and when you lose it displays your score and some text, if you close the popup and reopen it, it still shows the score rather than the start screen.
How do I make it reset when the popup is closed?
jQuery(document).ready(function($) {
$("#canvas").addClass("displayNone");
$("#lose").addClass("displayNone");
$("#post").removeClass("displayNone");
$("#controls").removeClass("displayNone");
$('#play').on('click', function() {
$('#playdiv').addClass('show-game');
})
var canvas = $("#canvas")[0];;
var ctx = canvas.getContext("2d");
var w = $("#canvas").width();
var h = $("#canvas").height();
var cw = 10;
var d;
var food;
var score;
var snake_array;
$("#score").addClass("displayNone");
$("#start").click(function() {
$("#start").addClass("displayNone");
$("#lose").addClass("displayNone");
$("#post").addClass("displayNone");
$("#canvas").removeClass("displayNone");
init();
})
var keys = [];
window.addEventListener("keydown",
function(e) {
keys[e.keyCode] = true;
switch (e.keyCode) {
case 37:
case 39:
case 38:
case 40:
case 32:
e.preventDefault();
break;
default:
break;
}
},
false);
window.addEventListener('keyup',
function(e) {
keys[e.keyCode] = false;
},
false);
// was here
function init() {
d = "right";
create_snake();
create_food();
score = 0;
if (typeof game_loop != "undefined") clearInterval(game_loop);
game_loop = setInterval(paint, 90);
}
// init();
function create_snake() {
var length = 5;
snake_array = [];
for (var i = length - 1; i >= 0; i--) {
snake_array.push({
x: i,
y: 0
});
}
}
function create_food() {
food = {
x: Math.round(Math.random() * (w - cw) / cw),
y: Math.round(Math.random() * (h - cw) / cw),
};
}
function paint() {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, w, h);
ctx.strokeStyle = "black";
ctx.strokeRect(0, 0, w, h);
var nx = snake_array[0].x;
var ny = snake_array[0].y;
if (d == "right") nx++;
else if (d == "left") nx--;
else if (d == "up") ny--;
else if (d == "down") ny++;
if (nx == -1 || nx == w / cw || ny == -1 || ny == h / cw || check_collision(nx, ny, snake_array)) {
document.querySelector('#score').innerText = 'Your score: ' + score;
$("#score").removeClass("displayNone");
$("#lose").removeClass("displayNone");
$("#start").removeClass("displayNone");
$("#canvas").addClass("displayNone");
//init();
return;
}
if (nx == food.x && ny == food.y) {
var tail = {
x: nx,
y: ny
};
score++;
create_food();
} else {
var tail = snake_array.pop();
tail.x = nx;
tail.y = ny;
}
snake_array.unshift(tail);
for (var i = 0; i < snake_array.length; i++) {
var c = snake_array[i];
paint_cell(c.x, c.y);
}
paint_cell(food.x, food.y);
var score_text = "Score: " + score;
ctx.fillText(score_text, 5, h - 5);
}
function paint_cell(x, y) {
ctx.fillStyle = "pink";
ctx.fillRect(x * cw, y * cw, cw, cw);
ctx.strokeStyle = "red";
ctx.strokeRect(x * cw, y * cw, cw, cw);
}
function check_collision(x, y, array) {
for (var i = 0; i < array.length; i++) {
if (array[i].x == x && array[i].y == y) return true;
}
return false;
}
$(document).keydown(function(e) {
var key = e.which;
if (key == "37" && d != "right") d = "left";
else if (key == "38" && d != "down") d = "up";
else if (key == "39" && d != "left") d = "right";
else if (key == "40" && d != "up") d = "down";
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div> unknown HTML please post it here</div>
Seems like you never clean setInterval on exit. Please try to clearInterval. Attach to the window, not local valriable.
const window.timerId = setInterval(init, 9000)
// On init
if (window.game_loop != "undefined") clearInterval(game_loop);
window.game_loop = setInterval(paint, 90);
I'm trying to make a platforming game, and I've been working on the collision for the past 2 weeks. The collision detection is working, but the collision itself (as in, keeping the player out of the tile) is not, no matter what I try. I've tried looking up how to do this, but all I'm finding is how to do the detection part, which I already have done. What do I do after I detect collision?
It was written from scratch, and the player is rectangular, and so are the tiles.
Here's the basic code:
var Player = function(hue, x, y, xSize, ySize, health) {
this.hue = hue;
this.position = new PVector(x, y);
this.originalPosition = new PVector(x, y);
//this.previousPosition = new PVector(x, y);
//this.ppp = new PVector(x, y);
//this.virtualPosition = new PVector(x, y);
//this.predictedPosition = new PVector(x, y);
this.velocity = new PVector(0, 0);
//this.predictedVelocity = new PVector(0, 0);
this.acceleration = new PVector(0, 0);
}
/*Player.prototype.testCollision = function(tile) {
if (this.predictedPosition.y < tile.position.y + tile.size.y && this.predictedPosition.y + this.size.y > tile.size.y && this.predictedPosition.x < tile.position.x + tile.size.x && this.predictedPosition.x + tile.size.x > tile.position.x) {
return false;
} else {
return true;
}
};*/
Player.prototype.ifColliding = function(tile) {
if (this.position.x < tile.position.x + tile.size.x && this.position.x + tile.size.x > tile.position.x) {
/*if (this.position.x + this.size.x > tile.position.x) {
this.position.set(tile.position.x - this.size.x, this.position.y);
} else if (this.position.x < tile.position.x + tile.size.x) {
this.position.set(tile.position.x + tile.size.x, this.position.y);
}*/
this.velocity.set(0, this.velocity.y);
//this.acceleration.set(0, this.acceleration.y);
/*if (this.ppp.x < tile.position.x + tile.size.x && this.ppp.x + tile.size.x > tile.position.x) {
if (this.ppp.x + this.size.x > tile.position.x) {
this.position.set(tile.position.x - this.size.x, this.position.y);
} else if (this.ppp.x < tile.position.x + tile.size.x) {
this.position.set(tile.position.x + tile.size.x, this.position.y);
}
} else if (this.previousPosition.x < tile.position.x + tile.size.x && this.previousPosition.x + tile.size.x > tile.position.x) {
this.position.set(this.ppp.x, this.position.y);
} else {
this.position.set(this.previousPosition.x, this.position.y);
}*/
}
if (this.position.y < tile.position.y + tile.size.y && this.position.y + this.size.y > tile.size.y) {
this.velocity.set(this.velocity.x, 0);
this.acceleration.set(this.acceleration.x, 0);
this.yColliding = true;
/*if (this.position.y + this.size.y > tile.position.y) {
this.position.set(this.position.x, tile.position.y - this.size.y);
rect(0, 20, 0, 0);
} else if (this.position.y < tile.position.y + tile.size.y) {
this.position.set(this.position.x, tile.position.y + tile.size.y);
rect(20, 20, 0, 0);
}*/
}
}
Player.prototype.update = function(tiles) {
//this.ppp.set(this.previousPosition.x, this.previousPosition.y);
//this.previousPosition.set(this.position.x, this.position.y);
this.velocity.add(this.acceleration);
/*this.predictedVelocity.set(this.velocity.x, this.velocity.y);
this.predictedVelocity.add(this.acceleration);
this.virtualPosition.set(this.position.x, this.position.y);
this.virtualPosition.add(this.velocity);
this.predictedPosition.set(this.virtualPosition.x, this.virtualPosition.y);
this.predictedPosition.add(this.predictedVelocity);
var collDcted = false;
for (var i = 0; i < tiles.length; i++) {
if (this.testCollision(tiles[i], true) === false) {
collDcted = false;
}
}*/
//if (collDcted) {
this.position.add(this.velocity);
//}
}
The commented out code is failed attempts. The non-commented code is the closest I could get it to working.
This is a sample collision I made:
<!DOCTYPE html>
<html>
<body>
<p id="Health">Health</p>
<canvas id="gameCanvas" width="600" height="480" style = "border:1px solid gray"></canvas>
<script>
// Adding keyboard evt listener
document.addEventListener("keydown", keyPressed);
document.addEventListener("keyup", keyReleased);
//defining canvas
var canvas;
var canvasContext;
//defining Player variables
var PLAYER_X = 100;
var PLAYER_Y = 100;
var PLAYER_WIDTH = 20;
var PLAYER_HEIGHT = 20;
var PLAYER_HEALTH = 100;
//defining keypress codes
var KEY_LEFT = 37;
var KEY_RIGHT = 39;
var KEY_UP = 38;
var KEY_DOWN = 40;
//variables used to test movement
var keyHeld_Up = false;
var keyHeld_Down = false;
var keyHeld_Left = false;
var keyHeld_Right = false;
//Keypress?
function keyPressed(evt) {
if(evt.keyCode == KEY_UP) {
keyHeld_Up = true;
}
if(evt.keyCode == KEY_DOWN) {
keyHeld_Down = true;
}
if(evt.keyCode == KEY_LEFT) {
keyHeld_Left = true;
}
if(evt.keyCode == KEY_RIGHT) {
keyHeld_Right = true;
}
//prevents page from scrolling when arrow keys are pressed
evt.preventDefault();
}
//Key Released?
function keyReleased(evt) {
if(evt.keyCode == KEY_UP) {
keyHeld_Up = false;
}
if(evt.keyCode == KEY_DOWN) {
keyHeld_Down = false;
}
if(evt.keyCode == KEY_LEFT) {
keyHeld_Left = false;
}
if(evt.keyCode == KEY_RIGHT) {
keyHeld_Right = false;
}
}
//Initialize Canvas and Game Loop
window.onload = function() {
console.log("Is this thing on?");
canvas = document.getElementById('gameCanvas');
canvasContext = canvas.getContext('2d');
var framesPerSecond = 30;
setInterval(function() {
drawObjects();
movePlayer();
damageTest();
}, 1000/framesPerSecond);
}
// Drawing function
function colorRect(x,y, width,height, color, health) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.color = color;
this.health = health;
this.update = function() {
this.draw();
}
this.draw = function() {
canvasContext.beginPath();
canvasContext.rect(this.x, this.y, this.width, this.height);
canvasContext.fillStyle = this.color;
canvasContext.fill();
canvasContext.closePath();
}
};
// Creating Objects
var Screen = new colorRect( 0, 0, 600, 480, 'black', 0);
var Player = new colorRect( PLAYER_X, PLAYER_Y, PLAYER_WIDTH, PLAYER_HEIGHT, 'red', PLAYER_HEALTH);
var Box = new colorRect( 200, 200, 30, 30, 'green', 0);
var Spike = new colorRect( 300, 300, 25, 25, 'white', 0);
// Drawing Objects
function drawObjects() {
Screen.update();
Spike.update();
Player.update();
Box.update();
}
//Collision Test
function collides( a, b ) {
return a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.y + a.height > b.y;
}
//Movement based on keypress events
function movePlayer() {
if(collides( Player, Box ) === false) {
if(keyHeld_Up) {
Player.y -= 2;
}
if(keyHeld_Down) {
Player.y += 2;
}
if(keyHeld_Left) {
Player.x -= 2;
}
if(keyHeld_Right) {
Player.x += 2;
}
}
}
//Testing Collision for damage
function damageTest() {
if(collides( Player, Spike ) === true) {
Player.health -= 1;
}
//Displaying Health in <body>
document.getElementById("Health").innerHTML = "Health: " + Player.health;
}
</script>
</body>
</html>
The code I made stops the player in its tracks completely when hitting the box, but you could create individual collision circumstances for when objects collide on each side of another object, and use those to detect collision.
I hope this helped! If you have any questions regarding this code, just ask! (To run code snippet you might want to go full screen and click inside canvas)
I am new to Javascript. I am trying to make a canvas game similar to Snake, but without the fruits.
The game is over if the player crosses his own path. The following is my code. Do you know how can I determine when the red rectangle crosses its own path and use the game over function?
Thank you!
var player;
var touch = 0;
function startGame() {
myGameArea.start();
player = new component(30, 30, "red", 270, 270);
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 600;
this.canvas.height = 600;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function(e) {
myGameArea.key = e.keyCode;
})
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y) {
this.gamearea = myGameArea;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
}
}
function updateGameArea() {
/*myGameArea.clear();*/
player.speedX = 0;
player.speedY = 0;
if (myGameArea.key == 37) {
player.speedX = -10;
}
if (myGameArea.key == 39) {
player.speedX = 10;
}
if (myGameArea.key == 38) {
player.speedY = -10;
}
if (myGameArea.key == 40) {
player.speedY = 10;
}
if (player.x <= 0 || player.x >= 570 || player.y <= 0 || player.y >= 570) { //When the player goes out of the canvas
gameOver();
}
player.newPos();
player.update();
}
function gameOver() {
var r = confirm("GAME OVER. Restart?");
if (r == true) {
window.location.reload();
} else {
window.open("https://www.google.ca");
}
}
canvas {
padding-left: 0;
padding-right: 0;
margin-left: auto;
margin-right: auto;
display: block;
background-color: #000;
}
<body onload="startGame()">
</body>
Array as a Queue.
The way this game is traditionally done is using a special array type called a queue. Like a real queue you have items added at one end and removed at the other, or first in first out.
Javascript does not have a special array type for a queue but it has all the functions needed to implement a queue.
Push and shift
Array.push(item); // pushes an item onto the top of the array
Array.shift(); // removes an item from the start of the queue
So for the snake game imagine the head as the end of the queue. Every time it moves one forward you place another item on the queue. At the other end you remove an item if the length of the array is longer than the snake length;
var snake = [];
var snakeLength = 10;
function snakeMove(x,y){ // position to move head
checkForHit(x,y); // see below
snake.push({x:x,y:y}); // put another headpiece on the queue
if(snake.length > snakeLength){ // is the length longer than it should be
snake.shift(); // remove a tail item
}
}
To draw the snake you just iterate each part drawing it at the X,y position
To test if the snake has run its self over use the following function
function checkForHit(x,y){
for(var i = 0; i < snake.length; i++){
if(snake[i].x === x && snake[i].y === y){
// Snake has hit its self
}
}
}
When the snake eats something it traditionally grows in length. this is easily done by simply increasing the length variable. snakeLength += 1 makes the queue longer.
And a demo as i have not played the game in so long why not.
"use strict";
var score = 0;
var canvas = document.createElement("canvas");
var scoreE = document.createElement("div");
scoreE.style.color = "white";
scoreE.style.font = "16px arial";
scoreE.style.position = "absolute";
scoreE.style.top = "10px";
scoreE.style.left = "10px";
scoreE.style.width = "600px";
scoreE.style.textAlign = "center";
scoreE.textContent = "Click canvas area to get focus";
canvas.width = 600;
canvas.height = 200;
var ctx = this.canvas.getContext("2d");
document.body.appendChild(canvas);
document.body.appendChild(scoreE);
var lastKeyDown = 0;
window.addEventListener('keydown', function(e) {
lastKeyDown = e.keyCode;
e.preventDefault()
})
var snakePartSize = 8;
var playWidth = canvas.width /snakePartSize;
var playHeight = canvas.height /snakePartSize;
var snake = [];
var snakeLength = 10;
var snakePosX = 0;
var snakePosY = 0;
var snakeDirX = 0;
var snakeDirY = 0;
var snakeSpeed = 16; // number of frame between moves
var gameOver = true;
var instDrawn = false;
var food = [];
var foodFreq = 60;
var yum = 0;
var yumCol = ["red","orange","yellow"];
function startSnake(){
ctx.fillStyle = "black";
ctx.fillRect(0,0,canvas.width,canvas.height);
snakePosX = Math.floor(playWidth / 2);
snakePosY = Math.floor(playHeight / 2);
snakeDirX = 0;
snakeDirY = 0;
snakeLength = 10;
snake = [];
snakeSpeed = 16;
move(snakePosX,snakePosY); // set first pos
food = [];
score = 0;
}
function testHit(x,y){
if(x < 0 || y < 0 || y >= playHeight || x >= playWidth ){
return true;
}
for(var i = 0; i < snake.length; i ++){
if(snake[i].x === x && snake[i].y === y){
return true;
}
}
}
function testFood(x,y){
for(var i = 0; i < food.length; i ++){
if(food[i].x === x && food[i].y === y){
food.splice(i,1);
i --;
yum = 4;
score += 100;
snakeLength += 1;
if(snakeLength % 4 === 0){
snakeSpeed -= snakeSpeed > 1 ? 1:0;
}
}
}
}
function addFood(){
var x = Math.floor(Math.random() * playWidth );
var y = Math.floor(Math.random() * playHeight );
if(!testHit(x,y)){
food.push({x:x,y:y});
drawFood();
}
}
function move(x,y){
if(testHit(x,y)){
gameOver = true;
return;
}
testFood(x,y);
snake.push({x : x, y : y});
drawSnakeHead();
if(snake.length > snakeLength){
drawSnakeTail();
snake.shift();
}
}
function drawYum(){
for(var i = 0; i < snake.length; i ++){
ctx.fillStyle = yumCol[yum];
ctx.fillRect(snake[i].x*snakePartSize, snake[i].y*snakePartSize, snakePartSize, snakePartSize);
}
}
function drawFood(){
var f = food[food.length-1];
ctx.fillStyle = "green";
ctx.fillRect(f.x*snakePartSize, f.y*snakePartSize, snakePartSize, snakePartSize);
}
function drawSnakeHead(){
var head = snake[snake.length-1];
ctx.fillStyle = "red";
ctx.fillRect(head.x*snakePartSize, head.y*snakePartSize, snakePartSize, snakePartSize);
}
function drawSnakeTail(){
var head = snake[0];
ctx.fillStyle = "black";
ctx.fillRect(head.x*snakePartSize, head.y*snakePartSize, snakePartSize, snakePartSize);
}
var counter = 0;
function update(){
counter += 1;
if(!gameOver){
if(snakeDirX === 0){
if(lastKeyDown === 37){ // left
snakeDirX = -1;
snakeDirY = 0;
}
if(lastKeyDown === 39){ // right
snakeDirX = 1;
snakeDirY = 0;
}
}
if(snakeDirY === 0){
if(lastKeyDown === 38){ // up
snakeDirY = -1;
snakeDirX = 0;
}
if(lastKeyDown === 40){ // down
snakeDirY = 1;
snakeDirX = 0;
}
}
lastKeyDown = 0;
if(counter % foodFreq ===0){
addFood();
}
if(counter % snakeSpeed === 0){
snakePosX += snakeDirX;
snakePosY += snakeDirY;
score += 1;
move(snakePosX ,snakePosY);
}
if((counter % 2 === 0) && yum > 0){
yum -= 1;
drawYum();
}
scoreE.textContent = "Score : "+ score;
}
if(gameOver){
if(!instDrawn){
instDrawn = true;
ctx.fillStyle = "white";
ctx.font = "32px arial";
ctx.textAlign = "center";
ctx.fillText("GAME OVER",canvas.width /2, canvas.height /2);
ctx.font = "16px arial";
ctx.fillText("Press a direction key to start.",canvas.width /2, canvas.height /2+32);
}
if(lastKeyDown >= 37 && lastKeyDown <= 40){
gameOver = false;
instDrawn = false;
counter = -1;
startSnake();
}
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
startSnake();
This is my first post so I hope that I put everything correctly down below here! :-P
I have a problem. Currently I'm making a snake game with a school friend of mine. We are making a snake game by using node.js so we can create a multiplayer snake game. Nothing really extreme just the basic snake game but then with more players.
Currently I've created a code that can move the snake and also will place food randomly on the canvas (I'm using the HTML5 Canvas element in which the game is played).
Now I'm stuck because I want to create a function that allows the snake to eat the food and then grow longer. As far as I know I have the function as it should be, but for some reason it does not work. My knowledge of javascript is very basic so what I'm doing here is all new for me. I will put the entire code down below so you can see it through.
I've created 2 javascript files. one that has the snake code in it and the other has the food code in it. The function that I'm referring about is inside the Snake script under Snake.prototype.move
I really hope that someone can help me out so I can proceed with our game.
This is the main code (Snake code):
var game;
$(document).ready(function(){
var canvas = $("#canvas")[0];
var ctx = canvas.getContext("2d");
var w = $("#canvas").width();
var h = $("#canvas").height();
var cw = 10;
ctx.fillStyle = "white";
ctx.fillRect(0, 0, w, h);
ctx.strokeStyle = "black";
ctx.strokeRect(0, 0, w, h);
var GameObject = function() {
this.snakes = [];
this.foods = [];
}
game = new GameObject();
var snake = new Snake(1, 15, 'testnaam');
snake.create();
game.snakes.push(snake);
game.foods.push(new Food(w, cw));
function loop() {
window.setTimeout(loop, 60);
ctx.clearRect(0, 0, w, h);
if(game.snakes.lenght !== 0) {
for(i = 0; i < game.snakes.length; i++) {
var s = game.snakes[i];
s.paint(ctx, game);
}
} else {
}
if(game.foods.length !== 0) {
for(var i = 0; i < game.foods.length; i++) {
var f = game.foods[i];
f.paint(ctx);
}
} else {
}
}
loop();
document.addEventListener('keydown', function(e) {
e.preventDefault();
var key = e.which;
if(key == "37" && snake.direction !="right") snake.direction = "left";
else if(key == "38" && snake.direction !="down") snake.direction = "up";
else if(key == "39" && snake.direction !="left") snake.direction = "right";
else if(key == "40" && snake.direction !="up") snake.direction = "down";
}, false);
});
var Snake = function(player, length, alias){
this.length = length;
this.pieces = [];
this.player = player;
this.position = {x: 0, y: 0};
this.direction = "right";
this.color = this.color();
this.getName = alias;
}
Snake.prototype.create = function(){
for(var i = this.length -1; i >= 0; i--) {
this.pieces.push({x: i, y: 0});
}
};
Snake.prototype.paint = function(ctx, game){
this.move(game);
for(var i = 0; i < this.pieces.length; i++){
var c = this.pieces[i];
ctx.fillStyle = this.color;
ctx.fillRect(c.x*10, c.y*10, 10, 10);
}
};
Snake.prototype.color = function(){
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
};
Snake.prototype.getName = function() {
return this.alias;
}
Snake.prototype.getPosition = function() {
return {x: this.x, y: this.y }
}
Snake.prototype.move = function(game) {
var nx = this.pieces[0].x;
var ny = this.pieces[0].y;
if(this.direction == "right")nx++;
else if(this.direction == "left")nx--;
else if(this.direction == "up")ny--;
else if(this.direction == "down")ny++;
if(Snake == game.foods[0].position.x && Snake == game.foods[0].position.y){
console.log("raak");
var tail = {
x: nx,
y: ny
};
Food.create();
} else{
var tail = this.pieces.pop();
tail.x = nx;
tail.y = ny;
}
this.pieces.unshift(tail);
};
Snake.prototype.collision = function(x, y, array){
for(var i = 0; i < array.length; i++){
if(array[i].x == x && array[i].y == y)
return true;
}
return false;
};
And This is the code for the food
var Food = function(w, cw){
this.w = w;
this.cw = cw;
this.position = this.create();
console.log(this.position);
};
Food.prototype.create = function(){
var min = 0;
var max = (this.w/this.cw);
return position = {
x: Math.round(min + Math.random()* (Math.abs(min)+(max)))*this.cw,
y: Math.round(min + Math.random()* (Math.abs(min)+(max)))*this.cw
}
};
Food.prototype.paint = function(ctx){
ctx.fillStyle = "#000";
ctx.fillRect(this.position.x,this.position.y,10,10)
};
Thank you very much!
Live demo
I had to fiddle with it a lot.. there is a lot of weirdness going on in the code, but this is the area I messed with primarily to get it working.
Snake.prototype.move = function (game) {
var nx = this.pieces[0].x;
var ny = this.pieces[0].y;
if (this.direction == "right") nx++;
else if (this.direction == "left") nx--;
else if (this.direction == "up") ny--;
else if (this.direction == "down") ny++;
/*
* you werent testing the front pieces x and y, also since your multiplying the snake
* pieces by 10, you need to divide the food positions by 10 for the coords to match up
*/
if (this.pieces[0].x == game.foods[0].position.x / 10 && this.pieces[0].y == game.foods[0].position.y / 10) {
console.log("raak");
var tail = {
x: nx,
y: ny
};
// push your piece
this.pieces.push(tail);
// you have an array for prob to eventually have more than one on the screen.
// for now i set food[0] to be a new piece of food. We dont have ref's to w and cw in this
// func to I passed in the values.
game.foods[0] = new Food(canvas.width, 10);
} else {
var tail = this.pieces.pop();
tail.x = nx;
tail.y = ny;
// only unshift when we havent added a piece
this.pieces.unshift(tail);
}
};
Basically you weren't testing the positions at all and you werent dividing the foods position by 10 when checking so the snake's position could never match the foods.