I'm working on a game (canvas-based), and I've run into a problem. Apparently, when I press a key, instead of the canvas updating the x and y of the object, it's just doing nothing. The variable itsself is updating, but the object on screen is not. Here's the code:
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 640;
canvas.height = 480;
document.body.appendChild(canvas);
var bluex = 560;
var bluey = 380;
var orangex = 20;
var orangey = 380;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 640, 480);
ctx.fillStyle = "orange";
ctx.fillRect(orangex, orangey, 64, 64);
ctx.fillStyle = "blue";
ctx.fillRect(bluex, bluey, 64, 64);
function keyDownHandler(event) {
var keyPressed = String.fromCharCode(event.keyCode);
if (keyPressed == "W") {
orangey = orangey - 5;
bluey = bluey - 5;
} else if (keyPressed == "D") {
orangex = orangex + 5;
bluex = bluex - 5;
} else if (keyPressed == "S") {
orangey = orangey + 5;
bluey = bluey + 5;
} else if (keyPressed == "A") {
orangex = orangex - 5;
bluex = bluex + 5;
}
alert(bluex + " " + bluey);
}
document.onkeydown = keyDownHandler;
Does anyone know how to fix this? Sorry if this is an incredibly basic code problem.
I'm working on a game (canvas-based), and I've run into a problem. Apparently, when I press a key, instead of the canvas updating the x and y of the object, it's just doing nothing. The variable itsself is updating, but the object on screen is not. Here's the code:
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 640;
canvas.height = 480;
document.body.appendChild(canvas);
var bluex = 560;
var bluey = 380;
var orangex = 20;
var orangey = 380;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 640, 480);
ctx.fillStyle = "orange";
ctx.fillRect(orangex, orangey, 64, 64);
ctx.fillStyle = "blue";
ctx.fillRect(bluex, bluey, 64, 64);
function keyDownHandler(event) {
var keyPressed = String.fromCharCode(event.keyCode);
if (keyPressed == "W") {
orangey = orangey - 5;
bluey = bluey - 5;
} else if (keyPressed == "D") {
orangex = orangex + 5;
bluex = bluex - 5;
} else if (keyPressed == "S") {
orangey = orangey + 5;
bluey = bluey + 5;
} else if (keyPressed == "A") {
orangex = orangex - 5;
bluex = bluex + 5;
}
alert(bluex + " " + bluey);
}
document.onkeydown = keyDownHandler;
Does anyone know how to fix this? Sorry if this is an incredibly basic code problem.
Share Improve this question asked Sep 25, 2015 at 14:25 NoOneSpecialNoOneSpecial 431 silver badge7 bronze badges 1-
Well, you didn’t tell JavaScript to redraw the canvas on keypress. Put the lines with
ctx.fillStyle
andctx.fillRect
in the handler function. – Sebastian Simon Commented Sep 25, 2015 at 14:31
4 Answers
Reset to default 4Change your function to the following:
function keyDownHandler(event) {
var ctx = canvas.getContext("2d");
var keyPressed = String.fromCharCode(event.keyCode);
if (keyPressed == "W") {
orangey = orangey - 5;
bluey = bluey - 5;
} else if (keyPressed == "D") {
orangex = orangex + 5;
bluex = bluex - 5;
} else if (keyPressed == "S") {
orangey = orangey + 5;
bluey = bluey + 5;
} else if (keyPressed == "A") {
orangex = orangex - 5;
bluex = bluex + 5;
}
ctx.fillStyle = "orange";
ctx.fillRect(orangex, orangey, 64, 64);
ctx.fillStyle = "blue";
ctx.fillRect(bluex, bluey, 64, 64);
}
Your ctx.fillStyle didn't got called when the function was called, but the variables got updated
I see two potential problems here with your code.
First Problem
Your code only draws to the canvas once. You can bat this in two ways. Firstly, you could contain the drawing code within a loop to update the canvas every x amount of seconds. Your second option is to redraw the canvas whenever a key is pressed.
Second Problem
Before you redraw the canvas, you need to clear it. This helps to avoid some pretty trippy effects.
Potential Solution
window.requestAnimationFrame(function(){
ctx.clearRect(0, 0, yourCanvasWidth, yourCanvasHeight);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 640, 480);
ctx.fillStyle = "orange";
ctx.fillRect(orangex, orangey, 64, 64);
ctx.fillStyle = "blue";
ctx.fillRect(bluex, bluey, 64, 64);
})
Preferred Solution
Create a plete game loop.
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 640;
canvas.height = 480;
document.body.appendChild(canvas);
var bluex = 560;
var bluey = 380;
var orangex = 20;
var orangey = 380;
function gameLoop(){
update();
render();
requestAnimationFrame(gameLoop);
}
function update(){};
function render(){
ctx.clearRect(0, 0, yourCanvasWidth, yourCanvasHeight);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 640, 480);
ctx.fillStyle = "orange";
ctx.fillRect(orangex, orangey, 64, 64);
ctx.fillStyle = "blue";
ctx.fillRect(bluex, bluey, 64, 64);
}
function keyDownHandler(event) {
var keyPressed = String.fromCharCode(event.keyCode);
if (keyPressed == "W") {
orangey = orangey - 5;
bluey = bluey - 5;
} else if (keyPressed == "D") {
orangex = orangex + 5;
bluex = bluex - 5;
} else if (keyPressed == "S") {
orangey = orangey + 5;
bluey = bluey + 5;
} else if (keyPressed == "A") {
orangex = orangex - 5;
bluex = bluex + 5;
}
alert(bluex + " " + bluey);
}
document.onkeydown = keyDownHandler;
requestAnimationFrame(gameLoop); // TO START THINGS OFF
This is by no means the most efficient game loop, but it should point you in the right direction.
Note: Don't forget to update the yourCanvasWidth and yourCanvasHeight within the clear function to your actual values.
http://codeinplete./posts/2013/12/4/javascript_game_foundations_the_game_loop/
I would like to expand on Unlockedluca's answer. The reason that your canvas wasn't updating like you expected it to was because you never told it to. People that are new to the canvas element often forget that they are just drawing a bitmap. Your initial code would make more sense if you were controlling DOM elements because they are rendered independently and if you update one, it will correspond to what happens on the screen. However, the canvas element has no preconceived notion of objects and their properties. It is simply a platform for drawing a picture, which is fairly (and fittingly) analogous to an art canvas. You can't just move a circle you just drew.
Also, because you are always evaluating the same value, I would suggest using a switch
statement instead of consecutive if-then-else
statements.
// the parameter is the value you are evaluating
switch(keyPressed){
// 'case "W":' is similar to 'if (keyPressed=="W"){'
// However, it only tells the switch statement where to start
case "W":
orangey = orangey - 5;
bluey = bluey - 5;
// break is important because it tells the switch statement to stop here.
// The switch statement would otherwise continue and
// execute all of the proceeding cases until the end of the switch
break;
case "D":
orangex = orangex + 5;
bluex = bluex - 5;
break;
case "S":
orangey = orangey + 5;
bluey = bluey + 5;
break;
case "A":
orangex = orangex - 5;
bluex = bluex + 5;
break;
// Default is always called, unless you break out of the switch
// It is very helpful for catching values that you weren't expecting
default:
break;
}
}
You just need to create yourself a render function which is called via a setInterval call like so
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 640;
canvas.height = 480;
document.body.appendChild(canvas);
var bluex = 560;
var bluey = 380;
var orangex = 20;
var orangey = 380;
function render() {
console.log("Update canvas");
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 640, 480);
ctx.fillStyle = "orange";
ctx.fillRect(orangex, orangey, 64, 64);
ctx.fillStyle = "blue";
ctx.fillRect(bluex, bluey, 64, 64);
}
function keyDownHandler(event) {
var keyPressed = String.fromCharCode(event.keyCode);
if (keyPressed == "W") {
orangey = orangey - 5;
bluey = bluey - 5;
} else if (keyPressed == "D") {
orangex = orangex + 5;
bluex = bluex - 5;
} else if (keyPressed == "S") {
orangey = orangey + 5;
bluey = bluey + 5;
} else if (keyPressed == "A") {
orangex = orangex - 5;
bluex = bluex + 5;
}
}
document.onkeydown = keyDownHandler;
// setInerval(`function name`, `miliseconds between calls`)
var game = setInterval(render, 1);
You can follow the answer Unlockedluca provided if nothing else is updated when the game is running, however if there is a ball moving or some other objects you will need a render function which will clear the canvas and then redraw all objects back on to the canvas. Just thing of the canvas as a canvas which is cleared every time we want to move something.
If you would like some example code take a look at a small game I created here http://canvascode.co.uk/Projects/spaceencounter.html
JSfile link http://canvascode.co.uk/Projects/spaceencounter.js