О чем этот пример
Визуализация случайных точек на линии — это не просто демонстрация математики, а мощный инструмент для создания игровых механик. Вы можете использовать этот подход для расстановки монет на трассе, определения траектории полёта снарядов или случайного появления врагов вдоль маршрута. В этой статье мы разберём пример из официальной документации Phaser и покажем, как метод `getRandomPoint()` объекта `Phaser.Geom.Line` может оживить вашу игру.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
index = 0;
points;
graphics;
line;
create ()
{
this.line = new Phaser.Geom.Line(100, 500, 700, 100);
this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0xff00ff }, fillStyle: { color: 0xff0000 }});
this.points = [];
for (let i = 0; i < 25; i++)
{
// if we omit a parameter, new Point instance will be created and returned
this.points.push(this.line.getRandomPoint());
}
}
update ()
{
this.index = ++this.index % 25;
// we can also supply an instance of Point that will be modified
this.line.getRandomPoint(this.points[this.index]);
this.graphics.clear();
this.graphics.strokeLineShape(this.line);
for (let i = 0; i < 25; i++)
{
const p = this.points[i];
this.graphics.fillRect(p.x - 4, p.y - 4, 8, 8);
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание линии и подготовка данных
Всё начинается с определения линии и подготовки массива для хранения точек. Линия создаётся между двумя координатами, а графический контекст (graphics) настраивается для отрисовки.
this.line = new Phaser.Geom.Line(100, 500, 700, 100);
this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0xff00ff }, fillStyle: { color: 0xff0000 }});
this.points = [];
Здесь мы создаём линию от точки (100, 500) до (700, 100). Объект graphics будет рисовать саму линию розовым цветом и точки красным квадратиком. Массив points изначально пуст — в него мы будем складывать сгенерированные точки.
Генерация начального набора точек
Перед началом цикла игры нужно создать начальный набор из 25 случайных точек на линии. Для этого в цикле вызывается метод getRandomPoint().
for (let i = 0; i < 25; i++)
{
// если не передавать параметр, метод создаст и вернёт новый экземпляр Point
this.points.push(this.line.getRandomPoint());
}
Ключевой момент: если вызвать getRandomPoint() без аргументов, метод сам создаст новый объект Phaser.Geom.Point с случайными координатами на линии и вернёт его. Это удобно для быстрой инициализации массива.
Анимация и обновление точек
В методе update() происходит магия анимации. Каждый кадр мы обновляем координаты одной из точек, перерисовывая графику.
this.index = ++this.index % 25;
// мы также можем передать экземпляр Point, который будет изменён
this.line.getRandomPoint(this.points[this.index]);
Переменная index циклически перебирает индексы массива от 0 до 24. Вторая форма вызова getRandomPoint(point) принимает существующий объект Point и модифицирует его координаты, помещая в новую случайную позицию на той же линии. Это эффективно, так как не создаёт новых объектов в памяти каждый кадр.
Отрисовка линии и точек
После обновления данных необходимо очистить холст и заново нарисовать линию со всеми точками.
this.graphics.clear();
this.graphics.strokeLineShape(this.line);
for (let i = 0; i < 25; i++)
{
const p = this.points[i];
this.graphics.fillRect(p.x - 4, p.y - 4, 8, 8);
}
Метод clear() стирает всё, что было нарисовано этим графическим объектом. Затем strokeLineShape(this.line) рисует контур линии. В цикле для каждой точки рисуется закрашенный квадрат с центром в её координатах (смещение на -4 по осям и размер 8x8 даёт квадрат 8 на 8 пикселей).
Практическое применение в играх
Как использовать эту технику не в демо, а в реальной игре? Вот несколько идей:
* **Маршруты патрулирования:** Задайте линию как путь для врага. Каждые несколько секунд обновляйте его целевую точку с помощью getRandomPoint(), создавая непредсказуемый патрульный маршрут.
* **Разброс снарядов:** При стрельбе из дробовика задайте основную линию траектории. Затем сгенерируйте несколько случайных точек на ней или рядом (используя смещение) для определения направления каждого дробина.
* **Генерация ресурсов:** Разместите линию вдоль горного хребта или реки. В начале уровня сгенерируйте на ней случайные точки — это будут места появления руды или рыбы.
// Пример: создание цели для патруля врага
update() {
if (this.patrolTimer <= 0) {
// Обновляем целевую точку патруля раз в 2 секунды
this.line.getRandomPoint(this.enemy.target);
this.patrolTimer = 2000;
}
this.patrolTimer -= this.game.loop.delta;
}
Что попробовать дальше
Метод Phaser.Geom.Line.getRandomPoint() — это элегантный и производительный способ работы со случайными позициями на отрезке. Он позволяет избежать лишних вычислений и создания объектов, что критично для производительности игры. Для экспериментов попробуйте: анимировать не одну, а несколько точек одновременно с разной скоростью; использовать не прямую, а ломаную линию, разбив её на сегменты; или применить этот принцип к другим геометрическим объектам Phaser, например, для получения случайной точки внутри прямоугольника (Phaser.Geom.Rectangle.getRandomPoint).
