我正在开发一款游戏(基于画布),但我遇到了一个问题。显然,当我按下一个键,而不是画布更新对象的x和y时,它就是什么都不做。变量本身正在更新,但屏幕上的对象不是。这是代码:
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;
有谁知道如何解决这个问题?很抱歉,如果这是一个令人难以置信的基本代码问题。
答案 0 :(得分:4)
将您的功能更改为以下内容:
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);
}
调用函数时没有调用ctx.fillStyle,但变量已更新
答案 1 :(得分:3)
我发现你的代码有两个潜在的问题。
您的代码只会绘制一次画布。你可以通过两种方式解决这个问题。首先,您可以在循环中包含绘图代码,每隔x秒更新画布。第二个选项是在按下某个键时重绘画布。
在重绘画布之前,需要清除它。这有助于避免一些非常有趣的效果。
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);
})
创建一个完整的游戏循环。
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
这绝不是最有效的游戏循环,但它应该指向正确的方向。
注意:不要忘记将clear函数中的yourCanvasWidth和yourCanvasHeight更新为实际值。
http://codeincomplete.com/posts/2013/12/4/javascript_game_foundations_the_game_loop/
答案 2 :(得分:1)
我想扩展Unlockedluca的答案。 您的画布没有像您预期的那样更新的原因是因为您从未告诉过它。对canvas元素不熟悉的人经常忘记他们只是绘制一个位图。如果您控制DOM元素,那么您的初始代码会更有意义,因为它们是独立呈现的,如果您更新它,它将对应于屏幕上发生的事情。但是,canvas元素没有先入为主的对象及其属性的概念。它只是一个绘制图片的平台,它与艺术画布相当(并且恰当地)类似。你不能只是移动一个刚绘制的圆圈。
另外,因为您总是在评估相同的值,我建议使用switch
语句而不是连续的if-then-else
语句。
// 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;
}
}
答案 3 :(得分:1)
你只需要创建一个渲染函数,通过setInterval调用来调用它,就像这样
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);
如果在游戏运行时没有其他任何内容更新,您可以按照Unlockedluca提供的答案进行操作,但是如果有球移动或其他某些对象,则需要渲染功能来清除画布,然后重新绘制所有对象。到画布。画布就像画布一样,每当我们想要移动时都会被清除。
如果您想要一些示例代码,请查看我在此处创建的小游戏http://canvascode.co.uk/Projects/spaceencounter.html