О чем этот пример
В игровой разработке отзывчивое управление — это основа. Часто для обработки ввода используют события клавиатуры, но в игровом цикле, особенно для постоянного движения персонажа, удобнее напрямую опрашивать состояние клавиш. В этой статье мы разберем, как с помощью метода `addKey()` в Phaser создать объект клавиши, состояние которой можно проверять в методе `update()`, что идеально подходит для плавного и предсказуемого игрового процесса.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
highlight1;
keySpace;
key5;
keyA;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('keyboard', 'assets/input/keyboard-opreem.png');
this.load.image('highlight', 'assets/input/key1.png');
}
create ()
{
this.drawKeyboard();
// Create a Key object we can poll directly.
// This is especially useful if you need to poll the key in a tight loop, such as for player controls.
this.keyA = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
this.key5 = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.FIVE);
this.keySpace = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
}
update ()
{
if (this.keyA.isDown)
{
console.log('A');
}
if (this.key5.isDown)
{
console.log('5');
}
if (this.keySpace.isDown)
{
console.log('spacebar');
}
}
drawKeyboard ()
{
this.add.image(0, 0, 'keyboard').setOrigin(0);
this.highlight1 = this.add.image(108, 112, 'highlight').setOrigin(0);
/*
var row = [1,2,3,4,5,6,7,8,9,0,'Minus','Plus','Backspace_Alt'];
x = 100;
y = 100;
spacing = 106;
for (var i = 0; i < row.length; i++)
{
var key = row[i];
this.add.image(x, y, 'keyboard', key);
x += spacing;
}
*/
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
backgroundColor: '#0072bc',
scene: Example
};
const game = new Phaser.Game(config);
Создание объектов клавиш
В Phaser управление клавиатурой централизовано в объекте this.input.keyboard. Метод .addKey() этого объекта позволяет создать специальный объект, представляющий конкретную клавишу. Этот объект можно сохранить в свойстве класса и использовать в любом месте программы, но чаще всего — в основном игровом цикле.
Код создает три таких объекта для клавиш A, 5 и Пробела. Константы с кодами клавиш находятся в объекте Phaser.Input.Keyboard.KeyCodes.
this.keyA = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
this.key5 = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.FIVE);
this.keySpace = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE);
Опрос состояния в игровом цикле
Сердце любой игры на Phaser — метод update(), который вызывается на каждом кадре. Здесь мы проверяем состояние созданных ранее объектов клавиш. У каждого объекта есть булево свойство .isDown, которое возвращает true, если клавиша нажата в данный момент.
Такой подход, в отличие от обработки событий keydown, гарантирует, что состояние клавиши проверяется каждый кадр, что критично для плавного перемещения или стрельбы. В примере состояние просто выводится в консоль.
if (this.keyA.isDown)
{
console.log('A');
}
if (this.key5.isDown)
{
console.log('5');
}
if (this.keySpace.isDown)
{
console.log('spacebar');
}
Преимущества прямого опроса
Почему addKey() и проверка .isDown в update() часто лучше событий?
1. **Предсказуемость и синхронизация:** Логика управления выполняется строго в игровом цикле, синхронно с физикой и отрисовкой. Это исключает задержки или "прострелы" кадров, которые могут возникать при асинхронных событиях.
2. **Идеально для непрерывных действий:** Проверка isDown идеально подходит для действий, которые должны длиться, пока зажата клавиша: бег, ускорение, прицеливание.
3. **Простота кода:** Не нужно создавать и удалять многочисленные обработчики событий. Состояние всех нужных клавиш проверяется в одном месте — в update().
Для одиночных действий (прыжок, использование предмета) лучше подходит событие on('down') у объекта клавиши, чтобы действие не повторялось, пока клавиша зажата.
Практическое применение: управление персонажем
Давайте применим этот подход для создания простого управления игроком. Предположим, у нас есть спрайт, которым нужно двигать стрелками.
Сначала создадим объекты клавиш в create(), а затем в update() будем менять скорость спрайта в зависимости от их состояния.
create() {
this.player = this.physics.add.sprite(400, 300, 'player');
this.cursors = this.input.keyboard.createCursorKeys(); // Альтернативный способ для стрелок
// Или так, если нужен больший контроль:
this.keyLeft = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT);
this.keyRight = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT);
}
update() {
const speed = 200;
this.player.setVelocityX(0); // Сбрасываем скорость каждый кадр
if (this.cursors.left.isDown || this.keyLeft?.isDown) {
this.player.setVelocityX(-speed);
}
else if (this.cursors.right.isDown || this.keyRight?.isDown) {
this.player.setVelocityX(speed);
}
}
Что попробовать дальше
Метод addKey() — это мощный и эффективный инструмент для создания отзывчивого игрового управления через прямое опрос состояния клавиш. Он становится незаменимым, когда важна непрерывность и синхронизация действий с игровым циклом.
**Идеи для экспериментов:**
1. Создайте комбинацию клавиш (например, SHIFT + A), проверяя состояние двух объектов одновременно в update().
2. Реализуйте "ускорение" при долгом удержании клавиши, увеличивая скорость персонажа со временем.
3. Сравните производительность и отзывчивость управления через addKey() в update() и через обработчики событий on('down') в сценарии быстрого таппинга.
