О чем этот пример
Векторная математика — основа динамики в играх. Понимание операций над векторами, таких как нахождение противоположного направления, критически важно для реализации движения, отражений и поведения ИИ. В этой статье мы разберем простой, но наглядный пример, показывающий, как работает метод `negate()` у вектора `Phaser.Math.Vector2` в реальном времени, реагируя на движение курсора. Это поможет вам интуитивно понять, как легко менять направление вектора в своих проектах.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics({ fillStyle: { color: 0x2266aa } });
const point = new Phaser.Math.Vector2(450, 350);
this.input.on('pointermove', pointer =>
{
point.x = pointer.x - 400;
point.y = pointer.y - 300;
redraw();
});
redraw();
function redraw ()
{
graphics.clear();
// draw as if 400/300 was the center
graphics.fillPoint(400 + point.x, 300 + point.y, 15);
point.negate();
graphics.fillStyle(0x00aa00);
graphics.fillPoint(400 + point.x, 300 + point.y, 15);
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что делает этот пример?
Программа создает интерактивную сцену с двумя точками. Исходная (синяя) точка следует за курсором мыши, но относительно смещенного центра. Ее противоположная (зеленая) точка мгновенно вычисляется методом negate() и отображается симметрично относительно центра экрана (координаты 400, 300). Движение мыши заставляет обе точки перемещаться зеркально.
Это наглядно демонстрирует, что операция отрицания вектора (negate) создает новый вектор с теми же длинами (модулями), но противоположным направлением по обеим осям.
Разбор структуры кода
Код представляет собой стандартную сцену Phaser. В методе create() инициализируется графика, создается векторная точка и подписывается на событие движения указателя.
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics({ fillStyle: { color: 0x2266aa } });
const point = new Phaser.Math.Vector2(450, 350);
this.input.on('pointermove', pointer =>
{
point.x = pointer.x - 400;
point.y = pointer.y - 300;
redraw();
});
redraw();
// ... функция redraw
}
}
Конфигурация игры задает окно 800x600 пикселей и связывает сцену.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Сердце программы: функция redraw()
Вся логика отрисовки инкапсулирована во вспомогательной функции redraw(). Она вызывается при инициализации и при каждом движении мыши.
function redraw ()
{
graphics.clear();
// draw as if 400/300 was the center
graphics.fillPoint(400 + point.x, 300 + point.y, 15);
point.negate();
graphics.fillStyle(0x00aa00);
graphics.fillPoint(400 + point.x, 300 + point.y, 15);
}
Ключевые шаги:
1. graphics.clear(): Очищает холст от предыдущего кадра.
2. graphics.fillPoint(400 + point.x, 300 + point.y, 15): Рисует синюю точку. Координаты вектора point изначально рассчитаны относительно центра (400,300), поэтому для отрисовки на экране мы прибавляем этот центр обратно.
3. point.negate(): **Это ключевой вызов.** Метод модифицирует сам вектор point, меняя знак его компонентов `xиyна противоположный. Теперьpoint` хранит уже отрицательные значения.
4. Смена стиля и отрисовка зеленой точки с новыми (отрицательными) координатами, также смещенными к центру. В результате она всегда находится зеркально синей точке относительно центра (400,300).
Важные детали и практические аспекты
Обратите внимание на несколько нюансов, важных для практического применения:
* **Изменение на месте:** Метод negate() не создает новый вектор, а изменяет существующий. Если исходный вектор нужно сохранить, следует сначала скопировать его с помощью clone().
* **Относительные координаты:** Логика примера построена на работе в относительной системе координат с центром в (400,300). Вектор point хранит смещение от этого центра. Это распространенный подход для упрощения геометрических расчетов.
* **Событийный цикл:** Функция redraw() вызывается в обработчике pointermove, обеспечивая плавную и мгновенную реакцию на действия пользователя. Это основа для любого интерактивного поведения в Phaser.
Пример использования negate() для отражения скорости мяча от стенки:
// При столкновении с горизонтальной стенкой инвертируем вертикальную скорость
ball.body.velocity.y *= -1;
// То же самое, но через вектор и метод negate()
ball.body.velocity.y = -ball.body.velocity.y;
// Если нужно инвертировать весь вектор скорости
ball.body.velocity.negate();
Что попробовать дальше
Метод negate() — это мощный и простой инструмент для работы с направлениями. Он мгновенно превращает вектор в его противоположность, что незаменимо для расчета отскоков, направления взгляда врага на игрока или зеркальных трансформаций. Попробуйте поэкспериментировать с примером: измените центр симметрии, добавьте третью точку, которая использует negate() только по одной оси (например, point.x = -point.x), или привяжите эту логику к скорости спрайта, чтобы управлять его движением с помощью мыши.
