Square gets stuck when it reaches the bottom of the canvas - javascript

I am trying to make a simple JavaScript based game, where the user would move the square around the canvas and dodge elements / squares coming towards it (however this is just a plan, I am far from that point at the moment).
The problem I am experiencing is that whenever I would make my canvas width value bigger than height, it would make the square get stuck after reaching the bottom of the page. There is probably an error / mistake in my code, however I could not seem to spot anything.
The code can be found here or below:
// This code was created in CodePen.io, so some parts of it might not make any sense,
// nor are they gonna be useful outside the CodePen platform. Those parts are however only commented.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// character data
var charPositionX = canvas.width / 2;
// Just for the snippet height
var charPositionY = 0;
//var deltaCharPositionX = 10;
//var deltaCharPositionY = 10;
//Removed the init() function, since the elements are loaded.
// start creating elements, first the game environment.
function draw() {
clear();
createRectangleToCoverCanvas();
createChar(charPositionX, charPositionY, 10);
}
function clear() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function createRectangleToCoverCanvas() {
ctx.fillStyle = '#ddd';
ctx.strokeStyle = '#ddd';
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fill();
ctx.stroke();
}
// now the character
function createChar(x, y, radius) {
ctx.fillStyle = 'white';
ctx.strokeStyle = 'white';
ctx.beginPath();
ctx.rect(x, y, 32, 32);
ctx.fill();
ctx.stroke();
}
var raf,
direction = {
x: 0,
y: 0
};
// set the speed variable for the character
var speed = 5;
function triggerMoveChar(event) {
switch (event.keyCode) {
// left
case 37:
// update the direction object
direction.x = -speed;
// avoid the scrolling
event.preventDefault();
break;
// up
case 38:
direction.y = -speed;
event.preventDefault();
break;
// right
case 39:
direction.x = speed;
event.preventDefault();
break;
//down
case 40:
direction.y = speed;
event.preventDefault();
break;
}
// if the animation haven't been initiated yet, and the direction is not 0, then do it now
if (!raf && (direction.x || direction.y)) moveChar();
}
function releaseMoveChar(event) {
switch (event.keyCode) {
// left
case 37:
//reset this direction
direction.x = 0;
break;
// up
case 38:
direction.y = 0;
break;
// right
case 39:
direction.x = 0;
break;
//down
case 40:
direction.y = 0;
break;
}
if (!direction.x && !direction.y) {
// if none of the directions is set, stop the animation
cancelAnimationFrame(raf);
raf = undefined;
}
}
function moveChar() {
// declare the animation function
var move = function() {
// update the positions without going out of the screen
if(direction.x){
if(
(charPositionX > 0 && charPositionX < canvas.width-32) ||
(charPositionX <= 0 && direction.x > 0) ||
(charPositionX >= canvas.width-32 && direction.x < 0))
charPositionX += direction.x;
}
if(direction.y){
if((charPositionY > 0 && charPositionY < canvas.height-32) ||
(charPositionY <= 0 && direction.y > 0) ||
(charPositionY >= canvas.width-32 && direction.y < 0))
charPositionY += direction.y;
}
// finally draw ou character
draw();
// update the raf id
raf = requestAnimationFrame(move);
};
// let's go !
raf = requestAnimationFrame(move);
}
draw();
window.addEventListener('keydown', triggerMoveChar, true);
window.addEventListener('keyup', releaseMoveChar, true);
canvas {
margin: auto;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 3px solid red;
}
body {
background: #222;
}
.container {
color: #999;
margin: 0;
padding: 10px 0px 20px;
font-family: "Orbitron", "Helvetica", sans-serif;
text-align: center;
font-size: 11px;
line-height: 16px;
}
.container h1 {
margin: 10px 0;
color: red;
font-size: 32px;
min-height: 430px;
}
.container h2 {
margin: 10px 0;
color: #ccc;
font-size: 24px;
min-height: 10px;
}
.container h3 {
margin: 10px 0;
color: #999;
font-size: 18px;
}
<div class="container">
<canvas id="canvas" width="640" height="416"></canvas>
<h1>Project : Simple Game [v0.1alpha]</h1>
<h2>CONTROLS: </h2>
<h3>Arrow Keys </h3>
</div>
I will appreciate any help.

You have a typo on this line
if(direction.y){
if((charPositionY > 0 && charPositionY < canvas.height-32) ||
(charPositionY <= 0 && direction.y > 0) ||
(charPositionY >= canvas.width-32 && direction.y < 0)) // here
charPositionY += direction.y;
}
It should be height not width.
(charPositionY >= canvas.height-32 && direction.y < 0))

Related

Snake Collision with Borders

