XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Желтая пресса: обучающие статьи
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

 
MF
Что-то вокруг не так
offline
Опыт: 26,594
Активность:
Вектора и движение в варкрафт
статья ориентирована на людей, которые имеют представление что такое вектор, но не представляют как их можно использовать.

О чем пойдет речь?

В первую очередь я постараюсь дать некоторые теоретические выкладки о векторах и некоторых способах их использования в варкрафте. Представлю вашему вниманию библиотеку для работы с векторами и два примера ее использования.
Все само собой с подробными объяснениями.

Теория

Подробную информацию о векторах можно посмотреть здесь: Вектор_(геометрия).
Теперь , что нам из всего этого можно использовать? Во-первых, нужно понимать что вектор это объект геометрического мира, обозначающий направление в чистом виде. Учитывая, что векторами очень часто обозначают всевозможные характеристики и воздействия в физике, то важна еще и длина вектора. Найти ее можно следующим образом:
SquareRoot( x * x + y * y + z * z )
Где x, y и z - это координаты вектора.
Что же мы можем делать с вектором? А можем мы следующее:

Умножение на число

Для этого достаточно умножить каждую координату на число, что самое полезное, длина вектора тоже умножится на это число. На этом основана одна полезная операция: приведение длины вектора к 1 (еще называют процессом нормализации вектора), или к какому-либо другому числу. Достаточно разделить каждую координату вектора на длину и умножить на требуемое число. При этом направление вектора не изменится.

Сложение векторов

По сути, если есть вектор а и вектор б то складывая их, мы получаем некоторый вектор ц, координаты которого получены с помощью сложения координат векторов а и б. Для чего это? Для имитации физических величин и воздействий. Например, если у объекта есть скорость и ускорение (обе величины вектора), то в каждый момент времени скорость меняется путем сложения с ускорением. Так же примером применения могут служить силы в физике. Если на тело действует несколько сил, то их можно заменить одной результирующей силой, равной сумме всех действующих сил.

Сложение вектора и точки

Необходимо для перемещения точки по вектору. Операция схожа с предыдущей (и кто то скажет, что это одно и то же, и будет прав с практической точки зрения, теоретически разницу все равно стоит понимать). Складываются координаты точки и вектора. Одна лишь разница, результатом такого сложения будет не вектор, а точка. Пример применения - элементарное движение прожектила. У нас есть вектор его скорости, каждые n секунд мы вычисляем его новую позицию как сумму вектора скорости и его текущей позиции.

Скалярное произведение векторов

подробно: Скалярное_произведение
Одна из самых полезных вещей, но ее применение не так очевидно. Найти его можно как произведение длин векторов на косинус угла меду ними... Возникает ряд неудобностей и сложностей. Но есть и еще один способ, более простой и удобный. Скалярное произведение равно
x1 * x2 + y1 * y2 + z1 * z2
Как можно применять? Применять можно для нахождения проэкций одного вектора на другой. У скалярного произведения есть еще и такой смысл: скалярное произведение двух векторов есть произведение длины одного вектора на проекцию второго на направление первого. Поясню примером, если создается волна из прожектилов источник которой точка. Создать такую волну с дуговым фронтом плевое дело для любого уважающего себя спеллера. А если фронт волны должен выглядеть как прямая? Что делать тогда? Вот тогда и пригодится данная формула. Достаточно знать общее направление волны (центральный вектор равный 1), затем проделывается следующая последовательность операций для векторов скоростей каждого из прожектила в волне:
-находим скалярное произведение этого вектора и центрального вектора
-делим вектор скорости прожектила на полученное число
После всего этого умножаем все вектора скоростей прожектилов на скорость волны.

Векторное произведение векторов

Здесь начинается особая векторная магия
Подробно: Векторное_произведение
Самая полезная (и в то же время самая запутанная операция для новичков). Для тех кто понимает что такое определитель матрицы и имеет представление о векторах i, j и k, скажу что оно равно определителю матрицы:
i j k
x1 y1 z1
x2 y2 z2
Для тех кто всего этого не знает, скажу что результатом будет вектор с координатами равными:
x = y1 * z2 - y2 * z1
y = z1 * x2 - z2 * x1
z = x1 * y2 - x2 * y1
Какими же свойствами обладает этот вектор и чем он так полезен? А тем что он направлен перпендикулярно обоим векторам. Что очень полезно для нахождения векторов нормалей к всевозможным поверхностям (например при определении вектора отражения в столкновениях).

Библиотека для работы с векторами

