|
|
|
|
[СТАТЬЯ] Отряд, ForGroup, GroupLoop
|
|
FkoFF | Дата: Вторник, 24 Мая 2011, 08:39:54 | Сообщение # 1 |
Группа: Заблокированные
Сообщений: 4356
Награды: 1
Репутация: 1413
Блокировки:
| Каждый человек использовавший триггеры в той или иной ситуации вынужден воспользоваться группами юнитов, что такое эти группы и с чем их едят я постараюсь изложить максимально доступно для мягкого нубъего мозга.
Итак, самое первое – свойства объекта.
Группа юнитов – объект достаточно легкий, однако обращение с ним стоит достаточно большого количества памяти. Состоит объект из массива чисел, являющихся ссылками на юнитов.
Опасные точки соприкосновения с группами это функции CreateGroup() и DestroyGroup() В игре бывают моменты когда подобные действия вызывают некоторые повышенные затраты оперативной памяти, хотя я и не решаюсь сказать по чему это конкретно происходит.
Еще одна опасная точка соприкосновения это функции на GUI, требующие конкретную группую юнитов для работы, самая опасная из всех - For Group Matching, создает не только утекающую группу но и утекающий Boolexpr.
Работа с группой юнитов возможна двумя путями: классический(ForGroup) и GroupLoop. Первый способ ForGroup берет группу и ссылку на функцию, заставляет для каждого юнита в группе исполнять действия в функции. Второй способ – GroupLoop выгодно отличается от первого тем, что не требует выноса за пределы функции, однако обладает рядом ограничений, и по этому в некотором роде ущербен.
Основной минус ForGroup и его переноса в функцию тот что функция не может содержать аргументов, а соответственно мы не можем передать, к примеру, юнита, который должен нанести урон всем в группе. Вторая проблема – нет функции которая бы вернула handle самой группы, для которой производятся действия, то есть нет фактического способа передачи данных в группу напрямую, исключение – глобальные переменные. Основной плюс – все действия происходят параллельно (а не последовательно, как в случае со вторым способом), а соответственно скорость работы данного способа несколько быстрее.
Основные минусы второго способа (GroupLoop) – вероятность того что выполнение цикла прервется из-за превышения максимального количества действий для одной функции. Второй минус – обязательное удаление юнита из группы для прогресса цикла (для перебора юнитов в существующей группе придется использовать еще одну группу). Однако все локальные переменные функции, в которой происходят действия – сохраняются и не требуют передачи.
Первый метод известен всем абсолютно людям пользовавшимся триггерами, это стандартный способ GUI, второй способ требует объяснения, что да как. Суть GroupLoop – избежание переноса действий из одной функции в другую, хотя бы по той причине что так удобнее кодить.
Рассмотрим самый удобный вариант
[code=jass] function grouploop takes real x, real y, real radius returns nothing local group g=udg_Temp_Group local unit forloop //для работы требуется юнит, назовем его forloop call GroupEnumUnitsInRange(g,x,y,radius,null) //функция GroupEnumUnitsInRange последним аргументом требует Boolexpr, однако он, //мало того что является объектом, так еще и требует отдельную функцию для работы
loop set forloop=FirstOfGroup(g) exitwhen forloop==null if UrCondition1==true and UrCondition2==true then ... endif call GroupRemoveUnit(g,forloop) endloop //собственно это и есть метод работы с GroupLoop, выбирается юнит, первый из группы //(g), если в группе нет юнитов, а соответственно forloop==null, цикл прекращается. Все //требуемые условия вынесены в if\then\else конструкцию, которую, к слову, //рекомендуется вынести в отдельную функцию, дабы не захламлять все функции с //груплупом одними и теми же условиями.
set g=null endfunction [/code]
Как читатель мог заметить – я использовал глобальную переменную, вместо локальной CreateGroup(). Так мы лишаем игру лишнего кратковременного хэндла и лишней нагрузки на вызов целых двух функций + связанных с ними возможных осложнений.
Благодарю за чтение, надеюсь читатель получил хоть сколько-то новой информации из статьи.
FkoFF, специально для Warcraft 3 Info.
|
|
|
|
lawson | Дата: Вторник, 24 Мая 2011, 08:44:58 | Сообщение # 2 |
Группа: Проверенные
Сообщений: 3482
Награды: 0
Репутация: 974
Блокировки:
| А что кто то не умеет пользоваться группами? Допиши call DestroyGroup - а то не которые могут не принять это во внимание.
Nic nie wiem bo mam chuj. редактирую посты! ВСЕ!
|
|
|
|
CHLSN | Дата: Вторник, 24 Мая 2011, 10:56:41 | Сообщение # 3 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| FkoFF, думаю идея с использованием глобальной группы оправдана, если команды выполняется последовательно, ведь это так?
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
|
|
|
|
FkoFF | Дата: Вторник, 24 Мая 2011, 13:39:25 | Сообщение # 4 |
Группа: Заблокированные
Сообщений: 4356
Награды: 1
Репутация: 1413
Блокировки:
| Quote (CHLSN) FkoFF, думаю идея с использованием глобальной группы оправдана, если команды выполняется последовательно, ведь это так? условие только одно - группа после использования должна быть пуста, шансов на конфликт нет вообще.
|
|
|
|
CHLSN | Дата: Вторник, 24 Мая 2011, 14:03:51 | Сообщение # 5 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| Quote (FkoFF) udg_Temp_Group Можно наверное и стандартную переменную использовать для полного счастия bj_groupLastCreatedDest ?
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
|
|
|
|
FkoFF | Дата: Вторник, 24 Мая 2011, 14:07:51 | Сообщение # 6 |
Группа: Заблокированные
Сообщений: 4356
Награды: 1
Репутация: 1413
Блокировки:
| Quote (CHLSN) bj_groupLastCreatedGroup Не, определенно глобалка надежнее, там 100% гарантия что переменная не будет переписана.
К слову - для некоторых целей все равно придется использовать "плавающие" группы, как например для снарядов типа волны силы, наносящих однократно х урона каждому юниту сквозь которого проходят )
|
|
|
|
CHLSN | Дата: Вторник, 24 Мая 2011, 14:19:22 | Сообщение # 7 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| Quote (FkoFF) Не, определенно глобалка надежнее, там 100% гарантия что переменная не будет переписана. Ага, то есть не используя BJ-функций, Warcraft может там самостоятельно свои переменные писать?
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
|
|
|
|
FkoFF | Дата: Вторник, 24 Мая 2011, 14:20:52 | Сообщение # 8 |
Группа: Заблокированные
Сообщений: 4356
Награды: 1
Репутация: 1413
Блокировки:
| Quote (CHLSN) Ага, то есть не используя BJ-функций, Warcraft может там самостоятельно свои переменные писать? собственно константные переменные bj_LastCreatedObject и используются для передачи в триггеры последнего созданного юнита, на джасс они вообще не используются никогда, за исключением тех случаев когда пишется функция на создание какого-либо объекта для наработки (что бы нубы могли использовать не задумываясь))
|
|
|
|
CHLSN | Дата: Вторник, 24 Мая 2011, 14:31:15 | Сообщение # 9 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| А по поводу статьи - здорово)) + что не надо создавать локальную группу, разрушать, обнулять. Экономично получается.
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
|
|
|
|
SirNikolas | Дата: Вторник, 24 Мая 2011, 15:22:44 | Сообщение # 10 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| А почему же не рассмотрен третий способ?Code globals constant group PickGroup = CreateGroup() boolexpr PickBool endglobals
funciton Trig_Temp_Pick takes nothing returns boolean local unit u = GetFilterUnit() //... set u = null return false endfunction
function Trig_Temp_Actions takes nothing returns nothing call GroupEnumUnitsInRect(PickGroup, bj_mapInitialPlayableArea, PickBool) endfunction
function InitTrig_Temp takes nothing returns nothing set PickBool = Filter(function Trig_Temp_Pick) endfunction
|
|
|
|
CHLSN | Дата: Вторник, 24 Мая 2011, 15:41:30 | Сообщение # 11 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| Так, к слову, Condition() оставляет неудаленный boolexpr?
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
|
|
|
|
lawson | Дата: Вторник, 24 Мая 2011, 17:42:38 | Сообщение # 12 |
Группа: Проверенные
Сообщений: 3482
Награды: 0
Репутация: 974
Блокировки:
| Quote (CHLSN) Так, к слову, Condition() оставляет неудаленный boolexpr? Да надо удалять потом boolexpr, если ты об этом.
Nic nie wiem bo mam chuj. редактирую посты! ВСЕ!
|
|
|
|
CHLSN | Дата: Вторник, 24 Мая 2011, 17:48:33 | Сообщение # 13 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| Тогда я думаю, что эта муть с boolexpr, которую SirNikolas предложил, не особо нужна, т.к. читабельнее размещать функции условий рядом там, где они используются и писать call GroupEnumUnitsIn<>(PickGroup, <>, Condition( function <> ) )
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
|
|
|
|
SirNikolas | Дата: Вторник, 24 Мая 2011, 19:31:36 | Сообщение # 14 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| Quote (CHLSN) call GroupEnumUnitsIn<>(PickGroup, <>, Condition( function <> ) ) Так писать нельзя именно потому, что будет утечка boolean expression. Можно, конечно, каждый раз создавать локальный буль и удалять его, но это будет хуже.
Сообщение отредактировал SirNikolas - Вторник, 24 Мая 2011, 19:33:59 |
|
|
|
CHLSN | Дата: Вторник, 24 Мая 2011, 19:39:14 | Сообщение # 15 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| SirNikolas, и куда она утекает?
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
|
|
|
|
SirNikolas | Дата: Вторник, 24 Мая 2011, 19:48:12 | Сообщение # 16 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| Condition( function <> ) возвращает conditionfunc (type conditionfunc extends boolexpr), который никуда не записывается и потому "утекает". Вот, запусти и посмотри, что будет:Code globals constant group GROUP = CreateGroup() endglobals
function LeakChecker takes nothing returns nothing local timer t = CreateTimer() call BJDebugMsg(I2S(GetHandleId(t))) call DestroyTimer(t) set t = null endfunction
function Trig_LeakTest_Conditions takes nothing returns boolean return true//Просто для примера endfunction
function Trig_LeakTest_Actions takes nothing returns nothing call GroupEnumUnitsInRect(GROUP, bj_mapInitialPlayableArea, Condition(function Trig_LeakTest_Conditions) ) call LeakChecker() endfunction
function InitTrig_LeakTest takes nothing returns nothing call TimerStart(CreateTimer(), .01, true, funciton Trig_LeakTest_Actions) endfunction
Сообщение отредактировал SirNikolas - Вторник, 24 Мая 2011, 20:02:39 |
|
|
|
CHLSN | Дата: Вторник, 24 Мая 2011, 19:52:56 | Сообщение # 17 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| Quote (SirNikolas) GroupEnumUnitsInRect(GROUP, bj_mapInitialPlayableArea, Condition(function Trig_LeakTest_Conditions) ) А здесь тогда куда он записывается?
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
|
|
|
|
SirNikolas | Дата: Вторник, 24 Мая 2011, 19:59:22 | Сообщение # 18 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| В том и дело, что никуда. И если запустить, то ты увидишь на экране вот это:
|
|
|
|
CHLSN | Дата: Вторник, 24 Мая 2011, 20:02:24 | Сообщение # 19 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| Quote (SirNikolas) В том и дело, что никуда. Сцука, американцы криворукие.
Что ж, в любом случае мне еще раз нужно будет пройтись по спеллам, дабы недочеты исправить, заодно это все поправлю, но, ОМГ, это все равно не подчиняется моей логике Condition() => boolexpr ->(передача) GroupEnum... А на деле вот так: Condition() => boolexpr ->(копирование Оо) GroupEnum...
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
Сообщение отредактировал CHLSN - Вторник, 24 Мая 2011, 20:05:35 |
|
|
|
FkoFF | Дата: Вторник, 24 Мая 2011, 23:48:24 | Сообщение # 20 |
Группа: Заблокированные
Сообщений: 4356
Награды: 1
Репутация: 1413
Блокировки:
| Quote (SirNikolas) А почему же не рассмотрен третий способ? Quote (CHLSN) Что ж, в любом случае мне еще раз нужно будет пройтись по спеллам, дабы недочеты исправить, заодно это все поправлю, но, ОМГ, это все равно не подчиняется моей логике создавать бульэкспр - безумие, когда можно просто отфильтровать юнитов внутри цикла. Между прочим сам буль весит больше чем группа (объект) и засоряет память достаточно сильно. По этому втопку булэкспры, размещайте простые условия через if\then.
|
|
|
|
CHLSN | Дата: Среда, 25 Мая 2011, 00:25:12 | Сообщение # 21 |
10 уровень
Группа: Проверенные
Сообщений: 1627
Награды: 0
Репутация: 132
Блокировки:
| FkoFF, а-ля, теоретически, если юнит проходит проверку один раз, и один раз используется, то без разницы где это делать, в цикле или выборе...
FkoFF, само собой (см. ниже)))
Я в контакте и на warcraft3ft.info. Кто может сказать, почему **** дизайнер писал вместо "pt" "px" в CSS, благодаря чему нужно смотреть форум через лупу с Ctrl++?
Сообщение отредактировал CHLSN - Среда, 25 Мая 2011, 13:25:05 |
|
|
|
FkoFF | Дата: Среда, 25 Мая 2011, 01:02:07 | Сообщение # 22 |
Группа: Заблокированные
Сообщений: 4356
Награды: 1
Репутация: 1413
Блокировки:
| CHLSN, удобнее делать это в цикле потому как не надо гемороится с переносом данных в другую функцию через глобалки..
|
|
|
|
|
|
|
|
|
|
|