О чем этот пример
Интерактивность — основа вовлечённости в игре. Понимание того, как обрабатывать действия игрока (клики, тапы) — первый шаг к созданию отзывчивого геймплея. В этой статье мы разберём простой, но мощный механизм Phaser — Pointer Events, который позволяет реагировать на нажатия мыши или касания экрана. Вы научитесь получать координаты клика, создавать объекты по ним и в реальном времени отслеживать состояние указателя, что является фундаментом для множества игровых механик: от стрельбы до управления интерфейсом.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
text;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.spritesheet('balls', 'assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });
}
create ()
{
this.text = this.add.text(10, 10, '', { font: '16px Courier', fill: '#00ff00' });
this.input.on('pointerdown', function (pointer)
{
console.log(this.game.loop.frame, 'down B');
this.add.image(pointer.x, pointer.y, 'balls', Phaser.Math.Between(0, 5));
}, this);
}
update ()
{
const p = this.input.activePointer;
this.text.setText([
`x: ${p.x}`,
`y: ${p.y}`,
`duration: ${p.getDuration()}`
]);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Настройка сцены и загрузка ассетов
Работа начинается с базовой структуры класса сцены Phaser. В методе preload мы загружаем спрайтшит — набор кадров (спрайтов), упакованный в одно изображение. Это эффективный способ работы с множеством похожих объектов, например, с разноцветными шарами.
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.spritesheet('balls', 'assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });
Ключевой параметр frameWidth и frameHeight указывает Phaser, как нарезать большое изображение на отдельные кадры. В данном случае мы ожидаем 6 кадров (шаров разного цвета), каждый размером 17x17 пикселей.
Обработка события клика (pointerdown)
Вся магия интерактивности происходит в методе create. Мы создаём текстовый объект для отладки и, что важнее, подписываемся на глобальное событие pointerdown через this.input.on. Это событие срабатывает при нажатии кнопки мыши или касании сенсорного экрана в любом месте игрового поля.
this.input.on('pointerdown', function (pointer) {
console.log(this.game.loop.frame, 'down B');
this.add.image(pointer.x, pointer.y, 'balls', Phaser.Math.Between(0, 5));
}, this);
Обратите внимание на три важные детали:
1. **Параметр `pointer`**: он автоматически передаётся в функцию-обработчик и содержит всю информацию о событии, включая координаты `x` и `y`.
2. **`this.add.image`**: используя координаты из `pointer`, мы создаём новый спрайт (изображение) прямо в точке клика. Ключ `'balls'` указывает на загруженный спрайтшит.
3. **`Phaser.Math.Between(0, 5)`**: эта функция случайным образом выбирает один из шести кадров (от 0 до 5) из спрайтшита, создавая разноцветные шары.
4. **Контекст `this`**: последний аргумент `, this` в вызове `on` гарантирует, что внутри функции-обработчика `this` будет ссылаться на текущую сцену (экземпляр `Example`), что позволяет нам вызывать `this.add.image`.
Отслеживание активного указателя в реальном времени
Чтобы дать игроку визуальную обратную связь, полезно показывать состояние указателя. Это делается в методе update, который вызывается на каждом кадре игры.
const p = this.input.activePointer;
this.text.setText([
`x: ${p.x}`,
`y: ${p.y}`,
`duration: ${p.getDuration()}`
]);
Мы получаем ссылку на активный указатель (activePointer) и обновляем текстовое поле:
- **p.x / p.y**: текущие координаты указателя.
- **p.getDuration()**: время в миллисекундах, прошедшее с момента начала текущего нажатия (если кнопка нажата). Если кнопка отпущена, метод возвращает время, прошедшее с момента последнего отпускания. Это крайне полезно для реализации механик, зависящих от длительности нажатия (например, зарядка выстрела).
Конфигурация и запуск игры
Финальный шаг — создание и конфигурация экземпляра игры Phaser.Game. В объекте конфигурации мы указываем базовые настройки.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
- type: Phaser.AUTO позволяет движку самому выбрать рендерер (WebGL или Canvas).
- parent: ID HTML-элемента, в который будет встроен canvas игры.
- width / height: размер игрового поля.
- scene: класс основной сцены, которая будет запущена сразу после инициализации игры.
Что попробовать дальше
Использование pointerdown и activePointer открывает дверь к созданию базовой интерактивности в вашей игре на Phaser. Вы можете не только создавать объекты, но и начинать перемещение персонажа, активировать способности или выбирать элементы интерфейса.
**Идеи для экспериментов:**
1. Измените обработчик pointerdown так, чтобы шар не просто появлялся, а "выстреливал" из центра экрана в точку клика, используя физический движок Arcade Physics (this.physics.add.image и setVelocity).
2. Реализуйте перетаскивание: подпишитесь также на события pointermove и pointerup, чтобы перемещать созданный шар, пока кнопка нажата.
3. Используйте getDuration() для создания механики: чем дольше удерживается клик, тем больше или быстрее создаваемый шар.