» код библиотеки для работы с векторами
library vectors
    
    struct vector
        real x
        real y
        real z
        static method create takes real x, real y, real z returns vector
            local vector v = vector.allocate()
            set v.x=x
            set v.y=y
            set v.z=z
            return v
        endmethod

        method realmul takes real r returns nothing
            set .x=.x*r
            set .y=.y*r
            set .z=.z*r
        endmethod
        
        method getlength takes nothing returns real
            return SquareRoot(.x*.x+.y*.y+.z*.z)
        endmethod
        
        method normalize takes nothing returns nothing
            local real l = .getlength()
            if l>0 then
                call .realmul(1/l)
            endif
        endmethod   
        
        method setlength takes real r returns nothing
            local real l = .getlength()
            if l>0 then
                call .realmul(r/l)
            endif
        endmethod
        
        method scalarmul takes vector v returns real
            return .x*v.x+.y*v.y+.z*v.z
        endmethod
        
        method vectorsum takes vector v returns nothing
            set .x=.x+v.x
            set .y=.y+v.y
            set .z=.z+v.z
        endmethod    
        
        method vectormul takes vector v returns nothing
            local real x = .y*v.z-v.y*.z
            local real y = .z*v.x-v.z*.x
            local real z = .x*v.y-v.x*.y
            set .x = x
            set .y = y
            set .z = z
        endmethod
        
        method clone takes nothing returns vector
            local vector v=vector.allocate()
            set v.x=.x
            set v.y=.y
            set v.z=.z
            return v
        endmethod      
        
        method copy takes vector p returns nothing
            set .x=p.x
            set .y=p.y
            set .z=p.z            
        endmethod
        
        method change takes real x, real y, real z returns nothing
            set .x=x
            set .y=y
            set .z=z
        endmethod
    endstruct    
    
endlibrary
Итак, начнем разбиратся с методами.
  • Метод create
Статичный метод создающий вектор, принимает координаты возвращает вектор.
» пример
local vector v = vector.create(0,0,0)
  • Метод realmul
Умножает вектор на какое либо число.
» пример
local vector v = vector.create(1,1,1)
call v.realmul(2)
//результат вектор с координатами 2 2 2
  • Метод getlength
Метод возвращающий длину вектора
» пример
local vector v = vector.create(0,0,1)
local real r = v.getlength()
//результат равен 1
  • Метод normalize
Устанавливет длину вектора равным 1
» пример
local vector v = vector.create(54,0,0)
call v.normalize()
//результат: вектор а равен 1 0 0
  • Метод setlength
Принимает число. Устанавливает длину вектора равной этому числу.
» пример
local vector v = vector.create(54,0,0)
call v.setlength(30)
//результат: вектор а равен 30 0 0
  • Метод scalarmul
Принимает вектор. Возвращает число равное скалярному произведению этих векторов.
» пример
local vector v = vector.create(1,2,3)
local vector w = vector.create(1,0,3)
local real r = v.scalarmul(w)
//результат равен 10
  • Метод vectorsum
Принимает вектор. Устанавливает вызывающий вектор равным сумме самого себя и принятого вектора.
» пример
local vector v = vector.create(1,2,3)
local vector w = vector.create(1,0,3)
local real r = v.vectorsum(w)
//результат: вектор v равен 2 2 6, вектор w не изменился
  • Метод vectormul
Принимает вектор. Устанавливает вызывающий вектор равным векторному произведению самого себя и принятого вектора.
» пример
local vector v = vector.create(1,0,0)
local vector w = vector.create(0,1,0)
local real r = v.vectormul(w)
//результат: вектор v равен 0 0 1, вектор w не изменился
  • Метод clone
Принимает вектор. Возвращает вектор равный вызывающему.
» пример
local vector v = vector.create(1,0,0)
local vector w = vector.clone()
//результат: вектор v равен 1 0 0, вектор w равен 1 0 0
  • Метод copy
Принимает вектор. Устанавливает значение вызывающего вектора равным принятому вектору.
» пример
local vector v = vector.create(1,0,0)
local vector w = vector.create(0,1,0)
call v.copy(w)
//результат: вектор v равен 0 1 0, вектор w равен 0 1 0
  • Метод change
Принимает координаты x, y и z. Форсированное изменение координат вектора.
» пример
local vector v = vector.create(1,0,0)
call v.change(1,1,1)
//результат: вектор v равен 1 1 1
P.S. Не забываем вызывать метод destroy для векторов которые уже не нужны!

Примеры и их описание

