Задержка при передвижении персонажа
При передвижении персонажа происходит некая задержка. Как пример, зажимаю клавишу управления, персонаж двигается только на несколько координат, через некоторое время двигается так, как мне необходимо.
Не подскажете, как убрать данную проблему?
const canv = document.querySelector("canvas");
let ctx = canv.getContext("2d");
canv.height = 768;
canv.width = 1024;
class Unit {
constructor(options) {
this.ctx = options.ctx;
this.image = options.image;
this.width = options.width;
this.height = options.height;
this.cordinateFrameY = 580;
this.numberOfFrames = options.numberOfFrames;
this.lengthFrames = (this.numberOfFrames * this.width) - this.width;
this.positionX = options.position.x;
this.positionY = options.position.y;
this.velocity = options.velocity;
this.tick_count = 0;
this.x = 0;
this.tick();
}
tick() {
if (this.tick_count > 5) {
this.draw();
this.tick_count = 0;
}
this.tick_count += 1;
requestAnimationFrame(() => {
this.tick();
});
}
draw() {
this.x = (this.x === this.lengthFrames ? this.width : this.x + this.width);
ctx.clearRect(0, 0, canv.width, canv.height);
ctx.drawImage(this.image, this.x, this.cordinateFrameY, this.width, this.height, this.positionX, this.positionY, this.width, this.height);
}
moveLeft() {
this.positionX -= this.velocity;
this.cordinateFrameY = 580;
}
moveRight() {
this.positionX += this.velocity;
this.cordinateFrameY = 708;
}
moveTop() {
this.positionY -= this.velocity;
this.cordinateFrameY = 516;
}
moveDown() {
this.positionY += this.velocity;
this.cordinateFrameY = 644;
}
}
let knightSprite = new Image();
knightSprite.src = 'assets/knight_unit.png';
knightSprite.onload = function () {
let knight = new Unit({
height: 64,
width: 64,
ctx: canv.getContext("2d"),
image: knightSprite,
numberOfFrames: 9,
position: {
x: 0,
y: 0
},
velocity: 2
})
function animate() {
window.addEventListener('keydown', function (event) {
switch (event.key) {
case 'ArrowUp':
knight.moveTop();
break;
case 'ArrowDown':
knight.moveDown();;
break;
case 'ArrowLeft':
knight.moveLeft();
break;
case 'ArrowRight':
knight.moveRight();
break;
}
});
}
animate();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Animation</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="custom.js"></script>
</body>
</html>
Ответы (1 шт):
Автор решения: no more jalapenos
В этих слушателях обновляем объект
→ Ссылка
Вот это все:
...knight.moveTop();
knight.moveDown();...
нужно обновлять внутри игрового цикла.
Создаем объект отображающий зажатые кнопки
const pressedKeys = {
up: false,
down: false,
left: false,
right: false,
}
Указываем названия клавиш участвующих в передвижении
const upKeys = ['w', 'ArrowUp']
const downKeys = ['s', 'ArrowDown']
const leftKeys = ['a', 'ArrowLeft']
const rightKeys = ['d', 'ArrowRight']
Добавляем слушатели на нажатие и отжимание клавиш
addEventListener('keydown', keydownListener)
addEventListener('keyup', keyupListener)
В этих слушателях обновляем объект pressedKeys
function keydownListener ({ key }) {
if (upKeys.includes(key)) {
pressedKeys.up = true
} else if (downKeys.includes(key)) {
pressedKeys.down = true
} else if (rightKeys.includes(key)) {
pressedKeys.right = true
} else if (leftKeys.includes(key)) {
pressedKeys.left = true
}
}
function keyupListener ({ key }) {
if (upKeys.includes(key)) {
pressedKeys.up = false
} else if (downKeys.includes(key)) {
pressedKeys.down = false
} else if (rightKeys.includes(key)) {
pressedKeys.right = false
} else if (leftKeys.includes(key)) {
pressedKeys.left = false
}
}
Создаем объект который будет указывать направление
const direction = { x: 0, y: 0 }
Запускаем цикл
requestAnimationFrame(frameListener)
Внутри этого цикла обновляем направление
function frameListener() {
direction.x = Number(pressedKeys.right) - Number(pressedKeys.left)
direction.y = Number(pressedKeys.down) - Number(pressedKeys.up)
requestAnimationFrame(frameListener)
}
В итоге получится что-то такое
function frameListener() {
direction.x = Number(pressedKeys.right) - Number(pressedKeys.left)
direction.y = Number(pressedKeys.down) - Number(pressedKeys.up)
player.position.x += direction.x * player.speed
player.position.y += direction.y * player.speed
requestAnimationFrame(frameListener)
}
Сама идея взята отсюда и там же можно посмотреть как можно добавить плавность движению(если нужно).
const canvasElement = document.getElementById('canvas')
const context = canvasElement.getContext('2d')
const pressedKeys = {
up: false,
down: false,
left: false,
right: false,
}
const upKeys = ['w', 'ArrowUp']
const downKeys = ['s', 'ArrowDown']
const leftKeys = ['a', 'ArrowLeft']
const rightKeys = ['d', 'ArrowRight']
const direction = { x: 0, y: 0 }
const world = { width: 0, height: 0 }
const player = {
speed: 5,
position: { x: 0, y: 0 }
}
resizeListener()
addEventListener('resize', resizeListener)
addEventListener('keydown', keydownListener)
addEventListener('keyup', keyupListener)
requestAnimationFrame(frameListener)
function keydownListener ({ key }) {
if (upKeys.includes(key)) {
pressedKeys.up = true
} else if (downKeys.includes(key)) {
pressedKeys.down = true
} else if (rightKeys.includes(key)) {
pressedKeys.right = true
} else if (leftKeys.includes(key)) {
pressedKeys.left = true
}
}
function keyupListener ({ key }) {
if (upKeys.includes(key)) {
pressedKeys.up = false
} else if (downKeys.includes(key)) {
pressedKeys.down = false
} else if (rightKeys.includes(key)) {
pressedKeys.right = false
} else if (leftKeys.includes(key)) {
pressedKeys.left = false
}
}
function resizeListener() {
const pixelRatio = Math.max(1, Math.min(devicePixelRatio, 2))
const rect = canvasElement.getBoundingClientRect()
world.width = rect.width
world.height = rect.height
canvasElement.width = world.width * pixelRatio
canvasElement.height = world.height * pixelRatio
context.scale(pixelRatio, pixelRatio)
}
function frameListener() {
direction.x = Number(pressedKeys.right) - Number(pressedKeys.left)
direction.y = Number(pressedKeys.down) - Number(pressedKeys.up)
player.position.x += direction.x * player.speed
player.position.y += direction.y * player.speed
context.clearRect(0, 0, world.width, world.height)
context.fillRect(player.position.x, player.position.y, world.width * 0.05, world.width * 0.05)
requestAnimationFrame(frameListener)
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
display: block;
}
<canvas id="canvas"></canvas>