Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Стартап [ПЕРЕВОД] Векторное Программирование Для Чайников

Dexel

Активный участник
Пользователь
Баллы
76
Имя в Minecraft
SiRiuS_OSiRiuS
2400179-vector.png

Векторное Программирование Для Чайников
Что такое вектор и как их понимание поможет вам в разработке плагинов
--------------------------------------------------------------------------------------------------------------------------------------
​

ЧТО ТАКОЕ ВЕКТОР?
Вектор представляется длиной и направлением и всегда описывает движение из точки А в точку Б. Многие из вас наверняка уже слышали о векторах или видели какие-то странные стрелки, обозначающие их. Давайте осмотрим векторы в Spigot.

ВЕКТОР В SPIGOT

В Spigot класс Vector можно найти в пакете org.bukkit.util. Его можно создать двумя способами:
Java:
Vector v = new Vector();  // Создаёт вектор с длиной 0 и БЕЗ направления
Vector v = new Vector(x, y, z);  // Создаёт вектор с указанными направлением и длиной
У каждого вектора есть три значения, которые изображают его. Это X, Y и Z (3 направления). Также важно знать, что методом .length() можно получить длину вектора и впоследствии получать / устанавливать значение каждой оси при помощи методов .getX(), .getY(), .getZ() и .setX(x), .setY(y), .setZ(z).

В ЧЁМ СМЫСЛ ВЕКТОРА В SPIGOT?
Всякий раз, когда перемещается сущность или нужно рассчитать цель, которую вы ищете, используется вектор. К концу статьи вы научитесь выполнять обе вещи.

Давайте объясним возможные вычисления.

* Синяя стрелка является результатом вычисления

СЛОЖЕНИЕ
fuMq8oK.png

Эта операция очень банальна. У вас есть одна стрелка, и вы добавляете её к другой. Давайте запишем это!
Java:
Vector first = new Vector(1, 3, 2);
Vector second = new Vector(3, -1, 4);

// Давайте сложим их!

Vector result = first.add(second); // В результате у нас получился вектор с параметрами 4, 2, 6

УМНОЖЕНИЕ
QaAXOMp.png

Ещё одна простая (и существенная) операция. Просто умножайте длину вектора. Когда полученное число ОТРИЦАТЕЛЬНОЕ, вектор меняет направление.
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
P.S. Если вы смогли проделать то же самое с любым другим числом вручную (пусть даже иногда используя калькулятор), вы поняли эту тему ;)

ВЕКТОРНОЕ ПРОИЗВЕДЕНИЕ
tjcBJ2f.png

Эта операция возвращает вектор, ортогональный двум предыдущим. Его длина — это площадь голубого параллелограмма. Это можно использовать для примерного сравнения двух векторов (например, когда нацеливаешься на игрока).

Например:
Java:
Vector first = new Vector(1, 2, 3);
Vector second = new Vector(-7, 8, 9);

Vector result = first.crossProduct(second); // Вернёт вектор с параметрами -6, -30, 22
6558ea9420e42205846c9ad12cbb3944.png


СРЕДНЕЕ АРИФМЕТИЧЕСКОЕ
Это легко! Берёшь один вектор, складываешь с другим и делишь результат на 2. И получаешь среднее арифметическое!
JzGuuoC.png

У вас есть два вектора — чёрный и оранжевый. Вы складываете их и получаете зелёный вектор. Вы делите зелёный вектор на 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);
}
 
Последнее редактирование:
Как правильно получить значение расстояния до конечной точки вектора!?
 

Поделиться этой страницей

Назад
Верх