I am making a snake game, in html, css, and js. It is been working good to me, then i noticed that when i pause the game, the canva seems to move, and the snake collsiion with the left and bottom border is not working correctly, can you help me find my error
let score = 0;
let gameOver = false;
let isPaused = false;
const appleImg = new Image();
appleImg.src = "apple.png";
let snakeHeadImg = new Image();
snakeHeadImg.src = "snakeHead.png";
let startTime = Date.now();
let speed = 75;
let eatingSound = new Audio("Coin.wav");
let deathSound = new Audio("Death.wav");
let bgMusic = document.getElementById("bg-music");
bgMusic.play();
// Get the canvas element
const canvas = document.getElementById("game-canvas");
// Set the canvas dimensions
canvas.width = 400;
canvas.height = 400;
// Get the canvas context
const ctx = canvas.getContext("2d");
// Initialize snake
let snake = [{x: 200, y: 200}];
// Initialize food
let food = {x: Math.floor(Math.random() * (canvas.width - 20)), y: Math.floor(Math.random() * (canvas.width - 20))};
// Initialize snake direction
let direction = "right";
// Draw the score
function drawScore() {
document.getElementById("score").innerHTML = "Score: " + score;
}
// Draw the snake
function drawSnake() {
ctx.fillStyle = "#f1fa8c";
for (let i = 0; i < snake.length; i++) {
if (i === 0) {
// Save the current canvas state
ctx.save();
// Translate the canvas to the position of the snake head
ctx.translate(snake[i].x + 5, snake[i].y + 5);
// Rotate the canvas based on the snake's direction
switch (direction) {
case 'down':
ctx.rotate(180 * Math.PI/180);
break;
case 'right':
ctx.rotate(90 * Math.PI/180);
break;
case 'left':
ctx.rotate(-90 * Math.PI/180);
break;
}
// Draw the head of the snake using the image
ctx.drawImage(snakeHeadImg, -5, -5, 10, 10);
// Restore the canvas state
ctx.restore();
} else {
// Draw the rest of the snake using rectangles
ctx.fillRect(snake[i].x, snake[i].y, 10, 10);
}
}
}
// Draw the food
function drawFood() {
ctx.drawImage(appleImg, food.x, food.y, 15, 15);
}
// Move the snake
function moveSnake() {
let head = {x: snake[0].x, y: snake[0].y};
if (direction === "right") {
head.x += 10;
} else if (direction === "left") {
head.x -= 10;
} else if (direction === "up") {
head.y -= 10;
} else if (direction === "down") {
head.y += 10;
}
snake.unshift(head);
snake.pop();
}
// Clear the canvas
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// Check for collision between the snake itself
function checkSelfCollision() {
for (let i = 1; i < snake.length; i++) {
if (snake[i].x === snake[0].x && snake[i].y === snake[0].y) {
gameOver = true;
// play the death sound
bgMusic.currentTime = 0;
bgMusic.pause();
deathSound.currentTime = 0;
deathSound.play();
break;
}
}
}
// Check for collision between snake and food
function checkCollision() {
if (Math.abs(snake[0].x - food.x) <= 15 && Math.abs(snake[0].y - food.y) <= 15) {
food = {x: Math.floor(Math.random() * canvas.width), y: Math.floor(Math.random() * canvas.height)};
score++;
snake.push({x: snake[snake.length-1].x, y: snake[snake.length-1].y});
// play the eating sound
eatingSound.currentTime = 0;
eatingSound.play();
}
}
// Check for collision between snake and border
function checkBorderCollision() {
if (snake[0].x < 0 || snake[0].x > canvas.width || snake[0].y < 0 || snake[0].y > canvas.height) {
gameOver = true;
// play the death sound
bgMusic.currentTime = 0;
bgMusic.pause();
deathSound.currentTime = 0;
deathSound.play();
}
}
document.addEventListener("keydown", event => {
if (event.code === "Space") {
if(isPaused) {
isPaused = false;
gameLoop();
}
else if(!gameOver) {
isPaused = true;
}
}
});
const pauseButton = document.getElementById("pause");
pauseButton.addEventListener("click", handlePauseClick);
function handlePauseClick(event) {
if (event.target.id === "pause") {
if(isPaused) {
isPaused = false;
gameLoop();
}
else if(!gameOver) {
isPaused = true;
}
}
}
// Show game over screen
function showGameOverScreen() {
ctx.fillStyle = "rgba(0, 0, 0, 0.4)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font = "30px Arial";
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.fillText("Game Over", canvas.width / 2, canvas.height / 2 - 50);
ctx.fillText("Score: " + score, canvas.width / 2, canvas.height / 2);
ctx.font = "20px Arial";
ctx.fillText("Press 'R' to restart", canvas.width / 2, canvas.height / 2 + 50);
ctx.fillText("Press 'Q' to quit", canvas.width / 2, canvas.height / 2 + 80);
}
// Main game loop
function gameLoop() {
if(isPaused) {
ctx.fillStyle = "rgba(0, 0, 0, 0.4)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font = "30px Arial";
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.fillText("Game Paused", canvas.width/2, canvas.height/2);
ctx.fillText("Press space to continue", canvas.width/2, canvas.height/2+30);
return;
} else {
bgMusic.play();
clearCanvas();
drawScore();
drawFood();
drawSnake();
moveSnake();
checkSelfCollision();
checkCollision();
checkBorderCollision();
if (gameOver) {
showGameOverScreen();
return;
}
let elapsedTime = Date.now() - startTime;
if (elapsedTime > 60000) { // 60 seconds
speed = 60;
}
if (elapsedTime > 120000) { // another 60 seconds
speed = 45;
}
speed = Math.max(speed, 45); // minimum value
setTimeout(gameLoop, speed);
}
}
gameLoop();
// Handle arrow key presses
document.addEventListener("keydown", event => {
if ((event.code === "ArrowRight" || event.code === "KeyD") && direction !== "left") {
direction = "right";
} else if ((event.code === "ArrowLeft" || event.code === "KeyA") && direction !== "right") {
direction = "left";
} else if ((event.code === "ArrowUp" || event.code === "KeyW") && direction !== "down") {
direction = "up";
} else if ((event.code === "ArrowDown" || event.code === "KeyS") && direction !== "up") {
direction = "down";
}
});
const upButton = document.getElementById("up-button");
const leftButton = document.getElementById("left-button");
const downButton = document.getElementById("down-button");
const rightButton = document.getElementById("right-button");
upButton.addEventListener("click", handleButtonClick);
leftButton.addEventListener("click", handleButtonClick);
downButton.addEventListener("click", handleButtonClick);
rightButton.addEventListener("click", handleButtonClick);
function handleButtonClick(event) {
if (event.target.id === "right-button" && direction !== "left") {
direction = "right";
} else if (event.target.id === "left-button" && direction !== "right") {
direction = "left";
} else if (event.target.id === "up-button" && direction !== "down") {
direction = "up";
} else if (event.target.id === "down-button" && direction !== "up") {
direction = "down";
}
}
// Handle restart and quit keys
document.addEventListener("keydown", event => {
if (event.code === "KeyR" && gameOver) {
location.reload();
} else if (event.code === "KeyQ" && gameOver) {
window.close();
}
});
body {
background-color: #1d1f21;
}
#game-canvas {
border: 2px solid #f1fa8c;
font-family: 'Source Sans Pro', sans-serif;
color: #f1fa8c;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#score{
border: 2px solid #f1fa8c;
font-family: 'Source Sans Pro', sans-serif;
color: #f1fa8c;
position: absolute;
top: 25%;
left: 50%;
padding: 10px;
transform: translate(-50%, -50%);
font-weight: bolder;
box-shadow: 0 0 5px #c5e1a5;
}
#game-title {
font-size: 80px;
font-family: "Futura";
text-align: center;
color: #f1fa8c;
text-shadow: 0 0 10px #c5e1a5, 0 0 20px #c5e1a5, 0 0 30px #c5e1a5, 0 0 40px #c5e1a5, 0 0 50px #c5e1a5, 0 0 60px #c5e1a5;
position: absolute;
top: 10px;
left: 50%;
transform: translate(-50%, -50%);
}
#buttons {
font-family: 'Source Sans Pro', sans-serif;
color: #f1fa8c;
position: absolute;
top: 85%;
left: 50%;
transform: translate(-50%, -50%);
}
.buttons{
font-size: 30px;
height: 60px;
width: 60px;
border: 2px solid #f1fa8c;
background-color: #1d1f21;
color: #f1fa8c;
}
.pauseButton{
position: absolute;
top: 17%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 30px;
height: 60px;
width: auto;
border: 2px solid #f1fa8c;
background-color: #1d1f21;
color: #f1fa8c;
}
<!DOCTYPE html>
<html>
<head>
<title>Snake Game</title>
<link rel="stylesheet" type="text/css" href="style.css">
<audio id="bg-music" src="Snake1.wav" loop></audio>
</head>
<body>
<h1 id="game-title">Snakeee</h1>
<button class="pauseButton" id="pause">Pause</button>
<p id="score"></p>
<canvas id="game-canvas"></canvas>
<div id="buttons">
<center>
<button class="buttons" id="up-button">W</button> <br>
<button class="buttons" id="left-button">A</button>
<button class="buttons" id="down-button">S</button>
<button class="buttons" id="right-button">D</button>
</center>
</div>
<script src="script.js"></script>
</body>
</html>
If you press to run the snipet it wont due to images in the code, so just use any images if you want to run and test it

