如何使用箭头键在画布中平滑移动对象

时间:2016-10-01 12:55:42

标签: javascript html5 canvas arrow-keys

我正在制作一个简单的太空游戏,船只左右移动以避开小行星。

我学会了从this video左右移动我的船。

但这个动作相当块状。如何顺利移动船舶?

这是我的所有代码:

// 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>

2 个答案:

答案 0 :(得分:4)

这是因为keydown触发事件与键盘在记事本上键入的方式相似,因为它会触发一次稍有延迟并触发更多定时器。

正如 @Azamantes 所说,要解决这个问题,你需要在truekeydown false上设置一个布尔值keyup }。然后,您将使用包含setTimeout/setInterval和/或requestAnimationFrame的主事件循环。在下面的示例中,为了简单起见,我只使用setInterval作为主循环,因为您已经拥有它,我们可以将move()移动到该主循环中:

注意:有关实施requestAnimationFrame的信息,请参阅@MarkE对此问题的评论。

默认情况下,requestAnimationFrame也会尽可能多地刷新。换句话说,如果需要控制FPS,则需要添加更多逻辑,这在HTML5游戏中很常见。要使用受控FPS的requestAnimationFrame,请参阅this answer

&#13;
&#13;
// 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();
}
&#13;
<!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>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

  1. 使用requestAnimationFrame
  2. 不要将update(您的渲染)放在keyUp keyDown事件处理程序中
  3. 创建一个布尔变量(每个方向一个)并在keuDown上设置为true,在keyUp上设置为false,在渲染函数内部添加一个简单的if检查
  4. TL; DR

    让你的生活更简单。

    您可能希望改为使用event.key,它会返回键名(&#39; a&#39;,&#39; Esc&#39;,&#39; Space&#39;等)如果你不在keyCodes旁边放置评论,它会更具可读性。