WarCraft 3: [vJass]: Первые шаги | |
Теперь приступим к самому программированию. В vJass добавили возможность
создания библиотек – области кода, которые после компиляции будут вставлены выше
Custom script карты. Очень полезная вещь, позволяет систему держать в 1
триггере, облегчая импорт вашей наработки. Удаляем стандартную инициализацию
и создаем триггер «MovingSys», дальше «Правка->Конвертировать в текст»,
удаляем весь текст из триггера и пишем: library MoveSys
ndlibrar ey
Вот и создали библиотеку, теперь нам надо описать вектор. Вектору
необходимы 3 переменные для его координат: library MoveSys
struct vector real x real y real z endstruct
endlibrary
Теперь добавим методы (те самые функции) для операций над
вектором:
library MoveSys
struct vector real x real y real z static method GetFrom2Locs takes real ax,real ay,real az,real bx,real by,real bz returns vector local vector v = vector.create() set v.x = bx-ax set v.y = by-ay set v.z = bz-az return v endmethod method Summ takes vector a returns nothing set this.x = this.x + a.x set this.y = this.y + a.y set this.z = this.z + a.z endmethod method Multiply takes real k returns nothing set this.x = k*this.x set this.y = k*this.y set this.z = k*this.z endmethod method Module takes nothing returns real return SquareRoot(this.x*this.x+this.y*this.y+this.z*this.z) endmethod method Norm takes nothing returns nothing local real m = SquareRoot(this.x*this.x+this.y*this.y+this.z*this.z) set this.x = this.x/m set this.y = this.y/m set this.z = this.z/m endmethod endstruct
endlibrary
Поздравляю, первый «кит» системы готов! Теперь обратим свой взор на объекты
движения. Двигать мы будем юнитов, и чтобы к ним привязать векторы скорости,
ускорения и силы, создадим еще одну структуру:
// Обзовем новую структуру "телом" struct body unit u real m vector v vector a vector f static method Create takes unit u, real mass returns body local body b = body.create() set b.u = u set b.m = mass set b.v = vector.create() set b.a = vector.create() set b.f = vector.create() call UnitAddAbility(u,'Amrf') call UnitRemoveAbility(u,'Amrf') return b endmethod method Destroy takes nothing returns nothing call this.v.destroy() call this.a.destroy() call this.f.destroy() call this.destroy() endmethod endstruct
Основная часть движка
Теперь остался последний кит – сам цикл движения. Есть два способа двигать
тело: обсчитывать координаты, а потом перемещать юнита в точку с этими
координатами; брать за основу координаты юнита и перемещать относительно них.
Может быть, вам не видно разницы между этими способами? Тогда приведу
примеры:
set x = … set y = … set z = … call SetUnitX(u,x) call SetUnitY(u,y) call SetUnitFlyHeight(u,z,0)
Это пример первого способа. Все вычисления производятся вне нативных
функций, при этом не учитываются «желания» юнита передвигаться, поэтому придется
делать еще триггер сброса приказа (или добавлять способность москитов), так как
при попытке бежать юнит будет дергаться.
call SetUnitX(u,GetUnitX(u)+dx) call SetUnitY(u, GetUnitY(u)+dy) call SetUnitFlyHeight(u, GetUnitFlyHeight(u)+dz,0)
Второй способ. Теперь два движения будут складываться. Воспользуемся этим
методом.
Создаем массив тел, по которому будет бегать цикл:
globals body array mvs_Sb [1000] integer mvs_si = -1 endglobals
Теперь создадим функцию, которая нам запустит систему:
library MoveSys initializer IniMove
… private function Engine takes nothing returns nothing
endfunction
function IniMove takes nothing returns nothing call TimerStart(CreateTimer(), 0.025, true, function Engine) endfunction
endlibrary
Пора наполнить содержанием функцию «Engine»:
private function Engine takes nothing returns nothing local integer i = 0 local body b loop exitwhen i > mvs_si if mvs_Sb__ != 0 then set b = mvs_Sb__ if b.m > 0 then set b.a.x = b.f.x/b.m set b.a.y = b.f.y/b.m set b.a.z = b.f.z/b.m endif set b.f.x = 0 set b.f.y = 0 set b.f.z = 0 set b.v.x = b.v.x + b.a.x set b.v.y = b.v.y + b.a.y set b.v.z = b.v.z + b.a.z call SetUnitX(b.u, GetUnitX(b.u) + b.v.x*0.025) call SetUnitY(b.u, GetUnitY(b.u) + b.v.y*0.025) call SetUnitFlyHeight(b.u, GetUnitFlyHeight(b.u) + b.v.z*0.025,0) else set mvs_Sb__ = mvs_Sb[mvs_si] set mvs_Sb[mvs_si] = 0
set mvs_si = mvs_si - 1 set i = i - 1 endif set i = i + 1 endloop endfunction
|