Why is the bullet not drawn when the background is?

I am trying to make bullet objects for my HTML game, but they won't get drawn, even though the background (which is drawn the same way before the bullets) works.
<!DOCTYPE html>
<html>
<head>
<title>
Shooter
</title>
<style>
body{
background-color: blue;
}
canvas{
position: absolute;
top: 50px;
left: 50px;
}
h1{
color: yellow;
position: absolute;
top: 0px;
left: 50px;
}
p{
color: red;
position: absolute;
top: 450px;
left: 50px;
}
</style>
</head>
<body onkeydown='getKeyAndMove(event)'>
<h1>
Shooter
</h1>
<canvas width='800' height='400' id='myCanvas'></canvas>
<p>
Use Up and Down to move, Space to shoot. Don't get hit!
</p>
<script>
var start = null;
var playery = 0;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var radius = 1;
var bullets = [null];
var enemies = new Array(null);
function fire(playery, bullets, enemies){
if (bullets[0] === null){
console.log(9)
bullets[0] = {
x:0,
y:playery,
length:50,
height:25,
update: function(enemies){
bullets[0].x += 5;
var maxCount = enemies.length;
/*for (i=0; i<maxCount; i++){
var enemy = enemies[i];
if (enemy.x <= bullets[0].x + bullets[0].length){
if (enemy.x + enemy.length >= bullets[0].x){
if (enemy.y + enemy.height >= bullets[0].y){
if (enemy.y <= bullets[0].y + bulets[0].height){
enemies[i] = null;
bullets[0] = null;
}
}
}
}
}*/
if (bullets[0].x >= 800){
bullets[0] = null;
return;
}
}
};
}
};
function getKeyAndMove(e){
var key_code=e.which||e.keyCode;
switch(key_code){
case 38:
playery -= 5
break;
case 40:
playery += 5
break;
case 32:
console.log(32)
fire(playery, bullets, enemies);
break;
}
};
function step(timestamp){
if (!start) start = timestamp;
var progress = timestamp - start;
ctx.fillStyle = 'white'
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = 'rgb(0, 0, 0)'
ctx.fillRect(1, 1, canvas.width - 2, canvas.height - 2)
var i=0;
var j=0;
for (i=0; i < 800; i++){
for (j=0; j < 400; j++){
if (Math.random() > 0.9999) {
ctx.beginPath();
ctx.arc(i, j, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'white';
ctx.fill();
ctx.lineWidth = 0;
ctx.strokeStyle = '#FFFFFF';
ctx.stroke();
ctx.closePath();
}
}
}
if (bullets[0] != null){
bullets[0].update(enemies)
console.log(0)
if(bullets[0] != null){
ctx.fillStyle = '#DD0000'
ctx.fillRect(bullets[0].x, bullets[0].y, bullets[0].width, bullets[0].height)
}
}
window.requestAnimationFrame(step)
}
window.requestAnimationFrame(step)
</script>
</body>
</html>
The console shows no errors when I run the code. I have set it to log every frame that there is a bullet, and the log is showing up, the bullet just never appears.
What am I doing wrong?
I accidentally typed width instead of length in line 126. The problem is solved.

clearRect isnt clearing canvas

im developing a game as a coding exercise and ive come across a bug that i cant find when ever i press the selected button it does not remove the shape and redraw anotheer one it for some reason just keeps the shape on the page and draws a new shae i need it to delete the old shape and redraw a new shape this is how the game should work
enter code here
window.addEventListener("load", function() {
function clear(ctx, width, height) {
}
function drawRandomShape(width, height) {
//ctx.clearRect(0,0, canvas.width, canvas.height)
canvas.style.backgroundColor = 'white';
// var num = Math.floor(Math.random() * 10)
var number = 30;
var countdown = setInterval(function(){
timerSpan.innerHTML = number--;
//console.log(number)
if(number == 0 - 1){
clearInterval(countdown);
}
},1000);
function randomShape(){
var randomNum = Math.floor(Math.random() * 10);
//ctx.clearRect(0,0, canvas.width, canvas.height)
// if(number > 0){
if(randomNum >= 0 && randomNum <= 2){
// ctx.clearRect(0, 0, canvas.width, canvas.height);
var triangle = ctx.beginPath();
triangle += ctx.moveTo(0, 0);
triangle += ctx.lineTo(90, 90);
triangle += ctx.lineTo(0, 90);
triangle += ctx.closePath();
triangle += ctx.fillStyle = "red";
triangle += ctx.fill();
document.addEventListener('keyup', function shape(e){
if(e.keyCode == 37){
triangle += ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
document.removeEventListener('keyup', shape);
randomShape();
}
});
}else if(randomNum > 2 && randomNum <= 4){
// ctx.clearRect(0,0, canvas.width, canvas.height);
var blackTriangle = ctx.fillStyle = "black";
blackTriangle += ctx.beginPath();
blackTriangle += ctx.moveTo(0,0);
blackTriangle += ctx.lineTo(90, 90);
blackTriangle += ctx.lineTo(0, 90);
blackTriangle += ctx.fill();
document.addEventListener('keyup', function shape(e){
if(e.keyCode == 38){
blackTriangle += ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
document.removeEventListener('keyup', shape);
randomShape();
}
});
}else if(randomNum >= 4 && randomNum <= 6){
//ctx.clearRect(0, 0, canvas.width, canvas.height);
var redSquare = ctx.fillStyle = 'black';
redSquare += ctx.rect(200, 100, 90, 90)
redSquare += ctx.fill();
document.addEventListener('keyup', function shape(e){
if(e.keyCode == 39){
redSquare += ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
randomShape()
}
});
}else if(randomNum > 6 && randomNum < 10){
//ctx.clearRect(0,0, canvas.width, canvas.height);
var whiteSquare = ctx.rect(50,70,90,90);
whiteSquare += ctx.fillStyle = 'red';
whiteSquare += ctx.fill();
document.addEventListener('keyup', function shape(e) {
if(e.keyCode == 40){
whiteSquare += ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
document.removeEventListener('keyup', shape);
randomShape();
}
});
}
console.log(randomNum)
//};
}
randomShape();
}
//}, 1000);
function drawGameStartText(width, height ,score) {
width = 170;
height = 350;
ctx.fillStyle = 'White';
ctx.font = '30px Verdana'
ctx.fillText('Press space bar to start a new game' , width , height);
}
function restartGame(ctx, width, height){
}
var canvas = document.getElementById("shapes-game"),
height = canvas.scrollHeight,
width = canvas.scrollWidth,
gameOn = false,
expectedKey = undefined,
ctx = canvas.getContext('2d'),
// white triangle = up, red square = down,
// red triangle = left, white square = right
expectedKeysMap = {white0: 38, red1: 40, red0: 37, white1: 39};
timerSpan = document.getElementById("time-remaining");
scoreSpan = document.getElementById("score-val"),
seconds = 3;
// intervalId;
document.addEventListener("keyup", function(e) {
e.preventDefault();
if(e.keyCode == 32){
drawRandomShape();
}
});
drawGameStartText()
})
body {
padding-bottom: 50px;
}
#shapes-game {
border: 4px solid grey;
background-color: black;
}
.canvas-container {
padding: 10px;
}
.canvas-container, #shapes-game {
height: 750px;
width: 800px;
}
.scores {
padding: 10px;
text-align: center;
}
.legend {
padding-top: 15px;
}
.legend-contents {
text-align: left;
padding-left: 30px;
}
.triangle-bottomleft-red {
width: 0;
height: 0;
border-bottom: 50px solid red;
border-right: 50px solid transparent;
}
.triangle-bottomleft-black {
width: 0;
height: 0;
border-bottom: 54px solid black;
border-right: 58px solid transparent;
}
.triangle-inner-white {
position: relative;
top: 2px;
left: 2px;
width: 0;
height: 0;
border-bottom: 50px solid white;
border-right: 50px solid transparent;
}
.triangle-left {
width: 0;
height: 0;
border-top: 23px solid transparent;
border-bottom: 23px solid transparent;
border-right: 23px solid red;
}
.inner-triangle {
position: relative;
top: -20px;
left: 2px;
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 20px solid blue;
}
.red-square {
width: 50px;
height: 50px;
background-color: red;
}
.white-square {
width: 50px;
height: 50px;
background-color: white;
border-style: solid;
border-width: 1px;
}
<!DOCTYPE html>
<html>
<head>
<title>Shapes!!</title>
<link rel="stylesheet" type="text/css" href="vendor/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="styles.css">
<script type="text/javascript" src="vendor/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="vendor/bootstrap.min.js"></script>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
<div class="container">
<div class="col-xs-10 canvas-container">
<canvas id="shapes-game" height="750" width="800"></canvas>
</div>
<div class="col-xs-2 scores">
<h1>Score</h1>
<h3><span id="score-val">0</span></h3>
<h1>Timer</h1>
<h3><span id="time-remaining">30</span></h3>
<div class="legend">
<h1>Legend</h1>
<div class="legend-contents">
<div class="triangle-bottomleft-red">
</div>
<h4>Left</h4>
<div class="white-square">
</div>
<h4>Right</h4>
<div class="triangle-bottomleft-black">
<div class="triangle-inner-white"></div>
</div>
<h4>Up</h4>
<div class="red-square">
</div>
<h4>Down</h4>
</div>
</div>
</div>
</div>
</body>
</html>
There are a zillion things wrong with your code.
First of why are you doing
var blackTriangle = ctx.fillStyle = "black";
blackTriangle += ctx.beginPath();
As it does absolutely nothing.
Create one key handler and handle everything in that rather than
document.addEventListener('keyup', function shape(e){
if(e.keyCode == 39){
redSquare += ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
randomShape()
}
});
You are just creating a pile of key handlers.
If you want to track shapes you are drawing create an array for each shape
const shapes = {
whiteSquares : [],
redSquares : [],
whiteTriangle : [],
redTriangle: [],
};
then when you add the shape add it to the appropriate array
if(randomNum <= 2){
ctx.beginPath();
ctx.lineTo(0, 0);
ctx.lineTo(90, 90);
ctx.lineTo(0, 90);
ctx.closePath();
ctx.fillStyle = "red";
ctx.fill();
shapes.redTriangle.push([0,0]); // store the top left of the triangle
}
Then you can clear it in the key handler
var gameStarted = false;
const keyNames = {
space : 32,
left : 37;
up : 38,
right : 39,
down : 40,
}
// only one key handler needed.
document.addEventListener('keyup', e => {
if(gameStarted === false && e.keyCode === keyNames.space) {
gameStarted = true;
drawRandomShape();
}else if(e.keyCode === keyNames.left) {
if(shapes.redTriangle.length > 0){
var pos = shapes.redTriangle.shift(); // remove the bottom item in the array
ctx.clearRect(pos[0],pos[1],90,90); // clear that position
randomShape(); // create anothe shape.
}
}else if(e.keyCode === keyNames.right) {
if(shapes.whiteSquares.length > 0){
// same as above
}
}else if(e.keyCode === keyNames.up) {
if(shapes.whiteTriangle.length > 0){
// same as above
}
}else if(e.keyCode === keyNames.down) {
if(shapes.redSquares.length > 0){
// same as above
}
}
}
Dont over complicate conditional statements.
You have
var randomNum = Math.floor(Math.random() * 10);
if(randomNum >= 0 && randomNum <= 2){
// do stuff
}else if(randomNum > 2 && randomNum <= 4){
// do stuff
}else if(randomNum >= 4 && randomNum <= 6){
// do stuff
}else if(randomNum > 6 && randomNum < 10){
// do stuff
}
is the same as
var randomNum = Math.floor(Math.random() * 10);
if (randomNum <= 2) {
// do stuff
} else if(randomNum <= 4) {
// do stuff
} else if(randomNum <= 6) {
// do stuff
} else {
// do stuff
}

javascript - not working for loop

I'm coding Snake Game, but I have an issue.
var ctx = document.getElementById('ctx').getContext('2d');
var canvas = document.getElementById('ctx');
var y = [240, 230, 220];
var x = [240, 240, 240];
var xSpeed = 0;
var ySpeed = 0;
function load() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (p = 0; p < x.length; p++) {
ctx.fillStyle = "black";
ctx.fillRect(x[p], y[p], 10, 10);
}
}
function keyDown() {
var key = event.keyCode; /*getting keyCode of pressed key*/
ctx.fillStyle = "black"; /*color of rectangle*/
switch (key) {
case 39: //RIGHT
xSpeed = 10;
ySpeed = 0;
break;
case 37: //LEFT
xSpeed = -10;
ySpeed = 0;
break;
case 38: //UP
xSpeed = 0;
ySpeed = -10;
break;
case 40: //DOWN
xSpeed = 0;
ySpeed = 10;
break;
}
}
function update() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (x[0] >= 490) {
xSpeed = 0;
} else if (y[0] >= 490) {
ySpeed = 0;
}
//console.clear();
y[0] += ySpeed;
x[0] += xSpeed;
for (i = x.lenght; i >= 0; i--) {
y[i] = y[i - 1];
x[i] = x[i - 1];
console.log(i);
}
for (i = 0; i < x.length; i++) {
ctx.fillStyle = "black";
ctx.fillRect(x[i], y[i], 10, 10);
//console.log("y= " + y[i]);
//console.log("x= " + x[i]);
}
//console.log(xSpeed);
//console.log(ySpeed);
}
setInterval(update, 500);
<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="#">
<title>The Snake Game</title>
</head>
<style>
#ctx {
position: absolute;
/*it can be fixed too*/
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
/*this to solve "the content will not be cut when the window is smaller than the content":*/
max-width: 100%;
max-height: 100%;
overflow: auto;
}
</style>
<body onkeydown="keyDown()" onload="load()">
<center><canvas id="ctx" width="500" height="500" style="border:1px solid black"></canvas></center>
</body>
<script src="script.js"></script>
</html>
The for loop inside of update function is not loggin, so it looks like it's not working.
for (i = x.lenght; i >= 0; i--) {
y[i] = y[i - 1];
x[i] = x[i - 1];
console.log(i);
}
I don't know what I've done wrong, but I think it's just another one stupid mistake. Please don't criticize me so much, I'm just nooby 14 y.o. programmer.
Thanks in advice,
Tomas ;-)
On a first sight it's just a typing mistake because you wrote x.lenght instead of x.length.
var ctx = document.getElementById('ctx').getContext('2d');
var canvas = document.getElementById('ctx');
var y = [240, 230, 220];
var x = [240, 240, 240];
var xSpeed = 0;
var ySpeed = 0;
function load() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (p = 0; p < x.length; p++) {
ctx.fillStyle = "black";
ctx.fillRect(x[p], y[p], 10, 10);
}
}
function keyDown() {
var key = event.keyCode; /*getting keyCode of pressed key*/
ctx.fillStyle = "black"; /*color of rectangle*/
// Prevent the snake from going in the reverse direction.
switch (key) {
case 39: //RIGHT
if(xSpeed != -10) {
xSpeed = 10;
ySpeed = 0;
}
break;
case 37: //LEFT
if(xSpeed != 10) {
xSpeed = -10;
ySpeed = 0;
}
break;
case 38: //UP
if(ySpeed != 10) {
xSpeed = 0;
ySpeed = -10;
}
break;
case 40: //DOWN
if(ySpeed != -10) {
xSpeed = 0;
ySpeed = 10;
}
break;
}
}
function update() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (x[0] >= 490) {
xSpeed = 0;
} else if (y[0] >= 490) {
ySpeed = 0;
}
if((xSpeed + ySpeed) != 0) {
for(var idx = x.length - 1; idx >= 1; idx--) {
y[idx] = y[idx - 1];
x[idx] = x[idx - 1];
}
}
y[0] += ySpeed;
x[0] += xSpeed;
for (i = 0; i < x.length; i++) {
ctx.fillStyle = "black";
ctx.fillRect(x[i], y[i], 10, 10);
}
}
setInterval(update, 500);
<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="#">
<title>The Snake Game</title>
</head>
<style>
#ctx {
position: absolute;
/*it can be fixed too*/
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
/*this to solve "the content will not be cut when the window is smaller than the content":*/
max-width: 100%;
max-height: 100%;
overflow: auto;
}
</style>
<body onkeydown="keyDown()" onload="load()">
<center><canvas id="ctx" width="500" height="500" style="border:1px solid black"></canvas></center>
</body>
<script src="script.js"></script>
</html>
I really liked your code, especially for how simple it is! So I have added a slightly improved version here. These are the issues I noticed:
Spoilers
In the keyDown function, by adding the condition to check previous speed you can prevent the snake from reversing its direction.
In update function you should update the location of x[0] and y[0] only after updating the "tail" elements. Otherwise, you would not have the new location for the x[1] and y[1] element.
Also, you might need to put an if condition for (xSpeed + ySpeed) != 0 around the loop that updates the location of the tail elements. This would help ensure that the snake doesn't jumble up into single element before the user interacts with it.

