О чем этот пример
Управление с помощью стрелок — основа многих игр. Но что, если вам нужно знать не просто факт нажатия, а сколько времени игрок удерживает кнопку? Это может пригодиться для зарядки прыжка, ускорения или активации особых способностей. В этой статье мы разберем официальный пример Phaser, который показывает, как использовать объект `Key` для точного замера длительности нажатий. Вы научитесь получать временные метки и рассчитывать продолжительность удержания клавиши, что откроет новые возможности для геймдизайна.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
downKeyDebug;
upKeyDebug;
rightKeyDebug;
leftKeyDebug;
player;
cursors;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('elephant', 'assets/sprites/elephant.png');
}
create ()
{
this.cursors = this.input.keyboard.createCursorKeys();
this.player = this.physics.add.image(400, 300, 'elephant');
this.player.setCollideWorldBounds(true);
this.leftKeyDebug = this.add.text(10, 300, 'Left', { font: '16px Courier', fill: '#00ff00' });
this.rightKeyDebug = this.add.text(570, 300, 'Right', { font: '16px Courier', fill: '#00ff00' });
this.upKeyDebug = this.add.text(300, 10, 'Up', { font: '16px Courier', fill: '#00ff00' });
this.downKeyDebug = this.add.text(300, 530, 'Down', { font: '16px Courier', fill: '#00ff00' });
}
update ()
{
this.player.setVelocity(0);
if (this.cursors.left.isDown)
{
this.player.setVelocityX(-300);
}
else if (this.cursors.right.isDown)
{
this.player.setVelocityX(300);
}
if (this.cursors.up.isDown)
{
this.player.setVelocityY(-300);
}
else if (this.cursors.down.isDown)
{
this.player.setVelocityY(300);
}
this.leftKeyDebug.setText([
`Left: ${this.cursors.left.isDown}`,
`down: ${this.cursors.left.timeDown}`,
`up: ${this.cursors.left.timeUp}`,
`duration: ${(this.cursors.left.isDown) ? this.cursors.left.getDuration() : this.cursors.left.duration}`
]);
this.rightKeyDebug.setText([
`Right: ${this.cursors.right.isDown}`,
`down: ${this.cursors.right.timeDown}`,
`up: ${this.cursors.right.timeUp}`,
`duration: ${(this.cursors.right.isDown) ? this.cursors.right.getDuration() : this.cursors.right.duration}`
]);
this.upKeyDebug.setText([
`Up: ${this.cursors.up.isDown}`,
`down: ${this.cursors.up.timeDown}`,
`up: ${this.cursors.up.timeUp}`,
`duration: ${(this.cursors.up.isDown) ? this.cursors.up.getDuration() : this.cursors.up.duration}`
]);
this.downKeyDebug.setText([
`Down: ${this.cursors.down.isDown}`,
`down: ${this.cursors.down.timeDown}`,
`up: ${this.cursors.down.timeUp}`,
`duration: ${(this.cursors.down.isDown) ? this.cursors.down.getDuration() : this.cursors.down.duration}`
]);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
backgroundColor: '#0072bc',
width: 800,
height: 600,
physics: {
default: 'arcade',
arcade: {
debug: true
}
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка сцены и создание объектов
В методе preload() загружается спрайт, а в create() происходит основная инициализация. Ключевой момент — создание объекта cursors, который представляет собой группу из четырех объектов Key (для стрелок). Каждый такой объект содержит свойства для работы со временем.
Также создается физический спрайт игрока и четыре текстовых объекта для отладки, которые будут выводить информацию о состоянии каждой клавиши.
create ()
{
this.cursors = this.input.keyboard.createCursorKeys();
this.player = this.physics.add.image(400, 300, 'elephant');
this.player.setCollideWorldBounds(true);
// Создание текстовых полей для отладки
this.leftKeyDebug = this.add.text(10, 300, 'Left', { font: '16px Courier', fill: '#00ff00' });
// ... аналогично для rightKeyDebug, upKeyDebug, downKeyDebug
}
Базовое движение и свойства времени
В методе update() реализовано стандартное движение игрока с помощью setVelocity(). Логика проста: если нажата стрелка, задается скорость по соответствующей оси.
Объект Key (например, this.cursors.left) предоставляет несколько полезных свойств, связанных со временем:
* isDown — логический флаг, нажата ли клавиша в данный момент.
* timeDown — временная метка (в миллисекундах), когда клавиша была нажата в последний раз.
* timeUp — временная метка, когда клавиша была отпущена в последний раз.
* duration — продолжительность (в миллисекундах), сколько клавиша была отпущена. Актуально, когда isDown равно false.
if (this.cursors.left.isDown)
{
this.player.setVelocityX(-300);
}
// ... обработка остальных направлений
Измерение длительности нажатия
Самая интересная часть — расчет, сколько времени клавиша удерживается нажатой. Для этого у объекта Key есть метод getDuration(). Он возвращает количество миллисекунд, прошедших с момента последнего нажатия (timeDown).
В примере используется тернарный оператор для выбора отображаемого значения: если клавиша нажата сейчас, вызывается getDuration(), чтобы получить актуальную длительность удержания. Если клавиша отпущена, отображается свойство duration, которое хранит, как долго она была нажата в последний раз.
this.leftKeyDebug.setText([
`Left: ${this.cursors.left.isDown}`,
`down: ${this.cursors.left.timeDown}`,
`up: ${this.cursors.left.timeUp}`,
`duration: ${(this.cursors.left.isDown) ? this.cursors.left.getDuration() : this.cursors.left.duration}`
]);
Практическое применение в играх
Получение точного времени нажатия открывает множество игровых механик. Вот несколько идей: 1. **Прыжок с переменной высотой:** Чем дольше игрок удерживает клавишу прыжка, тем выше и дальше прыжок. 2. **Заряжаемое оружие или атака:** Длительность нажатия определяет мощность выстрела или область эффекта. 3. **Бег или ускорение:** Персонаж начинает с обычной скорости, а после удержания клавиши движения 1-2 секунды переходит на спринт. 4. **Тайминговые события в диалогах или QTE:** Проверка, удержал ли игрок клавишу достаточно долго для успешного действия.
Для реализации таких механик достаточно в update() проверять значение, возвращаемое getDuration(), и на его основе менять параметры игрового объекта.
Что попробовать дальше
Использование временных свойств объекта Key в Phaser — это мощный инструмент, выходящий за рамки простого «нажато/отпущено». Он позволяет создавать более глубокие и отзывчивые игровые механики, основанные на времени реакции игрока.
Для экспериментов попробуйте изменить пример: добавьте визуальный индикатор заряда (например, растущую полоску), который зависит от getDuration(). Или реализуйте систему комбо, где следующее действие должно быть выполнено в строго определенный временной интервал после предыдущего нажатия, используя свойства timeDown и timeUp для расчетов.
