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

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

 
Skino

offline
Опыт: 4,683
Активность:
Движение снарядов по прямой.
Статья рассчитана на новичка и неиспользует всякие там вектора и прожектора.
Эта система использует одну функцию для передвижения, дамми юнитов, с разной скоростью, разным уроном, всем разным...
В данном примере я покажу как я сделал дамми юнит в виде рокеты...
Система работает только на версии 1.24+
Итак! нам понадобяться:
Давайте для начало упростим мне написание стать, а именно сокращения:
Д.Ю. = дамми юнит = снаряд
Запомнили? Тогда идём дальше.

Редактор объектов

Для движения Д.Ю. нам нужно что? Конечно же сам Д.Ю., давайте сначало его создадим, это нехитрая операция, для этого нужно всего изменить пару параметров обычного юнита, (я предпочитаю использовать юнита "Ядовитое облоко" он находится: Нежить => Особые войска) а именно:
Идём снизу вверх
  • Название xD - ставим какое нравиться, я например поставил "++Rocket" ("++" это что бы наш юнит был самым верхним в списке)
  • Способности - Возможные способости: "Amrf,Avul,Aloc" (Что бы не усложнять вам жизнь давайте просто вставим через Shift+Enter в этот параметр наши скилы, расписываться я их небуду т.к. после вставки вы автоматом увидите их нахвания)
  • Пути - Физический размер: 0.00 (что бы юнит не "толкался")
  • Движения - Тип: Плывущий (только "Плывущий" корректно взаимедействует с рельефом)
  • Движение - Базовая скорость: 100.00
  • Графика - Файл модели: На ваш выбор xD
  • Графика - Максимальный угол поворота: 0.00 (что бы юнита не колбасило на склонах)
  • Графика - Максимальный угол крена: 0.00 (то же самое)
(Строго соблюдайте все вышеуказанные параметры)
Отлично! Теперь наш Д.Ю. "готов к употреблению".

Кастом код

Для начала давайте разберемся с кастом кодом карты, туда необходимо вставить функции необходимые для движения Д.Ю.
Смотрим:
globals
location L = Location(0.00,0.00)
hashtable HT = InitHashtable()
group G = CreateGroup()
endglobals
L - для дальнейшего определения высоты рельефа
HT - для аттача к юниту всего необходимого
G - в моей системе юниты выбираются не путём перебора массивов, а путем выбора каждого юнита из группы

function GetLocZ takes real x, real y returns real
    call MoveLocation(L,x,y)
    return GetLocationZ(L)
endfunction
Функция для определения высоты рельефа

function Boom takes unit u returns nothing
    local real dmg = GetUnitDefaultMoveSpeed(u)
    //Высчитываем урон
    call GroupRemoveUnit(G,u)
    call FlushChildHashtable(HT,GetHandleId(u))
    //Тут должна быть функция по нанесению урона
    call KillUnit(u)
endfunction
Функция уничтожения Д.Ю.

function MoveUnit takes unit u, real x, real y, real z returns nothing
    if x != 0.00 then
    call SetUnitX(u,x)
    endif
    if y != 0.00 then
    call SetUnitY(u,y)
    endif
    if z != 0.00 then
    call SetUnitFlyHeight(u,z,0.00)
    endif
endfunction
Универсальная функция для передвижения юнита в пространстве (очень удобно)

Создание дамми юнита

Теперь основа: создание самого дамми юнита.
Для этого создайте пустой триггер с названием "RocketCreate" и скопируйте в него код:
function Trig_CreateRocket_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == 'Hpal'
endfunction

function Trig_CreateRocket_Actions takes nothing returns nothing

endfunction

function InitTrig_RocketCreate takes nothing returns nothing
    set gg_trg_RocketCreate = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_RocketCreate, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_RocketCreate, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_RocketCreate, EVENT_PLAYER_UNIT_ISSUED_ORDER )
    call TriggerAddCondition( gg_trg_RocketCreate, Condition( function Trig_CreateRocket_Conditions ) )
    call TriggerAddAction( gg_trg_RocketCreate, function Trig_CreateRocket_Actions )
endfunction
Данный триггер реагирует на приказ юниту типа "move" и т.п.
Данное событие срабатывает на ордеры паладина.
Такс теперь в функции "Trig_CreateRocket_Actions" мы напишем код создания юнита, все что с ним связано.

Для начало нам нужно найти в пространстве самго юнита, скажем так стрельнувшего из рокета, вот и координаты:
    local real xu = GetUnitX(GetTriggerUnit())
    local real yu = GetUnitY(GetTriggerUnit())
    local real zu = GetLocZ(xu,yu)

