- Баллы
- 76
- Имя в Minecraft
- SiRiuS_OSiRiuS
Векторное Программирование Для Чайников
Что такое вектор и как их понимание поможет вам в разработке плагинов
--------------------------------------------------------------------------------------------------------------------------------------
ЧТО ТАКОЕ ВЕКТОР?
Вектор представляется длиной и направлением и всегда описывает движение из точки А в точку Б. Многие из вас наверняка уже слышали о векторах или видели какие-то странные стрелки, обозначающие их. Давайте осмотрим векторы в Spigot.
ВЕКТОР В SPIGOT
В Spigot класс Vector можно найти в пакете org.bukkit.util. Его можно создать двумя способами:
Java:
Vector v = new Vector(); // Создаёт вектор с длиной 0 и БЕЗ направления
Vector v = new Vector(x, y, z); // Создаёт вектор с указанными направлением и длиной
В ЧЁМ СМЫСЛ ВЕКТОРА В SPIGOT?
Всякий раз, когда перемещается сущность или нужно рассчитать цель, которую вы ищете, используется вектор. К концу статьи вы научитесь выполнять обе вещи.
Давайте объясним возможные вычисления.
* Синяя стрелка является результатом вычисления
СЛОЖЕНИЕ
Эта операция очень банальна. У вас есть одна стрелка, и вы добавляете её к другой. Давайте запишем это!
Java:
Vector first = new Vector(1, 3, 2);
Vector second = new Vector(3, -1, 4);
// Давайте сложим их!
Vector result = first.add(second); // В результате у нас получился вектор с параметрами 4, 2, 6
УМНОЖЕНИЕ
Ещё одна простая (и существенная) операция. Просто умножайте длину вектора. Когда полученное число ОТРИЦАТЕЛЬНОЕ, вектор меняет направление.
Java:
Vector v = new Vector(3, 4, 2);
Vector result1 = v.multiply(2); // Вектор с параметрами 6, 8, 4
Vector result2 = v.multiply(-1); // Вектор с параметрами -3, -4, -2
НОРМАЛИЗАЦИЯ
Устанавливает длину вектора на 1. К примеру, у вас есть вектор (3, 3, 3). Значит, его длина √( (3 * 3) + (3 * 3) + (3 * 3) ) = √(27) = 5.19.
Теперь нормализации надо разделить ожидаемую длину вектора на его нынешнюю длину, чтобы получить нормализованный вектор. Так нормализация вызывает метод .multiply(1/5.19). В результате мы получаем вектор (0.57, 0.57, 0.57).
Java:
Vector v = new Vector(3, 3, 3);
Vector result = v.normalize(); // Возвращает вектор с длиной 1 и движением 0.57, 0.57, 0.57

ВЕКТОРНОЕ ПРОИЗВЕДЕНИЕ
Эта операция возвращает вектор, ортогональный двум предыдущим. Его длина — это площадь голубого параллелограмма. Это можно использовать для примерного сравнения двух векторов (например, когда нацеливаешься на игрока).
Например:
Java:
Vector first = new Vector(1, 2, 3);
Vector second = new Vector(-7, 8, 9);
Vector result = first.crossProduct(second); // Вернёт вектор с параметрами -6, -30, 22
СРЕДНЕЕ АРИФМЕТИЧЕСКОЕ
Это легко! Берёшь один вектор, складываешь с другим и делишь результат на 2. И получаешь среднее арифметическое!
У вас есть два вектора — чёрный и оранжевый. Вы складываете их и получаете зелёный вектор. Вы делите зелёный вектор на 2 (или умножаете на 0.5) и получаете среднее арифметическое.
Java:
Vector first = new Vector(1, 3, 4);
Vector second = new Vector(4, 3, 1);
Vector midpoint1 = first.midpoint(second); // Вектор с параметрами 2.5, 3, 2.5
Vector midpoint2 = first.add(second).multiply(0.5); // Вектор с параметрами 2.5, 3, 2.5
ПРИМЕР
Давайте проверим, смотрит ли игрок на какую-то локацию!
Java:
public boolean doesPlayerTarget(Player p, Location target) {
// p — это ваш игрок
// target — это локация, куда игрок должен смотреть
// Проверяем, находятся ли они в одном мире
if(!target.getWorld().equals(p.getWorld())) return false;
// Давайте начнём!
// Получаем локацию головы игрока
Location head = p.getLocation().add(0, p.getEyeHeight(), 0);
// Получаем направление взгляда игрока в виде вектора и
// сокращаем его до длины 1, используя normalize()
Vector look = p.getLocation().getDirection().normalize();
// Получаем направление цели от игрока, вычитая из его локации цель
// Естественно, снова используем normalize(), чтобы сократить значение
Vector direction = head.subtract(target).toVector().normalize();
// Давайте сконструируем наше векторное умножение. Когда длина векторного умножения 0, игрок
// определённо смотрит на нашу локацию цели
// почему? потому что тогда площадь параллелограмма, показанного выше, будет равно 0 :)
Vector cp = direction.crossProduct(look);
// Давайте получим длину из вектора
double length = cp.length();
// Если длина больше 0.1, игрок явно
// Не смотрит на нашу локацию.
return (length < 0.1);
}
Последнее редактирование:
