问题
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:
- Use requestAnimationFrame
- Don't put
update
(your rendering) inside keyUp keyDown event handlers - Make a boolean variable (one for each directio) and set it to
true
on keuDown and tofalse
on keyUp and inside your rendering functions add a simpleif
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