Теперь таким же нехитрым способом находим координаты таргета(куда полетит Д.Ю.) и координаты создания самого Д.Ю.:
    local real xt = GetLocationX(GetOrderPointLoc())
    local real yt = GetLocationY(GetOrderPointLoc())
    local real zt = GetLocZ(xt,yt)
    //Вот мы имеет координаты точки в пространстве
    local real a  = Atan2(yt-yu,xt-xu)
    //Направление
    local real xr = xu+50.00*Cos(a)
    local real yr = yu+50.00*Sin(a)
    local real zr = ((zu-GetLocZ(xr,yr))+60.00)+GetLocZ(xr,yr)
а - направления от юнита до точки ордера
50.00 - расстояния от юнита, до точки появления Д.Ю
60.00 - высота появления Д.Ю.

Дальше когда мы имеем все координаты в пространстве, нам нужно знать расстояние между ними (t и r), тоже конечно в пространстве:
    local real d  = SquareRoot(((xt-xr)*(xt-xr))+((yt-yr)*(yt-yr))+((zt-zr)*(zt-zr)))

И вот теперь мы высчитываем шаги Д.Ю. в пространстве по формуле ниже:
    local real xs = xu-(xu+50.00*Cos(a))
    local real ys = yu-(yu+50.00*Sin(a))
    local real zs = (zr-zt)/(d/50.00)
50.00 - расстояния за 1 шаг (скорость)

Теперь создаём юнита:
    local unit r  = CreateUnit(GetTriggerPlayer(),'u000',xr,yr,bj_RADTODEG*a)
Где "u000" это рав код вашего созданого юнита (увидить его можно нажав Ctrl+D в РО)

Теперь устанавливаем Д.Ю. высоту, добовляем в группу, аттачим к нему шаги по X, Y и Z
    call SetUnitFlyHeight(r,zr-GetLocZ(xr,yr),0.00)
    call GroupAddUnit(G,r)
    call SaveReal(HT,GetHandleId(r),1,xs)
    call SaveReal(HT,GetHandleId(r),2,ys)
    call SaveReal(HT,GetHandleId(r),3,zs)
    set r = null

Вот и готов тригер по созданию Д.Ю.

Передвижение

Теперь основа всей системы "Движочек"
Опять создаем триггер и называем его "BullMove" конвертируем в текст, очищяем и вставляем:
function Bull_Move_G takes nothing returns nothing

endfunction

function Bull_move takes nothing returns nothing
    call ForGroup(G,function Bull_Move_G)
endfunction

function InitTrig_BullMove takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t,0.025,true)
    call TriggerAddAction(t,function Bull_move)
    set t = null
endfunction
Этот триггер каждые 0.025 секунд делает действя для каждого юнита в группе G.
Сами действия это "Bull_Move_G" пока они пустые, но щяс их наполним:

    local unit u   = GetEnumUnit()
    local real xu  = GetUnitX(u)
    local real yu  = GetUnitY(u)
    local real zu  = GetUnitFlyHeight(u)+GetLocZ(xu,yu)
    //Координаты юнита в пространстве
    local real xs  = LoadReal(HT,GetHandleId(u),1)
    local real ys  = LoadReal(HT,GetHandleId(u),2)
    local real zs  = LoadReal(HT,GetHandleId(u),3)
    //Шаги юнита в пространстве
Узнаем координаты юнита в пространстве, и с помощью аттача узнаем шаги юнита в пространстве.

Теперь имея координаты и шаги, высчитываем его следующее положение в пространстве
    local real xun = xu-xs
    local real yun = yu-ys
    local real zun = ((zu-zs)-GetLocZ(xun,yun))
    //Вычесляем положение юнита по осям X и Y, и динамически вычесляем следущее положение по оси Z

Проверяем высоту на проходимость, и если всё ок, то двигаем
    if zun <= 0.00 then
        call Boom(u)
    else
        call MoveUnit(u,xun,yun,zun)
    endif
    set u = null
Вот и всё, проверьте ещё разочек код, и можно проверять карту(незабудте закинуть на карту паладина, тригер создания реагирует именно на его действия), далее я выложил свой пример, качаем и лишний раз убеждаемся что всё работает, (ходить на стрелках).
Коментим, дополняем, попровляем!
Из-за негодования некоторых пользователей XGM статья приняла иную форму.
Прикрепленные файлы
Тип файла: w3x LineMove.w3x (29.8 Кбайт, 184 просмотров )

