Проблема в том, что вы ждете, когда каждое событие keydown
обновит позицию судна. Событие keydown имеет задержку, прежде чем он снова запустится: задержка, которую вы испытываете в начале, и прыжок, с которым вы сталкиваетесь при каждом перерисовке.
Решение состоит в том, чтобы вызвать движение на keydown
и отпустить его keyup
. Таким образом, ваш корабль будет двигаться плавно, как только вы нажмете кнопку.
// Im' assuming most of visitors here have recent browsers, so I removed the rAF polyfill for readibility
// If you wrap it after the canvas element decalaration, you can already populate this variable, it will avoid that you make a lot of calls to document.getElementById()
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// ship data
var shipPositionX = canvas.width / 2;
// Just for the snippet height
var shipPositionY = 0;
var deltaShipPositionX = 10;
var deltaShipPositionY = 10;
//Removed the init() function, since our elements are loaded.
function draw() {
clear();
createRectangleToCoverCanvas();
createSpaceShip(shipPositionX, shipPositionY, 10);
}
function clear() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function createRectangleToCoverCanvas() {
ctx.fillStyle = 'black';
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fill();
ctx.stroke();
}
function createSpaceShip(x, y, radius) {
ctx.fillStyle = 'white'
ctx.strokeStyle = 'white'
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.fill();
ctx.stroke();
}
// instantiate a variable that will store our animationFrame id, so we can cancel it further
var raf,
// the direction object, with an x and y values
direction = {
x: 0,
y: 0
};
// we can set a speed variable
var speed = 2.5;
function triggerMoveSpaceShip(event) {
switch (event.keyCode) {
// left
case 37:
// update the direction object
direction.x = -speed;
// avoid the scroll in the snippet
event.preventDefault();
break;
// up
case 38:
direction.y = -speed;
event.preventDefault();
break;
// right
case 39:
direction.x = speed;
event.preventDefault();
break;
//down
case 40:
direction.y = speed;
event.preventDefault();
break;
}
// if we haven't initiated the animation yet, and that our direction is not 0, then do it now
if (!raf && (direction.x || direction.y)) moveSpaceShip();
}
function releaseMoveSpaceShip(event) {;
switch (event.keyCode) {
// left
case 37:
//reset this direction
direction.x = 0;
break;
// up
case 38:
direction.y = 0;
break;
// right
case 39:
direction.x = 0;
break;
//down
case 40:
direction.y = 0;
break;
}
if (!direction.x && !direction.y) {
// if none of the directions is set, stop the animation
cancelAnimationFrame(raf);
raf = undefined;
}
}
function moveSpaceShip() {
// declare our animation function
var move = function() {
// update the positions without going out of the screen
// Sorry, this is dirty...
if(direction.x){
if(
(shipPositionX > 0 && shipPositionX < canvas.width-20) ||
(shipPositionX <= 0 && direction.x > 0) ||
(shipPositionX >= canvas.width-20 && direction.x < 0))
shipPositionX += direction.x;
}
if(direction.y){
if(
(shipPositionY > 0 && shipPositionY < canvas.height-20) ||
(shipPositionY <= 0 && direction.y > 0) ||
(shipPositionY >= canvas.width-20 && direction.y < 0))
shipPositionY += direction.y;
}
// finally draw ou ship
draw();
// update our raf id
raf = requestAnimationFrame(move);
};
// let's go !
raf = requestAnimationFrame(move);
}
draw();
window.addEventListener('keydown', triggerMoveSpaceShip, true);
window.addEventListener('keyup', releaseMoveSpaceShip, true);
canvas {
margin: auto;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border: 1px solid black;
}
body{
overflow: none;
}
Эта статья предоставляет больше подробную информацию об этой проблеме: http://electrosofts.com/systemverilog/arrays.html , особенно разделите 5.2.
упакованный массив А является механизмом для подразделения вектора в подполя, к которым можно удобно получить доступ как элементы массива. Следовательно, упакованный массив, как гарантируют, будет представлен как непрерывный набор битов. Распакованный массив может или не может быть так представлен. Упакованный массив отличается от распакованного массива в этом, когда упакованный массив появляется как основное устройство, это рассматривают как единственный вектор.
Распакованные массивы дадут вам больше ошибок при компиляции, чем упакованные.
По этой причине я вижу распакованные массивы в определениях портов модулей. Компилятор выдаст ошибку, если размеры сигнала не совпадают с портом с распакованными массивами. С упакованными массивами он обычно просто идет вперед и связывает вещи как можно лучше, не выдавая ошибки.