Вложение Vectors не содержит в себе функциональной демонстрации, это чистая библиотека. Готовая для копирования и использования.
Вложение Simple_projektils это пример с простым прямолинейным движением прожектилов по прямой в 3d и столкновением с ландшафтом. Для запуска прожектила достаточно применить заклинание "Канал" на любой точке ландшафта. Прожектилы учитывают высоту рельефа и летают строго по прямой. Прошу обратить внимание, что все движение выполнено только на алгебраических функциях (никаких синусов и косинусов), что значительно увеличивает быстродействие. Единственная тригонометрическая функция это Atan2 для определения взгляда прожектила (можно было и использовать взгляд кастера, но сделано так, чтоб показать как это можно делать динамически используя вектор). Все вычисления направления происходят 1 раз для каждого прожектила. В дальнейшем высчитываются только координаты.
Вложение Projectils_with_inertial более сложный пример. Здесь участвует такая вещь как инерция. Прожектилы не просто летят к магу крови. Они еще и учитывают свою текущую скорость. Сделано это с помощью добавления в систему прожектилов вектора ускореня, который всегда направлен в сторону мага. Так же наложены ограничения на скорость в виде пороговой скорости. При этом прожектилы не уничтожаются при столкновении с ландшафтом, они от нее отражаются (определенное количество раз). Реализовано это с помощью векторного и скалярного произведения. Механика такая:
  • В момент падения строится два маленких ортогональных вектора задающих участок плоскости падения
  • К этим векторам строится перпендикуляр (нормаль к поверхности)
  • С помощью скалярного произведения на основе вектора падения и вектора нормали строится отраженный вектор, именно он становится новой скоростью прожектила.
Вот и все. Enjoy and Good Luck!!!
Прикрепленные файлы
Тип файла: w3m Vectors.w3m (16.9 Кбайт, 107 просмотров )
Тип файла: w3x Simple_projektils.w3x (25.8 Кбайт, 185 просмотров )
Тип файла: w3x Projectils_with_inertial.w3x (28.6 Кбайт, 143 просмотров )

Отредактировано MF, 27.07.2009 в 05:19.
Старый 24.07.2009, 09:14
Тзинч

offline
Опыт: 4,948
Активность:
Кхм... статья интересная, но я на сонную голову пока ничего не понимаю.
Я не помню какой предмет, очень знакомый.
Просто у нас его читали, но плохо.
Старый 24.07.2009, 09:29
DragonSpirit
у - уходи
offline
Опыт: 22,625
Активность:
MF имхо хорошая статья,зачёт
а за библиотеку векторов отдельное спасибо =)
Старый 24.07.2009, 09:42
MF
Что-то вокруг не так
offline
Опыт: 26,594
Активность:
Не забываем указывать автора в титрах при использовании. ^_^
Если что-то непонятно и нужно более подробно расписать, пишите. Я учту и дополню статью.
Старый 24.07.2009, 09:46
dk

offline
Опыт: 60,293
Активность:
Линкану одну старую "библеотеку" по векторам... VectorFunctions.w3x Мб тож пригодится.
так все в одном топике будет)

