最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - Javascript canvas not redrawing? - Stack Overflow

programmeradmin2浏览0评论

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 and ctx.fillRect in the handler function. – Sebastian Simon Commented Sep 25, 2015 at 14:31
Add a ment  | 

4 Answers 4

Reset to default 4

Change 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

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>