Отредактировано Skino, 11.02.2010 в 13:35.
Старый 10.02.2010, 08:20
Rewenger
The culprit will not die
offline
Опыт: 35,873
Активность:
Skino, они просто движутся по прямой в пространстве?.. Т.е. отлов столкновения в дестрактеблы и юнитов пишем сами?)
Старый 10.02.2010, 08:55
Skino

offline
Опыт: 4,683
Активность:
Скачай посмотри, ну а вообще ты прав, столкновения пишите сами, ибо у каждого свои условия.
У меня столкновения я бы сказал показательные...
Старый 10.02.2010, 08:57
Rewenger
The culprit will not die
offline
Опыт: 35,873
Активность:
Скачай посмотри
Зачем качать, если ты код выложил? Отличать функции отлова столкновений с юнитами от других я пока не разучился. *)
А вообще, без столкновений с объектами полезность этого сомнительна. Кажется, в барахолке должно быть ещё полным-полно таких.
Статья расчитана на пользователя со знанием джаза хотябы до 70%(где прочитать про джаз я думаю вы знаете)
Так же статья рассчитана на новичка и неиспользует всякие там вектора и прожектора.
Несколько взаимоисключающие пункты.
Старый 10.02.2010, 09:02
Skino

offline
Опыт: 4,683
Активность:
Знал бы ты сколько новичков молится на такие системы? После прочтения, ко всем мечтателям о шутерах придёт муза =)
Столкновения там есть!
Более сложные пишите сами! их писать нефиг делать даже на гуи
Старый 10.02.2010, 09:05
MF
Что-то вокруг не так
offline
Опыт: 26,594
Активность:
Итак:
  1. в точку (0,0,0) почему нельзя перемещатся? Оо
  2. function MoveUnitCheck takes real x, real y returns real... что за лол? А если у меня дамми летающий или меньше чем тот юнит которого делаешь ты? Оо
  3. Дальше не читал... там косинусы в периодических триггерах... для прямой, даже в пространстве это нафиг не надо. Курим вектора и это творение в качестве работы над ошибками.
MF добавил:
Общее мнение... низачот.
Старый 10.02.2010, 11:54
FellGuard
Losyash
offline
Опыт: 39,547
Активность:
  1. На кой нужен Avul, если москиты итак дают неуязвимость?
  2. Корректно взаимодействует с рельефом плывущий и парящий типы движения, а не только плывущий.
  3. Макс. угол крена/поворота надо проставить по нулям, чтобы юнита на склонах не колбасило, это константно для всех даммиков.
  4. Код:
    call UnitDamagePoint(u,0.00,150.00,GetUnitX(u),GetUnitY(u),dmg,true,false,ATTACK_TYPE  _MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
    В системах с минимальной претензией на "физику" данная строка - ересь, так как будет повреждать юнита на любой высоте вне зависимости от высоты полёта снаряда. Иными словами, физ. модель снаряда становится не коробом а уходящей в +/- бесконечность по Z прямоугольную область.
  5. В MoveUnit(), опять же, что за ужасть, если мне, положим, всё-таки надо юниту задать 0ую высоту, то функция высокомерно проигнорирует мой запрос? Мб тогда z<0. ? Кстати вот расчёт "абсолютного" Z я как раз запихал бы в эту функцию, вот это было бы удобно и экономило бы вызовы.
  6. Небольшая и простенькая проверка постоянно пересоздаёт юнита. На кой? Используется же одна единственная локация на всю систему для GetLocationZ(), так и с юнитом бы поступить так же, вместо CreateUnit использовать SetUnitPosition(). Злоупотреблять вызовом SquareRoot() опять же, не стоило бы, почитайте статью Адольфа, ноо... Ладно, чёрт с ним.
  7. Про использование тригонометрии опять же отсылаю вас к статье Адольфа
  8. Код:
    local unit r  = CreateUnitAtLoc(GetTriggerPlayer(),'u000',Location(xr,yr),a)
    Утечка в виде локации, используем вместо этого
    Код:
    local unit r  = CreateUnit(GetTriggerPlayer(),'u000',xr,yr,a)

Отредактировано FellGuard, 10.02.2010 в 12:09.
Старый 10.02.2010, 11:57
agentex

offline
Опыт: 34,834
Активность:
Система работает только на версии 1.24+
...и сразу fail
local unit u = CreateUnitAtLoc(Player(14),'hpea',Location(x,y),0.00)
ахаха.. дальше можно нечитать

Отредактировано agentex, 10.02.2010 в 12:07.
Старый 10.02.2010, 12:00
FellGuard
Losyash
offline
Опыт: 39,547
Активность:
Кстати, да, перерасчёт статической траектории многократно во время движения это совсем совсем не хорошо) Линейная траектория считается один раз.

