How to use arrow keys to move object smoothly in canvas

こ雲淡風輕ζ 提交于 2019-12-13 17:36:05

问题


I'm working on making a simple space game where a ship moves left and right to dodge asteroids.

I learned to move my ship left and right from this video.

But the movement is pretty blocky. How do I move the ship smoothly?

Here is all my code:

// JavaScript Document

////// Variables //////
var canvas = {width:300, height:300 };
var score = 0;

var player = {
	x:canvas.width/2,
	y:canvas.height-100,
	speed: 20
};




////// Arrow keys //////

function move(e) {
	
	if(e.keyCode == 37) { 
		player.x -= player.speed;
	}
	if(e.keyCode == 39) {
		player.x += player.speed;	
	}
	
	update();
	
}

document.onkeydown = move;



////// other functions //////


//function to clear canvas
function clearCanvas() {
	ctx.clearRect(0,0,canvas.width,canvas.height);
}

// Draw Player ship.
function ship(x,y) {
	var x = player.x;
	var y = player.y;
	ctx.fillStyle = "#FFFFFF";

	ctx.beginPath();
    ctx.moveTo(x,y);
    ctx.lineTo(x+15,y+50);
    ctx.lineTo(x-15,y+50);
    ctx.fill();
}

// update

setInterval (update, 50);

function update() {
	clearCanvas();
	ship();
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>My Game</title>   

<script src="game-functions.js"></script>
        
</head>

<body>

<canvas id="ctx" width="300" height="300" style="border: thin solid black; background-color: black;"></canvas>
<br>


<script>
////// Canvas setup //////
var ctx = document.getElementById("ctx").getContext("2d");



</script>

</body>
</html>

回答1:


This is because keydown triggers events similarity to how you keyboard will type on Notepad, as it it will trigger once have a slight delay and they trigger many more timers.

As @Azamantes stated to solve this you will want to make a boolean that is set to true on keydown and false on keyup. Then you will be using a main event loop with either a setTimeout/setInterval and/or requestAnimationFrame. In the example below I've just used setInterval for the main loop for simplicity since you already have it, we can then move move() into that main loop:


Note: For implementing requestAnimationFrame see @MarkE's comment on this question.

Also requestAnimationFrame will refresh as much as it can by default. In other words you need to add more logic if you need to control the FPS, which can be common in HTML5 games. For using requestAnimationFrame with controlled FPS see this answer.

// JavaScript Document

////// Variables //////
var canvas = {width:300, height:300 };
var score = 0;

var player = {
	x:canvas.width/2,
	y:canvas.height-100,
	speed: 3
};

var LEFT = false; 
var RIGHT = false;


////// Arrow keys //////

function move() {
	
	if(LEFT) { 
		player.x -= player.speed;
	}
	if(RIGHT) {
		player.x += player.speed;	
	}
	
}

document.onkeydown = function(e) {
	if(e.keyCode == 37) LEFT = true;
	if(e.keyCode == 39) RIGHT = true;
}

document.onkeyup = function(e) {
	if(e.keyCode == 37) LEFT = false;
	if(e.keyCode == 39) RIGHT = false;
}


////// other functions //////


//function to clear canvas
function clearCanvas() {
	ctx.clearRect(0,0,canvas.width,canvas.height);
}

// Draw Player ship.
function ship(x,y) {
	var x = player.x;
	var y = player.y;
	ctx.fillStyle = "#FFFFFF";

	ctx.beginPath();
    ctx.moveTo(x,y);
    ctx.lineTo(x+15,y+50);
    ctx.lineTo(x-15,y+50);
    ctx.fill();
}

// update

setInterval (update, 10);

function update() {
	clearCanvas();
	ship();
    move();
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>My Game</title>   

<script src="game-functions.js"></script>
        
</head>

<body>

<canvas id="ctx" width="300" height="300" style="border: thin solid black; background-color: black;"></canvas>
<br>


<script>
////// Canvas setup //////
var ctx = document.getElementById("ctx").getContext("2d");



</script>

</body>
</html>



回答2:


  1. Use requestAnimationFrame
  2. Don't put update (your rendering) inside keyUp keyDown event handlers
  3. Make a boolean variable (one for each directio) and set it to true on keuDown and to false on keyUp and inside your rendering functions add a simple if check

TL;DR

Make your life simpler.

You might want to use event.key instead, which returns key name ('a', 'Esc', 'Space' etc), makes it more readable if you don't put comments next to the keyCodes.



来源:https://stackoverflow.com/questions/39806858/how-to-use-arrow-keys-to-move-object-smoothly-in-canvas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!