I found this platform game on the Internet and I modified it a bit:
<canvas id="canvas" widht=1000 height=400></canvas>
<script>
(function () {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
width = 1000,
height = 400,
player = {
x: width / 2,
y: height - 15,
width: 5,
height: 5,
speed: 3,
velX: 0,
velY: 0,
jumping: false,
grounded: false
},
keys = [],
friction = 0.8,
gravity = 0.3;
var boxes = [];
// dimensions
a = Math.floor((Math.random() * 20) + 1);
for (i = 0; i < a; i++) {
random1 = Math.floor((Math.random() * 1000) + 1);
random2 = Math.floor((Math.random() * 400) + 1);
random3 = Math.floor((Math.random() * 200) + 1);
random4 = Math.floor((Math.random() * 200) + 1);
boxes.push({
x: random1,
y: random2,
width: random3,
height: random4
}
boxes.push({
x: 0,
y: 0,
width: 10,
height: height
});
boxes.push({
x: 0,
y: height - 2,
width: width,
height: 50
});
boxes.push({
x: width - 10,
y: 0,
width: 50,
height: height
});
canvas.width = width;
canvas.height = height;
function update() {
// check keys
if (keys[38] || keys[32]) {
// up arrow or space
if (!player.jumping && player.grounded) {
player.jumping = true;
player.grounded = false;
player.velY = -player.speed * 2;
}
}
if (keys[39]) {
// right arrow
if (player.velX < player.speed) {
player.velX++;
}
}
if (keys[37]) {
// left arrow
if (player.velX > -player.speed) {
player.velX--;
}
}
player.velX *= friction;
player.velY += gravity;
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = "black";
ctx.beginPath();
player.grounded = false;
for (var i = 0; i < boxes.length; i++) {
ctx.rect(boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);
var dir = colCheck(player, boxes[i]);
if (dir === "l" || dir === "r") {
player.velX = 0;
player.jumping = false;
} else if (dir === "b") {
player.grounded = true;
player.jumping = false;
} else if (dir === "t") {
player.velY *= -1;
}
}
if(player.grounded){
player.velY = 0;
}
player.x += player.velX;
player.y += player.velY;
ctx.fill();
ctx.fillStyle = "red";
ctx.fillRect(player.x, player.y, player.width, player.height);
requestAnimationFrame(update);
}
function colCheck(shapeA, shapeB) {
// get the vectors to check against
var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
// add the half widths and half heights of the objects
hWidths = (shapeA.width / 2) + (shapeB.width / 2),
hHeights = (shapeA.height / 2) + (shapeB.height / 2),
colDir = null;
// if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {
// figures out on which side we are colliding (top, bottom, left, or right)
var oX = hWidths - Math.abs(vX),
oY = hHeights - Math.abs(vY);
if (oX >= oY) {
if (vY > 0) {
colDir = "t";
shapeA.y += oY;
} else {
colDir = "b";
shapeA.y -= oY;
}
} else {
if (vX > 0) {
colDir = "l";
shapeA.x += oX;
} else {
colDir = "r";
shapeA.x -= oX;
}
}
}
return colDir;
}
document.body.addEventListener("keydown", function (e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function (e) {
keys[e.keyCode] = false;
});
window.addEventListener("load", function () {
update();
});
</script>
The problem is in the for loop when I want to create multiple boxes with random width, height, position but that didn't work. How could I do that?
In you code there are two syntax error. first one is you didn't close for loop and second one is inside for loop first push operation was not close properly.
i have update code.
(function () {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
width = 1000,
height = 400,
player = {
x: width / 2,
y: height - 15,
width: 5,
height: 5,
speed: 3,
velX: 0,
velY: 0,
jumping: false,
grounded: false
},
keys = [],
friction = 0.8,
gravity = 0.3;
var boxes = [];
// dimensions
a = Math.floor((Math.random() * 20) + 1);
for (i = 0; i < a; i++) {
random1 = Math.floor((Math.random() * 1000) + 1);
random2 = Math.floor((Math.random() * 400) + 1);
random3 = Math.floor((Math.random() * 200) + 1);
random4 = Math.floor((Math.random() * 200) + 1);
boxes.push({
x: random1,
y: random2,
width: random3,
height: random4
});
boxes.push({
x: 0,
y: 0,
width: 10,
height: height
});
boxes.push({
x: 0,
y: height - 2,
width: width,
height: 50
});
boxes.push({
x: width - 10,
y: 0,
width: 50,
height: height
});
canvas.width = width;
canvas.height = height;
}
function update() {
// check keys
if (keys[38] || keys[32]) {
// up arrow or space
if (!player.jumping && player.grounded) {
player.jumping = true;
player.grounded = false;
player.velY = -player.speed * 2;
}
}
if (keys[39]) {
// right arrow
if (player.velX < player.speed) {
player.velX++;
}
}
if (keys[37]) {
// left arrow
if (player.velX > -player.speed) {
player.velX--;
}
}
player.velX *= friction;
player.velY += gravity;
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = "black";
ctx.beginPath();
player.grounded = false;
for (var i = 0; i < boxes.length; i++) {
ctx.rect(boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);
var dir = colCheck(player, boxes[i]);
if (dir === "l" || dir === "r") {
player.velX = 0;
player.jumping = false;
} else if (dir === "b") {
player.grounded = true;
player.jumping = false;
} else if (dir === "t") {
player.velY *= -1;
}
}
if(player.grounded){
player.velY = 0;
}
player.x += player.velX;
player.y += player.velY;
ctx.fill();
ctx.fillStyle = "red";
ctx.fillRect(player.x, player.y, player.width, player.height);
requestAnimationFrame(update);
}
function colCheck(shapeA, shapeB) {
// get the vectors to check against
var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
// add the half widths and half heights of the objects
hWidths = (shapeA.width / 2) + (shapeB.width / 2),
hHeights = (shapeA.height / 2) + (shapeB.height / 2),
colDir = null;
// if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {
// figures out on which side we are colliding (top, bottom, left, or right)
var oX = hWidths - Math.abs(vX),
oY = hHeights - Math.abs(vY);
if (oX >= oY) {
if (vY > 0) {
colDir = "t";
shapeA.y += oY;
} else {
colDir = "b";
shapeA.y -= oY;
}
} else {
if (vX > 0) {
colDir = "l";
shapeA.x += oX;
} else {
colDir = "r";
shapeA.x -= oX;
}
}
}
return colDir;
}
document.body.addEventListener("keydown", function (e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function (e) {
keys[e.keyCode] = false;
});
window.addEventListener("load", function () {
update();
});
<canvas id="canvas" widht=1000 height=400></canvas>
Related
I've been making a simple game just with the HTML5 canvas and plain JavaScript. Most recently I tried adding a feature to shoot bullets which would then destroy obstacles but I've come upon a problem. Whenever you shoot a bullet it doesn't move until another is shot. Even when it starts moving and collides with one of the obstacles nothing happens. I've done some troubleshooting and I can't seem to get to the bottom of it. Any help and/or suggestions would be greatly appreciated.
Collision handling code:
for(var i = 0; i < this.bullets.length - 1; i++) { // -1 is present because whenever I remove it I get an error. I have a feeling this may be related to the order of how everything updates, will be fixed
this.bullets[i].x += this.bullets[i].speed;
if(this.bullets[i].x > cvs.width) {
this.bullets.splice(i, 1);
}
for(var j = 0; j < obstacles.length - 1; j++) { // Same here
if(rectanglesColliding(this.bullets[i], obstacles[j])) {
console.log("Collision");
}
}
}
Full player object:
var player = {
score: 0,
x: 50,
y: 150,
radius: 10,
jumping: false,
bullets: [],
velocityX: 0,
velocityY: 1,
angle: 90,
update: function() {
this.draw();
this.score++;
if(this.y + this.radius + 2 > cvs.height - 50 && this.jumping === false || this.y - this.radius + 2 < 0 + 50 && this.jumping === true) {
this.velocityY = 0;
} else if(this.jumping === false){
this.velocityY = 4;
} else {
this.velocityY = -4;
}
obstacles.forEach((obstacle) => {
if(colliding(this, obstacle)) {
gameEnded = true;
}
});
this.x += this.velocityX;
this.y += this.velocityY;
for(var i = 0; i < this.bullets.length - 1; i++) { // -1 is present because whenever I remove it I get an error. I have a feeling this may be related to the order of how everything updates, will be fixed
this.bullets[i].x += this.bullets[i].speed;
if(this.bullets[i].x > cvs.width) {
this.bullets.splice(i, 1);
}
for(var j = 0; j < obstacles.length - 1; j++) { // Same here
if(rectanglesColliding(this.bullets[i], obstacles[j])) {
console.log("Collision");
}
}
}
},
draw: function() {
this.bullets.forEach((bullet) => {
ctx.fillStyle = 'green';
ctx.fillRect(bullet.x, bullet.y, 7, 2);
});
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
ctx.fill();
}
};
Collision Detection Function:
function rectanglesColliding(rect1, rect2) {
if(rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x && // Found on Mozilla.com: https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
rect1.y < rect2.y + rect2.height &&
rect1.y + rect1.height > rect2.y) return true;
else return false;
}
Shoot Function:
function shoot() {
player.bullets.push({ x: player.x + 10, y: player.y, speed: 6 });
}
Object of the game:
Survive as long as you can by avoiding the obstacles.
Controls:
Space: Go up
W: Shoot Bullet
Full code snippet:
var cvs = document.getElementById('canvas');
var ctx = cvs.getContext("2d");
var gameEnded = false;
var player = {
score: 0,
x: 50,
y: 150,
radius: 10,
jumping: false,
bullets: [],
velocityX: 0,
velocityY: 1,
angle: 90,
update: function() {
this.draw();
this.score++;
if(this.y + this.radius + 2 > cvs.height - 50 && this.jumping === false || this.y - this.radius + 2 < 0 + 50 && this.jumping === true) {
this.velocityY = 0;
} else if(this.jumping === false){
this.velocityY = 4;
} else {
this.velocityY = -4;
}
obstacles.forEach((obstacle) => {
if(colliding(this, obstacle)) {
gameEnded = true;
}
});
this.x += this.velocityX;
this.y += this.velocityY;
for(var i = 0; i < this.bullets.length - 1; i++) {
this.bullets[i].x += this.bullets[i].speed;
if(this.bullets[i].x > cvs.width) {
this.bullets.splice(i, 1);
}
for(var j = 0; j < obstacles.length - 1; j++) {
if(rectanglesColliding(this.bullets[i], obstacles[j])) {
console.log("Collision");
// obstacles.splice(i, 1);
}
}
}
},
draw: function() {
this.bullets.forEach((bullet) => {
ctx.fillStyle = 'green';
ctx.fillRect(bullet.x, bullet.y, 7, 2);
});
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
ctx.fill();
}
};
var obstacles = [{ x: 150, y: 60, width: 10, height: 20 }];
document.addEventListener('keydown', (event) => {
if(event.key === ' ') {
player.jumping = true;
}
if(event.key === 'w') {
shoot();
}
});
document.addEventListener('keyup', (event) => {
if(event.key === ' ') {
player.jumping = false;
}
});
function randomIntFromRange(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function getWidth() {
return Math.max(
document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth
);
}
function getHeight() {
return Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.documentElement.clientHeight
);
}
function colliding(circle, rect) {
var distX = Math.abs(circle.x - rect.x - rect.width / 2);
var distY = Math.abs(circle.y - rect.y - rect.height / 2);
if(distX > (rect.width / 2 + circle.radius)) return false;
if(distY > (rect.height / 2 + circle.radius)) return false;
if(distX <= (rect.width / 2)) return true;
if(distY <= (rect.height / 2)) return true;
}
function rectanglesColliding(rect1, rect2) {
if(rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x &&
rect1.y < rect2.y + rect2.height &&
rect1.y + rect1.height > rect2.y) {
return true;
}
}
function distance(x1, y1, x2, y2) {
const xDist = x2 - x1;
const yDist = y2 - y1;
return Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
}
function shoot() {
player.bullets.push({ x: player.x + 10, y: player.y, speed: 6 });
}
function generateObstacle() {
var obstacle = {
x: obstacles[0].x + randomIntFromRange(cvs.width - 100, cvs.width + 70),
y: 0 + randomIntFromRange(20, 550),
width: randomIntFromRange(25, 35),
height: randomIntFromRange(10, 25)
};
for(var i = 0; i < obstacles.length; i++) {
if(distance(obstacle.x, obstacle.y, obstacles[i].x, obstacles[i].y) < 65) {
obstacle = {
x: obstacles[0].x + randomIntFromRange(cvs.width - 100, cvs.width + 70),
y: 0 + randomIntFromRange(20, 550),
width: randomIntFromRange(25, 35),
height: randomIntFromRange(10, 25)
};
i = -1;
}
}
obstacles.push({ x: obstacle.x, y: obstacle.y, width: obstacle.width, height: obstacle.height });
}
function removeBadObstacles() {
for(var i = 0; i < obstacles.length; i++) {
if(obstacles[i].x < 0) {
obstacles.splice(i, 1);
}
}
}
function updateObstacles() {
if(obstacles[obstacles.length - 1].x < cvs.width + 5) {
generateObstacle();
generateObstacle();
}
obstacles.forEach((obstacle) => {
obstacle.x -= 10;
ctx.fillStyle = 'red';
ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
});
}
function init() {
cvs.width = getWidth();
cvs.height = getHeight();
update();
}
function update() {
if(gameEnded) {
ctx.font = '50px Verdana';
return ctx.fillText('Game Over', 110, cvs.height / 2);
}
requestAnimationFrame(update);
removeBadObstacles();
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, cvs.width, cvs.height);
updateObstacles();
player.update();
ctx.font = '30px Impact';
ctx.fillText("Score: " + player.score, 20, 40);
}
init();
<!DOCTYPE html>
<html>
<head>
<title>Game</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript" src="./JS/main.js"></script>
</body>
</html>
when iterate through a array, the last item is at length-1 (which mean you should use < length, not < length-1)
the remove code should be obstacles.splice(j, 1); (i is the index for bullet)
you do not assign size to bullet (and you may also want to use this size when draw)
var cvs = document.getElementById('canvas');
var ctx = cvs.getContext("2d");
var gameEnded = false;
var player = {
score: 0,
x: 50,
y: 150,
radius: 10,
jumping: false,
bullets: [],
velocityX: 0,
velocityY: 1,
angle: 90,
update: function() {
this.draw();
this.score++;
if(this.y + this.radius + 2 > cvs.height - 50 && this.jumping === false || this.y - this.radius + 2 < 0 + 50 && this.jumping === true) {
this.velocityY = 0;
} else if(this.jumping === false){
this.velocityY = 4;
} else {
this.velocityY = -4;
}
obstacles.forEach((obstacle) => {
if(colliding(this, obstacle)) {
gameEnded = true;
}
});
this.x += this.velocityX;
this.y += this.velocityY;
for(var i = 0; i < this.bullets.length; i++) {//<==============
this.bullets[i].x += this.bullets[i].speed;
if(this.bullets[i].x > cvs.width) {
this.bullets.splice(i, 1);
}
for(var j = 0; j < obstacles.length; j++) {//<==============
if(rectanglesColliding(this.bullets[i], obstacles[j])) {
console.log("Collision");
obstacles.splice(j, 1);//<==============
}
}
}
},
draw: function() {
this.bullets.forEach((bullet) => {
ctx.fillStyle = 'green';
ctx.fillRect(bullet.x, bullet.y, 7, 2);
});
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
ctx.fill();
}
};
var obstacles = [{ x: 150, y: 60, width: 10, height: 20 }];
document.addEventListener('keydown', (event) => {
if(event.key === ' ') {
player.jumping = true;
}
if(event.key === 'w') {
shoot();
}
});
document.addEventListener('keyup', (event) => {
if(event.key === ' ') {
player.jumping = false;
}
});
function randomIntFromRange(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function getWidth() {
return Math.max(
document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth
);
}
function getHeight() {
return Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.documentElement.clientHeight
);
}
function colliding(circle, rect) {
var distX = Math.abs(circle.x - rect.x - rect.width / 2);
var distY = Math.abs(circle.y - rect.y - rect.height / 2);
if(distX > (rect.width / 2 + circle.radius)) return false;
if(distY > (rect.height / 2 + circle.radius)) return false;
if(distX <= (rect.width / 2)) return true;
if(distY <= (rect.height / 2)) return true;
}
function rectanglesColliding(rect1, rect2) {
if(rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x &&
rect1.y < rect2.y + rect2.height &&
rect1.y + rect1.height > rect2.y) {
return true;
}
}
function distance(x1, y1, x2, y2) {
const xDist = x2 - x1;
const yDist = y2 - y1;
return Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
}
function shoot() {
player.bullets.push({ x: player.x + 10, y: player.y, speed: 6, width: 7, height: 6 }); //<====================
}
function generateObstacle() {
var obstacle = {
x: obstacles[0].x + randomIntFromRange(cvs.width - 100, cvs.width + 70),
y: 0 + randomIntFromRange(20, 550),
width: randomIntFromRange(25, 35),
height: randomIntFromRange(10, 25)
};
for(var i = 0; i < obstacles.length; i++) {
if(distance(obstacle.x, obstacle.y, obstacles[i].x, obstacles[i].y) < 65) {
obstacle = {
x: obstacles[0].x + randomIntFromRange(cvs.width - 100, cvs.width + 70),
y: 0 + randomIntFromRange(20, 550),
width: randomIntFromRange(25, 35),
height: randomIntFromRange(10, 25)
};
i = -1;
}
}
obstacles.push({ x: obstacle.x, y: obstacle.y, width: obstacle.width, height: obstacle.height });
}
function removeBadObstacles() {
for(var i = 0; i < obstacles.length; i++) {
if(obstacles[i].x < 0) {
obstacles.splice(i, 1);
}
}
}
function updateObstacles() {
if(obstacles[obstacles.length - 1].x < cvs.width + 5) {
generateObstacle();
generateObstacle();
}
obstacles.forEach((obstacle) => {
obstacle.x -= 10;
ctx.fillStyle = 'red';
ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
});
}
function init() {
cvs.width = getWidth();
cvs.height = getHeight();
update();
}
function update() {
if(gameEnded) {
ctx.font = '50px Verdana';
return ctx.fillText('Game Over', 110, cvs.height / 2);
}
requestAnimationFrame(update);
removeBadObstacles();
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, cvs.width, cvs.height);
updateObstacles();
player.update();
ctx.font = '30px Impact';
ctx.fillText("Score: " + player.score, 20, 40);
}
init();
<!DOCTYPE html>
<html>
<head>
<title>Game</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript" src="./JS/main.js"></script>
</body>
</html>
It's been few days that I've been learning JavaScript. So I'm completely new to this.
This is my code for snake game and it isn't complete yet but I've run into a problem. I'm not completely sure that if it's a logical error or not.
After eating the food several times, the game crashes with
TypeError: snakeBody[l] is undefined.
Screenshot of the error is here.
The entire code is given below:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
canvas {
background: #080d16;
border: 5px solid green;
padding: 0;
}
</style>
</head>
<body>
<canvas id="mycan" class="mycan" width="1860" height="920"></canvas>
<script>
var canvas = document.getElementById('mycan');
var ctx = canvas.getContext('2d');
var snakeSize = 20;
var snakeX = 100;
var snakeY = 100;
var foodX = 310;
var foodY = 310;
var foodSize = 10;
var dx = 20;
var dy = 20;
var leftPressed = false;
var rightPressed = true;
var topPressed = false;
var bottomPressed = false;
var snakeBody = [{x:snakeX,y:snakeY},{x:snakeX-20,y:snakeY}];
var z = 0;
//keypress event listner
document.addEventListener('keypress', keyHandler, false);
//keypress event handler function
function keyHandler(e) {
if (e.keyCode == 37) {
leftPressed = true;
rightPressed = false;
topPressed = false;
bottomPressed = false;
} else if (e.keyCode == 38) {
leftPressed = false;
rightPressed = false;
topPressed = true;
bottomPressed = false;
} else if (e.keyCode == 39) {
leftPressed = false;
rightPressed = true;
topPressed = false;
bottomPressed = false;
} else if (e.keyCode == 40) {
leftPressed = false;
rightPressed = false;
topPressed = false;
bottomPressed = true;
}
}
//draw food
function food() {
ctx.beginPath();
ctx.arc(foodX, foodY, foodSize, 0, Math.PI * 2);
ctx.fillStyle = "pink";
ctx.fill();
ctx.closePath();
}
//draw snake
function snake() {
for (var l = 0; l < snakeBody.length; l++) {
ctx.beginPath();
ctx.rect(snakeBody[l].x, snakeBody[l].y, snakeSize, snakeSize);
if (l == 0) {
ctx.fillStyle = "lightblue";
} else {
ctx.fillStyle = 'grey';
}
ctx.fill();
ctx.closePath();
}
console.log(l);
var head = {
x: snakeX,
y: snakeY
};
snakeBody.pop();
snakeBody.unshift(head);
}
function tail() {
if ((snakeX + dx / 2 > foodX - foodSize && snakeX + dx / 2 < foodX + foodSize) && (snakeY + dy / 2 > foodY - foodSize && snakeY + dy / 2 < foodY + foodSize)) {
foodX = (Math.floor(Math.random() * 88) + 1) * 20 + 10;
foodY = (Math.floor(Math.random() * 45) + 1) * 20 + 10;
z++;
if (snakeBody[snakeBody.length - 1].x == snakeBody[snakeBody.length - 2].x && snakeBody[0].y < snakeBody[1].y) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x,
y: snakeBody[snakeBody.length - 1].y + 20
};
} else if (snakeBody[snakeBody.length - 1].x == snakeBody[snakeBody.length - 2].x && snakeBody[0].y > snakeBody[1].y) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x,
y: snakeBody[snakeBody.length - 1].y - 20
};
} else if (snakeBody[snakeBody.length - 1].y == snakeBody[snakeBody.length - 2].y && snakeBody[0].x > snakeBody[1].x) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x - 20,
y: snakeBody[snakeBody.length - 1].y
};
} else if (snakeBody[snakeBody.length - 1].y == snakeBody[snakeBody.length - 2].y && snakeBody[0].x < snakeBody[1].x) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x + 20,
y: snakeBody[snakeBody.length - 1].y
};
}
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
snake();
food();
tail();
if (rightPressed && snakeX + dx < canvas.width) {
snakeX += dx;
} else if (leftPressed && snakeX > 0) {
snakeX += -dx;
} else if (topPressed && snakeY > 0) {
snakeY += -dy;
} else if (bottomPressed && snakeY + dy < canvas.height) {
snakeY += dy;
}
}
setInterval(draw, 80);
</script>
</body>
</html>
You have error in algorithm - your snakeBody put/pops elements and you miss some "corner cases" when use indexes in this array - the problem is not with JS but with algorithm - debug it and also use "triangle" in chrome konsole on left side of error to see more details (stacktrace)
I check and run your code more than once. This error does not appear for me. It is good for you to check the values in snake function and then use them. Modify your snake function to this
function snake() {
for (var l = 0; l < snakeBody.length; l++) {
ctx.beginPath();
if(snakeBody && snakeBody[l] && snakeBody[l].hasOwnProperty('x') && snakeBody[l].hasOwnProperty('y')) {
ctx.rect(snakeBody[l].x, snakeBody[l].y, snakeSize, snakeSize);
}
if (l == 0) {
ctx.fillStyle = "lightblue";
} else {
ctx.fillStyle = 'grey';
}
ctx.fill();
ctx.closePath();
}
console.log(l);
var head = {
x: snakeX,
y: snakeY
};
snakeBody.pop();
snakeBody.unshift(head);
}
As you can see, snakeBody has no indexes 24 and 25. But this condition satisfy this.
I'm making a html5 canvas game and I have a problem with the collision.
The problem is when the ball collides with any platform, the ball gravity should be -1 and go up as the same velocity as the platforms but it only works with the last platform and the left one. How can I fix it? Thanks!
HTML:
<html>
<head>
<title>Falldown</title>
</head>
<body>
<canvas id="canvas" width = "380" height= "640"></canvas>
<script src="beta.js"></script>
</body>
</html>
JS Code:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var isMenu = true;
var isPlaying = false;
var testing = true;
var pressingLeft = false;
var pressingRight = false;
var Platforms = [];
var difficulty = 1;
var gravity = 1;
var Player = {
color: "red",
radius: 7.5,
stepY: 1.5,
x: 175,
y: 75
};
function RectCircleColliding(circle, rect) {
var distX = Math.abs(circle.x - rect.x - rect.width / 2);
var distY = Math.abs(circle.y - rect.y - 20 / 2);
if (distX > (rect.width / 2 + circle.radius)) return false;
if (distY > (20 / 2 + circle.radius)) return false;
if (distX <= (rect.width / 2)) return true;
if (distY <= (20 / 2)) return true;
var dx = distX - rect.width / 2;
var dy = distY - 20 / 2;
return (dx * dx + dy * dy <= (circle.radius * circle.radius));
}
function drawBackground() {
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (isMenu && !isPlaying) {
createText("60px monospace", "white", "FallDown", 45, 130);
createText("34px Arial", "white", "PLAY", 130, 260);
createText("34px Arial", "white", "LEADERBOARD", 50, 340);
createText("34px Arial", "white", "SETTINGS", 90, 420);
} else {
if (testing) {
Platforms = [];
for (var i = 0; i < 13; i++) {
Platforms.push({
"x": 10,
"y": 160 + (i * 70),
"width": (Math.random() * canvas.width) - 60
});
}
testing = false;
}
for (var i in Platforms) {
ctx.fillStyle = "#00ffff";
ctx.fillRect(10, Platforms[i].y, Platforms[i].width, 20);
var totalTest = Platforms[i].width + 60;
ctx.fillRect(totalTest + 30, Platforms[i].y, canvas.width - totalTest, 20);
Platforms[i].y -= 1;
if (RectCircleColliding(Player, Platforms[i])) {
gravity = -1;
} else {
gravity = 1;
}
}
detectBorderCollision();
detectPlayerCollision();
drawPlayer();
drawBorder();
if (Platforms.length === 7) Platforms = [];
}
}
function detectBorderCollision() {
if (Player.x > 370 - Player.radius) {
Player.x = 370 - Player.radius;
} else if (Player.x < 3.8 + Player.radius * 2) {
Player.x = 3.8 + Player.radius * 2
}
}
function detectPlayerCollision() {
}
function drawPlayer() {
ctx.beginPath();
ctx.fillStyle = Player.color;
ctx.arc(Player.x, Player.y, Player.radius, 0, 2 * Math.PI);
ctx.fill();
ctx.closePath();
Player.y += gravity;
if (pressingRight) {
Player.x += 2;
} else if (pressingLeft) {
Player.x -= 2;
}
/*
ctx.fillStyle = "#00ffff";
ctx.fillRect(10, 160, 300, 20);
*/
}
function drawBorder() {
ctx.beginPath();
ctx.strokeStyle = "#00ffff";
ctx.lineWidth = 10;
ctx.moveTo(5, 0);
ctx.lineTo(5, 640);
ctx.moveTo(375, 0);
ctx.lineTo(375, 640);
ctx.stroke();
ctx.closePath();
}
function createText(font, color, value, posX, posY) {
ctx.font = font;
ctx.fillStyle = color;
ctx.fillText(value, posX, posY)
}
function isInside(realX, realY, x1, x2, y1, y2) {
return (realX > x1 && realX < x2) && (realY > y1 && realY < y2)
}
function drawGame() {
drawBackground();
}
function startDrawing() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawGame();
requestAnimationFrame(startDrawing);
}
function Init() {
requestAnimationFrame(startDrawing);
canvas.addEventListener("click", function(evt) {
var rect = canvas.getBoundingClientRect();
var mouseX = evt.clientX - rect.left;
var mouseY = evt.clientY - rect.top;
if (isMenu && !isPlaying) {
if (isInside(mouseX, mouseY, 115, 230, 220, 270)) {
isPlaying = true;
isMenu = false;
} else if (isInside(mouseX, mouseY, 35, 320, 300, 345)) {
console.log("Leaderboard");
} else if (isInside(mouseX, mouseY, 75, 270, 380, 430)) {
console.log("Settings");
}
}
});
window.addEventListener("keydown", function(evt) {
if (!isMenu && isPlaying) {
if (evt.keyCode === 39) { // right
pressingRight = true;
} else if (evt.keyCode === 37) { // left
pressingLeft = true;
}
}
});
window.addEventListener("keyup", function(evt) {
if (!isMenu && isPlaying) {
if (evt.keyCode === 39) { // right
pressingRight = false;
} else if (evt.keyCode === 37) { // left
pressingLeft = false;
}
}
});
}
Init();
There are so many magic numbers in your code that debugging it is difficult and tedious. Replace all the number literals with identifiers which describe what the values represent.
The following amendment to part of the drawBackground function causes all the collisions with left hand platforms to work, but not perfectly.
var hasCollided;
for (var i in Platforms) {
ctx.fillStyle = "#00ffff";
ctx.fillRect(10, Platforms[i].y, Platforms[i].width, 20);
var totalTest = Platforms[i].width + 60;
ctx.fillRect(totalTest + 30, Platforms[i].y, canvas.width - totalTest, 20);
Platforms[i].y -= 1;
if (!hasCollided) {
if (RectCircleColliding(Player, Platforms[i])) {
gravity = -1;
hasCollided = true;
} else {
gravity = 1;
}
}
}
So i have my code here:
var canvas = document.getElementById('c');
var ctx = c.getContext('2d');
var player = {
x: 0,
y: 0,
width: 20,
height: 20,
speed: 3,
velX: 0,
velY: 0,
jumping: false,
grounded: false,
gravity: 0.35,
friction: 0,
glitchCooldown: 0,
keys: []
};
var walls = [];
walls.push({
x: 50,
y: 230,
width: 20,
height: 20
})
walls.push({
x: 150,
y: 230,
width: 20,
height: 20
})
player.y = canvas.height - player.width;
document.body.addEventListener("keydown", function(e) {
player.keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
player.keys[e.keyCode] = false;
});
function update() {
if (player.keys[68]) {
if (player.velX < player.speed) {
player.velX++;
}
};
if (player.keys[65]) {
if (player.velX > -player.speed) {
player.velX--;
}
};
if (player.keys[87]) {
if (!player.jumping) {
player.jumping = true;
player.grounded = false;
player.velY = -player.speed*2;
}
};
if (player.keys[74]) {
glitch('backward');
};
if (player.keys[75]) {
glitch('down')
};
if (player.keys[76]) {
glitch('forward')
};
player.velY += player.gravity;
player.velX *= player.friction;
player.x += player.velX;
player.y += player.velY;
ctx.clearRect(0, 0, canvas.width, canvas.height);
player.grounded = false;
for (var i = 0; i < walls.length; i++) {
rect('black', walls[i].x, walls[i].y, walls[i].width, walls[i].height);
var dir = colCheck(player, walls[i]);
if (dir === "l" || dir === "r") {
player.velX = 0;
player.jumping = false;
} else if (dir === "b") {
player.grounded = true;
player.jumping = false;
} else if (dir === "t") {
player.velY *= -1;
}
}
if (player.grounded){
player.velY = 0;
}
if (player.glitchCooldown <= 0) {
player.glitchCooldown = 0;
}
player.glitchCooldown--;
rect('black', player.x, player.y, player.width, player.height);
requestAnimationFrame(update);
};
requestAnimationFrame(update)
function rect(color, x, y, width, height) {
ctx.fillStyle = color;
ctx.fillRect(x, y, width, height);
}
function glitch(x) {
if (player.glitchCooldown <= 0) {
setTimeout(function(){player.width = 0}, 200);
setTimeout(function(){player.width = 20}, 220);
setTimeout(function(){player.width = 0}, 400);
setTimeout(function(){player.width = 20}, 420);
setTimeout(function(){player.width = 0}, 500);
setTimeout(function(){player.width = 20}, 510);
setTimeout(function(){player.width = 0}, 530);
setTimeout(function(){player.width = 20}, 550);
if (x == 'forward'){setTimeout(function(){player.x += 20;}, 700)};
if (x == 'backward'){setTimeout(function(){player.x -= 20;}, 700)};
if (x == 'down'){setTimeout(function(){player.y += 20;}, 700)};
setTimeout(function(){player.glitchCooldown = 120}, 700);
}
}
function colCheck(shapeA, shapeB) {
// get the vectors to check against
var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
// add the half widths and half heights of the objects
hWidths = (shapeA.width / 2) + (shapeB.width / 2),
hHeights = (shapeA.height / 2) + (shapeB.height / 2),
colDir = 'l';
// if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) { // figures out on which side we are colliding (top, bottom, left, or right) var oX = hWidths - Math.abs(vX), oY = hHeights - Math.abs(vY); if (oX >= oY) {
if (vY > 0) {
colDir = "t";
shapeA.y += oY;
} else {
colDir = "b";
shapeA.y -= oY;
}
} else {
if (vX > 0) {
colDir = "l";
shapeA.x += oX;
} else {
colDir = "r";
shapeA.x -= oX;
}
}
}
return colDir;
}
function random() {
var x = Math.floor((Math.random() * 10) + 1);
return x;
}
<html>
<head>
<title>CoRRupTed</title>
<link rel="stylesheet" href="design.css">
</head>
<body>
<canvas height='250' width='1350' style='border: 1px solid black' id='c'>Your browser do not support the <canvas> tag. Please update your browser.</canvas>
<script src='main.js'></script>
</body>
</html>
As you can see, my colCheck function is not working properly. It suppose to return colDir as 'l', 'r', 'b' or 't'. Buut the error says "Illegal resturn statement", so I think that colCheck is returning colDir as null. Therefore, in my code, I already write var col = colCheck(player, walls[i]), but it is still not working properly. Any ideas?
This is because you are not consistently styling your code.
The error means you have mismatching opening and closing braces.
the line
if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) { // figures out on which side we are colliding (top, bottom, left, or right) var oX = hWidths - Math.abs(vX), oY = hHeights - Math.abs(vY); if (oX >= oY) {
should be. Comments within /* */ have been added by me.
/* DONT make comment run past right edge of screen put them in the line above */
// figures out on which side we are colliding (top, bottom, left, or right)
if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {
/* DONT use , to separate variable declarations */
const oX = hWidths - Math.abs(vX); /*Use consts for vars that don't change*/
const oY = hHeights - Math.abs(vY);
if (oX >= oY) {
As you can see there I've done some collisions in the middleish part...
That doesn't the console log !HIT! so it doesn't work. I want that boxes collide with player. I've read help everywhere tried their codes and no success. If you could fix it and maybe comment the parts you did with your name/nickname; Since this code is going for a Open-source-Game of mine. Everyone can edit it and stuff. The game currently has sounds a box that jumps and flies. And also if you could make it so that player could stay and stand on the boxes while you are at it :D.. for that you do
if(whateverthenameofyourcollisiondertectionthenis){
player.jumping = false,
player.VelY = 0
}
Or something like that I think...
I started with javascript few days ago so I dont know so much about it...
So my code goes like this:
(function() {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
width = 1600,
height = 900,
player = {
x : width/2,
y : height - 5,
width : 5,
height : 5,
speed: 5,
velX: 0,
velY: 0,
jumping: false,
nofly: true,
colission: false,
left: false,
right: false,
},
keys = [],
friction = 0.8,
gravity = 0.2;
var boxes = []
// dimensions
boxes.push({
x: Math.floor((Math.random() * 1400) + 1),
y: Math.floor((Math.random() * 895) + 1),
width: 200,
height: 5,
});
boxes.push({
x: Math.floor((Math.random() * 1400) + 1),
y: Math.floor((Math.random() * 895) + 1),
width: 200,
height: 5,
});
boxes.push({
x: Math.floor((Math.random() * 1400) + 1),
y: Math.floor((Math.random() * 895) + 1),
width: 200,
height: 5,
});
boxes.push({
x: Math.floor((Math.random() * 1400) + 1),
y: Math.floor((Math.random() * 895) + 1),
width: 200,
height: 5,
});
boxes.push({
x: Math.floor((Math.random() * 1400) + 1),
y: Math.floor((Math.random() * 895) + 1),
width: 200,
height: 5,
});
boxes.push({
x: Math.floor((Math.random() * 1400) + 1),
y: Math.floor((Math.random() * 895) + 1),
width: 200,
height: 5,
});
boxes.push({
x: Math.floor((Math.random() * 1400) + 1),
y: Math.floor((Math.random() * 895) + 1),
width: 200,
height: 5,
});
canvas.width = width;
canvas.height = height;
function update(){
// check keys
if (keys[38] || keys[32] || keys[87]) {
// up arrow or space or W
if(!player.jumping){
console.log("jump")
player.jumping = true;
player.velY = -player.speed*3;
document.getElementById('Jump').play();
}
}
if (keys[39] || keys[68]) {
// right arrow or D
if(!player.right){ player.left = false
if (player.velX < player.speed) {
player.velX++;
console.log("Right")
}
}
}
if (keys[37] || keys[65]) {
// left arrow
if(!player.left){ player.right = false
if (player.velX > -player.speed) {
player.velX--;
console.log("Left")
}
}
}
if (keys[40] || keys[83]) {
// down arrow or S
if(player.jumping){
player.velY++;
player.valX;
console.log("Down!")
}
}
if (keys[13]) {
// Enter
player.jumping = true
if(player.nofly){
console.log("Flap!")
player.velY = -player.speed*1;
document.getElementById('Flap').play();
player.nofly = false;
setTimeout(function(){player.nofly = true;},600);}
}
player.velX *= friction;
player.velY += gravity;
player.x += player.velX;
player.y += player.velY;
if (player.x >= width-player.width) {
player.right = true
console.log("Wall!")
player.x = width-player.width;
} else if (player.x <= 0) {
player.x = 0;
console.log("Wall!")
player.left = true
}
if(player.y >= height-player.height){
player.y = height - player.height;
player.jumping = false;
console.log("Ground!")
}
ctx.clearRect(0,0,width,height);
ctx.fillStyle = "white";
ctx.beginPath();
for (var i = 0; i < boxes.length; i++) {
ctx.rect(boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);
}
ctx.fill();
ctx.fillStyle = "GreenYellow";
ctx.fillRect(player.x, player.y, player.width, player.height);
//if(player.x = boxes[i].x - boxes[i].width &&
// player.y = boxes[i].y - boxes[i].height){player.velY = 0}
if (boxes.push.x < player.x + player.width &&
boxes.push.x + boxes.push.width > player.x &&
boxes.push.y < player.y + player.height &&
boxes.push.y + boxes.push.height > player.y)
{ player.colission = true; console.log("!HIT!")}
else { player.colission = false }
if (player.colission) { player.velY = 0, console.log("Ohnoes we must stop")}
requestAnimationFrame(update);
}
document.body.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
keys[e.keyCode] = false;
});
window.addEventListener("load",function(){
update();
});
function click(x,y){
if(keys[38]){
var ev = document.createEvent("MouseEvent");
var el = document.elementFromPoint(x,y);
ev.initMouseEvent(
"click",
true /* bubble */, true /* cancelable */,
window, null,
x, y, player.x, player.y, /* coordinates */
false, false, false, false, /* modifier keys */
0 /*left*/, null
);
el.dispatchEvent(ev);
}
}