FellGuard добавил:
Поправляй, пока что статья очень сырая.
Старый 10.02.2010, 12:08
MF
Что-то вокруг не так
offline
Опыт: 26,594
Активность:
По сути статья такого рода не нужна, Нкраш довольно таки неплохо написал о мувинг системах несколько ранее и более человеческими методами.
Старый 10.02.2010, 12:29
Skino

offline
Опыт: 4,683
Активность:
А если у меня дамми летающий или меньше чем тот юнит которого делаешь ты?
Этого тут вообще не должно быть, это идет как показательный довесок.
На кой нужен Avul, если москиты итак дают неуязвимость
Пусть будет, статья для новичков поэтому лучше перестраховаться.
надо юниту задать 0ую высоту
Тогда нужно задавать не 0 а хотябы 0.05
Skino добавил:
Линейная траектория считается один раз.
С учётом динамического изменения ландшафта?
Могу поспорить там наверное ещё и без массивов не обходится.
Старый 10.02.2010, 14:53
DioD

offline
Опыт: 45,134
Активность:
ересь если честно, 3д движение пишется на векторах и никак иначе.
Старый 10.02.2010, 16:49
Skino

offline
Опыт: 4,683
Активность:
Читаем для кого статья, + я её доработаю завтра. и сделаю некое подобие векторов.
Старый 10.02.2010, 17:22
DioD

offline
Опыт: 45,134
Активность:
да хоть на 1% знаешь джаз, 3Д движение делается на векторах даже на гуи.
Старый 10.02.2010, 17:43
adic3x

offline
Опыт: 108,439
Активность:
Статья расчитана на пользователя со знанием джаза хотябы до 70%
вступление нам как бы намекает, что человек даже не знает, как правильно писать слово жасс (джасс), или по русские пдсс (просто другая система сценариев)
ADOLF добавил:
Так же статья рассчитана на новичка и неиспользует всякие там вектора и прожектора
oh shi~
ADOLF добавил:
Warcraft III World Editor (рус версия т.к. я использую руские название)
double oh shi~
ADOLF добавил:
а чего нельзя двигать юнита по координатам 0.? мда, "вы все нешарите" ©
ADOLF добавил:
последний вопрос - почему юзаете триг место таймера?
ADOLF добавил:
UnitDamagePoint
косячно, не юзайте ее
ADOLF добавил:
Могу поспорить там наверное ещё и без массивов не обходится.
вы об этом так говорите, как будто в массивах есть что то плохое
Старый 10.02.2010, 22:48
DioD

offline
Опыт: 45,134
Активность:
можно подвести этог фразой "выпиливайте эту ересь как автор исправит пусть постит опять".
вот только адвансед уровень описан в статье про ньютонову механику, а лоу левел пишется на гуи.
Старый 11.02.2010, 05:09
Skino

offline
Опыт: 4,683
Активность:
а чего нельзя двигать юнита по координатам 0.? мда, "вы все нешарите" ©
Шанс что при движенни выпадит 0.00 равна 0.01%
косячно, не юзайте ее
Опять же, этого тут недолжнобыть, это просто как показательный довесок
Старый 11.02.2010, 07:28
MF
Что-то вокруг не так
offline
Опыт: 26,594
Активность:
Skino:
Шанс что при движенни выпадит 0.00 равна 0.01%
Шанс несколько больше или несколько меньше... но тем не менее. Не вижу смысла в этом бреде... хотя можешь выводить на экран в случае выпадения "О да! Вы счастливчик!"... Тогда это будет оправдано.
Старый 11.02.2010, 07:43
adic3x

offline
Опыт: 108,439
Активность:
спасибо, администрация долго смеялась над нелепейшем методом удаления неугодных автору комментариев.
самое забавное - что автор даже не удосужился хоть что то исправить в статье
продолжаем ловить лулзы в теме
предвидя его реакцию уточняю - да, я адский мудак
Старый 11.02.2010, 10:51
Toadcop

offline
Опыт: 54,313
Активность:
Цитата:
да, я адский мудак

НЕТ ТЫ !
Старый 11.02.2010, 17:21

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

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

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

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



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