Moving Image is lagging on Canvas with Keydown [duplicate]

The "spaceShip" in the following code isn't moving smoothly at the beginning of holding any arrow key down. It moves one step, freezes for a split second, and then moves "smoothly". How can I make it move smoothly right from the beginning, with not "freezing"?
My code:
<!doctype html>
<html>
<head>
<meta http-content="Content-type" charset="utf-8">
<title>Make body move smoothly</title>
<style type="text/css">
body {
}
canvas {
margin: auto;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="600"></canvas>
<script type="text/javascript">
// Set up requestAnimationFrame and cancelAnimationFrame
(function() {
var lastTime =0;
var vendors=['ms', 'moz', 'webkit', 'o'];
for(var x=0; x<vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame=window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame =
window[vendors[x]+ 'CancelAnimationFrame'] ||
window[vendors[x] +'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame=function(callback, element) {
var currTime =new Date().getTime();
var timeToCall =Math.max(0, 16 - (currTime - lastTime));
var id =window.setTimeout(function() { callback(currTime+timeToCall); },
timeToCall);
lastTime =currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame=function(id) {
clearTimeout(id);
};
}());
var canvas;
var ctx;
// ship data
var shipPositionX = document.getElementById('canvas').width/2;
var shipPositionY = document.getElementById('canvas').height - 30;
var deltaShipPositionX = 10;
var deltaShipPositionY = 10;
function init() {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
draw();
}
function draw(){
clear();
createRectangleToCoverCanvas();
createSpaceShip(shipPositionX, shipPositionY, 10);
requestAnimationFrame(draw);
}
function clear(){
ctx.clearRect(0, 0, document.getElementById('canvas').width, document.getElementById('canvas').height);
}
function createRectangleToCoverCanvas(){
ctx.fillStyle = 'black';
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
function createSpaceShip(x, y, radius) {
ctx.fillStyle = 'white'
ctx.strokeStyle = 'white'
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
function moveSpaceShip(event){
switch(event.keyCode){
// left
case 37:
if(shipPositionX - deltaShipPositionX + 15 > 0){
shipPositionX -= deltaShipPositionX;
}
break;
// up
case 38:
if(shipPositionY - deltaShipPositionY + 15 > 0){
shipPositionY -= deltaShipPositionY;
}
break;
// right
case 39:
if(shipPositionX + deltaShipPositionX < document.getElementById('canvas').width){
shipPositionX += deltaShipPositionX;
}
break;
//down
case 40:
if(shipPositionY + deltaShipPositionY < document.getElementById('canvas').height){
shipPositionY += deltaShipPositionY;
}
break;
}
}
window.addEventListener('load', init);
window.addEventListener('keydown', moveSpaceShip, true);
</script>
</body>
</html>
Notice the difference between my code and this example: http://atomicrobotdesign.com/blog_media/sprite_sheet/spritesheet.html
See how the example's is smooth, but my "spaceShip" isn't?
Why is it happening and how can I fix it? Is it because the example uses a sprite (but this doesn't seem to make much sense)?
The problem is that you wait for each keydown event to update the ship position.
The keydown event has a delay before it triggers again : the delay you are experiencing at beginning and the jump you face at each redraw.
The solution here is to trigger the movement on keydown and release it on keyup. This way, your ship will move smoothly as soon as you push the button.
// Im' assuming most of visitors here have recent browsers, so I removed the rAF polyfill for readibility
// If you wrap it after the canvas element decalaration, you can already populate this variable, it will avoid that you make a lot of calls to document.getElementById()
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// ship data
var shipPositionX = canvas.width / 2;
// Just for the snippet height
var shipPositionY = 0;
var deltaShipPositionX = 10;
var deltaShipPositionY = 10;
//Removed the init() function, since our elements are loaded.
function draw() {
clear();
createRectangleToCoverCanvas();
createSpaceShip(shipPositionX, shipPositionY, 10);
}
function clear() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function createRectangleToCoverCanvas() {
ctx.fillStyle = 'black';
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fill();
ctx.stroke();
}
function createSpaceShip(x, y, radius) {
ctx.fillStyle = 'white'
ctx.strokeStyle = 'white'
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.fill();
ctx.stroke();
}
// instantiate a variable that will store our animationFrame id, so we can cancel it further
var raf,
// the direction object, with an x and y values
direction = {
x: 0,
y: 0
};
// we can set a speed variable
var speed = 2.5;
function triggerMoveSpaceShip(event) {
switch (event.keyCode) {
// left
case 37:
// update the direction object
direction.x = -speed;
// avoid the scroll in the snippet
event.preventDefault();
break;
// up
case 38:
direction.y = -speed;
event.preventDefault();
break;
// right
case 39:
direction.x = speed;
event.preventDefault();
break;
//down
case 40:
direction.y = speed;
event.preventDefault();
break;
}
// if we haven't initiated the animation yet, and that our direction is not 0, then do it now
if (!raf && (direction.x || direction.y)) moveSpaceShip();
}
function releaseMoveSpaceShip(event) {;
switch (event.keyCode) {
// left
case 37:
//reset this direction
direction.x = 0;
break;
// up
case 38:
direction.y = 0;
break;
// right
case 39:
direction.x = 0;
break;
//down
case 40:
direction.y = 0;
break;
}
if (!direction.x && !direction.y) {
// if none of the directions is set, stop the animation
cancelAnimationFrame(raf);
raf = undefined;
}
}
function moveSpaceShip() {
// declare our animation function
var move = function() {
// update the positions without going out of the screen
// Sorry, this is dirty...
if(direction.x){
if(
(shipPositionX > 0 && shipPositionX < canvas.width-20) ||
(shipPositionX <= 0 && direction.x > 0) ||
(shipPositionX >= canvas.width-20 && direction.x < 0))
shipPositionX += direction.x;
}
if(direction.y){
if(
(shipPositionY > 0 && shipPositionY < canvas.height-20) ||
(shipPositionY <= 0 && direction.y > 0) ||
(shipPositionY >= canvas.width-20 && direction.y < 0))
shipPositionY += direction.y;
}
// finally draw ou ship
draw();
// update our raf id
raf = requestAnimationFrame(move);
};
// let's go !
raf = requestAnimationFrame(move);
}
draw();
window.addEventListener('keydown', triggerMoveSpaceShip, true);
window.addEventListener('keyup', releaseMoveSpaceShip, true);
canvas {
margin: auto;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 1px solid black;
}
body{
overflow: none;
}
<canvas id="canvas" width="400" height="200"></canvas>
uncommented fiddle

Categories