Javascript画布没有重绘?

时间:2015-09-25 14:25:05

标签: javascript html5 canvas

我正在开发一款游戏(基于画布),但我遇到了一个问题。显然,当我按下一个键,而不是画布更新对象的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;

有谁知道如何解决这个问题?很抱歉,如果这是一个令人难以置信的基本代码问题。

4 个答案:

答案 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

JSfile链接http://canvascode.co.uk/Projects/spaceencounter.js