Отредактировано dk, 24.07.2009 в 10:30.
Старый 24.07.2009, 09:59
FREEZE_ball
Cataclysm => жара
offline
Опыт: 15,247
Активность:
А кроме создания прожектилов, вектора ещё можно где-нибудь использовать (займёмся теорикрафтингом)?
Старый 24.07.2009, 10:11
MF
Что-то вокруг не так
offline
Опыт: 26,594
Активность:
FREEZE_ball
Прожектилы самый очеведный пример. Вообще вектора использовать можно где и как угодно. Всевозможные системы движения тоже можно делать на векторах.
К слову сказать, свой аналог DGUI для проекта я тоже писал используя вектора.
Старый 24.07.2009, 10:19
ScorpioT1000
Работаем
online
Опыт: отключен
Достаточно интересная вещь, но без оптимизации не обойтись. С тем же рядом проджектилов, есть решения быстрей, напр. с полярками(если я правильно понял задачу)
А вобще, тут есть еще то, с чем я никогда не сталкивался, надо будет заняться :)
ScorpioT1000 добавил:
зачот
Старый 24.07.2009, 13:28
MF
Что-то вокруг не так
offline
Опыт: 26,594
Активность:
ScorpioT1000
Не думаю что полярки быстрее, так как там используется тригонометрия (косинусы и синусы) и еще, в случае сложных спеллов, куча чего. Вектор же вычисляется путем 3 разностей. Да, если это производится 1 раз, то согласен с тобой, полярки и больше ниче не нужно (хотя я проект свой перевожу на вектора, так как это проще, если понять и вникнуть), если же приходится каждый раз вычислять какие то сложные вещи, да и еще в 3d (переходмим к сферичиским или цилиндричиским координатам) то тут у векторов нет конкурентов по скорости вычисления.
Старый 24.07.2009, 13:35
Hellfim
Новичок
offline
Опыт: 79,707
Активность:
Думаю понял, после часа пинания андреича в аське. В теории совсем не хвататет картинок.
Старый 24.07.2009, 19:48
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
MF ОФИГИТЕЛЬНАЯ статья. просто мечтал о такой. одну похожую читал, но она непонятная( была. спасибо автору очень много узнал всего...
Старый 25.07.2009, 02:57
PlayerDark
Coraline
offline
Опыт: 10,569
Активность:
Да, векторы действительно рулят. Да, кстати, я видел ОЧЕНЬ похожую библиотеку выложенную где-то в сети. Я не говорю что это плагиат, просто при желании сделать особого труда не доставит.
Старый 25.07.2009, 08:52
MF
Что-то вокруг не так
offline
Опыт: 26,594
Активность:
Цель ставилась не в реализации библиотеки. А в пробуждении интереса к человеческим методам в геймдеве у наших спеллеров.
Старый 25.07.2009, 11:02
GhfDllT

offline
Опыт: 3,980
Активность:
Предложение
Я как нуб джасса сначала спрошу, не ошибочен ли такой код, при условии что vectorsum возвращает вектор
Код:
locale vector v  = vector.create(x,y,z)
locale vector w  = vector.create(x,y,z)
v = v.vectorsum(w)

Если не ошибочен, то мне кажется лучше в методах где участвует 2 вектора возвращать вектор(сложение, оба умножения). Не претендую, но так просто удобней: если у меня 3 вектора, то я могу одному присвоить сумму остальных не модифицируя их, и не копируя в другие векторы, что при текущей версии делать неудобно. Да и при нормализации и установке длины тоже вектор возвращать следует, так просто грамотней по-моему и удобней.

GhfDllT добавил:
А статья хорошая, ради стеба можно еще метод вычитания векторов вставить)))
Цитата:
А в пробуждении интереса к человеческим методам в геймдеве у наших спеллеров
- для этого не мешало бы несколько интересных примеров на векторах показать, а то не сильно разбирающиеся не поймут причем тут векторы, с чем их едят и чем они ему помогут,- но это так, чушь
Старый 25.07.2009, 17:30
MF
Что-то вокруг не так
offline
Опыт: 26,594
Активность:
GhfDllT
Возвращать вектор значит создавать еще одного представителя данной структуры... Возможно я продублирую методы, те которые изменяют текущий вектор, чтоб возвращали новый не меняя старый. Пока можно делать следующим образом, если нужен новый вектор:
local vector v  = vector.create(x,y,z)
local vector w  = vector.create(x,y,z)
local vector b = v.clone()
call b.vectorsum(w)
Тогда в векторе b будет результат суммы, при этом v и w не изменятся.
Старый 25.07.2009, 18:41
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
еще раз прочитал, не очень понятно, но всравно чтото понимаю
Старый 25.07.2009, 23:57
J
expert
offline
Опыт: 48,447
Активность:
простейшая геометрия, среднии классы... я бы советовал лучше учебники почитать...
Цель ставилась не в реализации библиотеки. А в пробуждении интереса к человеческим методам в геймдеве у наших спеллеров.
не путай гейм дев и модмейкерство
J добавил:
не, ну народ что здесь отписываеться меня удивил, я конечно знал что многие не знают даже математику школьной программы, но чтобы настолько что не разбираться в подобных вещах... просто шокирующие

Отредактировано J, 26.07.2009 в 05:29.
Старый 26.07.2009, 05:33
Hellfim
Новичок
offline
Опыт: 79,707
Активность:
J, мне можно, у меня это только через месяц начнется =)
Старый 26.07.2009, 06:22
J
expert
offline
Опыт: 48,447
Активность:
и? самая глупая ошибка которую допускают школота это подчинение школьной программе, если тебе это было нужно можно получить подробнейшую информацию с той же википедии а не ждать следующего класса когда тебе все разжуют
Старый 26.07.2009, 06:45
Hellfim
Новичок
offline
Опыт: 79,707
Активность:
Мне это было ненужно. Меня вполне устраивали полярные координаты, и я не видел смысла в изучении векторов раньше времени. Теперь, я понимаю, что с векторами гораздо удобнее и постепенно перехожу на них.
Старый 26.07.2009, 07:16

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 13:20.