О чем этот пример
Интерактивное рисование линий — это мощный инструмент для создания игровых механик: от построения траекторий для снарядов до инструментов редактора уровней прямо в игре. В этом примере мы разберем, как использовать графические объекты Phaser (`Graphics`) для отрисовки линии, которая следует за движением курсора, реализуя эффект «рисования по холсту». Вы научитесь работать с геометрическими объектами, обрабатывать события ввода и динамически обновлять графику.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
points = [];
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('pic', 'assets/tests/sw.png');
}
create ()
{
this.add.image(0, 0, 'pic').setOrigin(0).setAlpha(0.8);
const sketch = this.add.graphics();
sketch.lineStyle(2, 0x00ff00);
// The graphics instance you draw on
const graphics = this.add.graphics();
const line = new Phaser.Geom.Line();
this.input.on('pointerdown', pointer =>
{
line.setTo(pointer.x, pointer.y, pointer.x, pointer.y);
});
this.input.on('pointerup', pointer =>
{
sketch.strokeLineShape(line);
graphics.clear();
});
this.input.on('pointermove', pointer =>
{
if (!pointer.isDown)
{
return;
}
line.x2 = pointer.x;
line.y2 = pointer.y;
graphics.clear();
graphics.lineStyle(2, 0x00ff00);
graphics.strokeLineShape(line);
});
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и создание графических объектов
В методе create() инициализируются ключевые объекты для рисования. Основная картинка добавляется как фон для наглядности.
Создаются два графических объекта (Graphics): sketch и graphics. Первый будет хранить финальный, «зафиксированный» рисунок, а второй — временную линию, которая рисуется в процессе перемещения курсора.
const sketch = this.add.graphics();
sketch.lineStyle(2, 0x00ff00);
const graphics = this.add.graphics();
Также создается геометрический объект Phaser.Geom.Line, который будет хранить координаты начала и конца текущей линии.
const line = new Phaser.Geom.Line();
Обработка нажатия: Начало новой линии
При событии pointerdown (нажатие кнопки мыши или касание) линия инициализируется. Ее начальная и конечная точки устанавливаются в одно и то же место — текущую позицию курсора. Это точка начала рисования.
this.input.on('pointerdown', pointer => {
line.setTo(pointer.x, pointer.y, pointer.x, pointer.y);
});
Метод setTo объекта Phaser.Geom.Line принимает четыре аргумента: x1, y1, x2, y2.
Обработка движения: Рисование временной линии
Событие pointermove срабатывает при каждом движении курсора. Однако рисовать нужно только тогда, когда кнопка зажата. Для этого используется проверка pointer.isDown.
Если кнопка нажата, обновляются конечные координаты линии (x2, y2). Перед отрисовкой новой линии временный графический объект graphics очищается методом clear(), чтобы стереть предыдущий кадр. Затем на нем заново рисуется обновленная линия.
this.input.on('pointermove', pointer => {
if (!pointer.isDown) {
return;
}
line.x2 = pointer.x;
line.y2 = pointer.y;
graphics.clear();
graphics.lineStyle(2, 0x00ff00);
graphics.strokeLineShape(line);
});
Важно: Стиль линии (lineStyle) задается каждый раз, так как метод clear() сбрасывает все параметры рисования для объекта graphics.
Обработка отпускания: Фиксация результата
Когда пользователь отпускает кнопку мыши (pointerup), текущая временная линия должна быть перенесена на постоянный холст sketch и очищена из временного буфера.
this.input.on('pointerup', pointer => {
sketch.strokeLineShape(line);
graphics.clear();
});
Метод strokeLineShape объекта sketch рисует финальную линию по координатам из объекта line. После этого временный объект graphics очищается, убирая линию-призрак с экрана. Основной рисунок на объекте sketch при этом сохраняется.
Что попробовать дальше
Вы создали интерактивный инструмент для рисования линий, используя события ввода и два слоя графики в Phaser. Этот паттерн — временный буфер (graphics) и постоянный холст (sketch) — отлично подходит для многих механик, требующих предварительного отображения (например, прицеливания или планирования пути). Для экспериментов попробуйте: изменить цвет и толщину линии в зависимости от скорости движения мыши, реализовать рисование не линией, а цепочкой точек (fillCircleShape), или добавить кнопку для очистки всего холста sketch.
