О чем этот пример
В игровой механике часто требуется сравнение форм и расстояний. Знание периметра (длины) геометрической фигуры позволяет, например, рассчитать путь движения объекта или проверить столкновение по границе. В этом примере мы наглядно вычислим длину эллипса и сравним её с периметром квадрата и длиной окружности, визуализируя результаты в реальном времени. Этот приём полезен для создания динамических границ, траекторий движения или любых расчётов, где важна точная длина кривой, а не просто площадь фигуры.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics();
const ellipse = new Phaser.Geom.Ellipse(400, 300, 250, 150);
const text = this.add.text(400, 50, '');
this.input.on('pointermove', pointer =>
{
ellipse.setSize(pointer.x, pointer.y);
redraw();
});
redraw();
function redraw ()
{
graphics.clear();
const circumference = Phaser.Geom.Ellipse.Circumference(ellipse);
// calculate side size for a square with the same circumference
const squareSide = circumference / 4;
graphics.lineStyle(2, 0x0000aa);
graphics.strokeRect(400 - squareSide / 2, 300 - squareSide / 2, squareSide, squareSide);
// calculate radius for a circle with the same circumference
const circleRadius = circumference / (2 * Math.PI);
graphics.lineStyle(2, 0x00aa00);
graphics.strokeCircle(400, 300, circleRadius);
graphics.lineStyle(2, 0x00aaaa);
graphics.strokeEllipseShape(ellipse);
text.setText(`Ellipse Circumference: ${circumference}`);
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание основы: эллипс и обработка ввода
В начале сцены create мы создаем графический объект graphics для рисования, экземпляр эллипса Phaser.Geom.Ellipse с центром в точке (400, 300) и начальными радиусами, а также текстовый объект для вывода информации.
Ключевой момент — обработка события перемещения указателя (pointermove). При каждом движении мыши размеры эллипса обновляются в соответствии с координатами курсора, после чего вызывается функция redraw для перерисовки всей сцены. Это позволяет интерактивно менять форму и сразу видеть изменения в расчётах.
const graphics = this.add.graphics();
const ellipse = new Phaser.Geom.Ellipse(400, 300, 250, 150);
const text = this.add.text(400, 50, '');
this.input.on('pointermove', pointer => {
ellipse.setSize(pointer.x, pointer.y);
redraw();
});
Расчёт периметра эллипса
Функция redraw начинается с очистки графики graphics.clear(). Затем мы используем статический метод Phaser.Geom.Ellipse.Circumference, чтобы получить длину (периметр) текущего эллипса. Важно понимать, что в Phaser под "circumference" подразумевается именно длина замкнутой кривой, а не площадь.
Это значение сохраняется в переменной circumference. Оно будет основой для всех дальнейших сравнений с другими фигурами.
const circumference = Phaser.Geom.Ellipse.Circumference(ellipse);
Сравнение с квадратом
Чтобы наглядно сравнить длину эллипса с периметром квадрата, мы вычисляем сторону квадрата, который имел бы такой же периметр. Для этого длину эллипса делим на 4 (поскольку у квадрата четыре равные стороны).
Затем мы рисуем этот квадрат с центром, совпадающим с центром эллипса. Используется синий цвет контура (0x0000aa). Если эллипс вытянут, его длина будет больше, и квадрат станет крупнее, что сразу видно на экране.
const squareSide = circumference / 4;
graphics.lineStyle(2, 0x0000aa);
graphics.strokeRect(400 - squareSide / 2, 300 - squareSide / 2, squareSide, squareSide);
Сравнение с окружностью
Аналогично мы сравниваем длину эллипса с длиной окружности (её периметром). Из формулы длины окружности C = 2 * π * R выражаем радиус: R = C / (2 * π). Используя вычисленную длину эллипса как `C`, мы получаем радиус воображаемой окружности с таким же периметром.
Эта окружность рисуется зелёным контуром (0x00aa00) с тем же центром, что и эллипс. Это сравнение особенно наглядно, когда эллипс близок к кругу — тогда окружность почти совпадёт с его границей.
const circleRadius = circumference / (2 * Math.PI);
graphics.lineStyle(2, 0x00aa00);
graphics.strokeCircle(400, 300, circleRadius);
Визуализация эллипса и вывод данных
После рисования сравнений мы отображаем сам исходный эллипс бирюзовым цветом (0x00aaaa), используя метод strokeEllipseShape. Это позволяет видеть, как меняется форма при взаимодействии.
Наконец, мы обновляем текстовый объект, выводя в него актуальное числовое значение длины эллипса. Это даёт точную цифру для анализа.
graphics.lineStyle(2, 0x00aaaa);
graphics.strokeEllipseShape(ellipse);
text.setText(`Ellipse Circumference: ${circumference}`);
Что попробовать дальше
Этот пример демонстрирует, как Phaser позволяет не только рисовать геометрические фигуры, но и проводить с ними практические математические расчёты. Знание длины кривой открывает возможности для игровой логики: от расчёта времени движения по сложной траектории до создания динамических барьеров, длина которых влияет на геймплей.
Для экспериментов попробуйте зафиксировать один из размеров эллипса и посмотреть, как меняется длина при изменении другого. Или используйте полученное значение circumference для контроля скорости объекта, движущегося по границе эллипса, — чтобы полный круг занимал строго определённое время.
