【问题标题】:How to use arrow keys to move object smoothly in canvas如何使用箭头键在画布中平滑移动对象
【发布时间】:2016-10-01 12:55:42
【问题描述】:

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

我从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>

【问题讨论】:

  • 一般来说,如果您更频繁地进行较小的动作(较小的 'player.speed')(时间间隔 1000/60=16.67),您的动作会更流畅。考虑了解requestAnimationFrame,这是一个更好的动画时序循环。

标签: javascript html canvas arrow-keys


【解决方案1】:

这是因为keydown 触发的事件与您在记事本上的键盘键入方式相似,因为它会触发一次,有轻微的延迟,然后会触发更多的计时器。

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


注意:要实现requestAnimationFrame,请参阅@MarkE 对此问题的评论。

此外,requestAnimationFrame 默认会尽可能多地刷新。换句话说,如果您需要控制 FPS,则需要添加更多逻辑,这在 HTML5 游戏中很常见。将 requestAnimationFrame 与受控 FPS 一起使用,请参阅 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>

【讨论】:

  • requestAnimationFrame will refresh as much as it can by default,不,这就是 rAF 的意义所在,它会在屏幕刷新率时调用。
  • @Kaiido 是的,我的意思是它会像屏幕刷新率一样快。这就是requestAnimationFrame 的意义所在,以及为什么控制它的 FPS 并不那么容易
【解决方案2】:
  1. 使用 requestAnimationFrame
  2. 不要将update(您的渲染)放在 keyUp keyDown 事件处理程序中
  3. 创建一个布尔变量(每个方向一个)并将其设置为 keuDown 上的 true 和 keyUp 上的 false 并在渲染函数中添加一个简单的 if 检查

TL;DR

让您的生活更简单。

您可能想改用event.key,它返回键名('a'、'Esc'、'Space' 等),如果您不将 cmets 放在 keyCodes 旁边,它会更易读。

【讨论】:

  • 很好的一般建议,但由于 OP 是 javascript 和游戏开发的新手,您可能希望扩展您的答案以填补您的答案与他们的经验之间的差距。 ;-)
猜你喜欢
  • 2020-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 2016-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多