Учимся рационально Enum'ить декорации

Добавлен , не публикуется
Всем доброго утра/дня/вечера/ночи. Недавно я учил свои заклинания корректно работать с окружающим миром, и, конечно же, встал вопрос: а как же можно делать выборку дектораций без локальных ректов? Напомню, что основополагающая функция выбора декораций - это функция
native EnumDestructablesInRect takes rect r, boolexpr filter, code actionFunc returns nothing
она собирает декорации в определенном ректе. Все сразу же подумали "ну а что такого-то в локальных ректах? создаем, удаляем, эка невидаль". Ан нет, мои друзья, ректы сильно грузят процессор (доходит до такого, что спелл без утечек начинает лагать как первый опыт гуишника по созданию "ультрамегагиперкрутого заклинания"). Я нашел выход (возможно, их может быть и несколько, мне пришел в голову только один). О нем ниже.
Итак, какой же способ я придумал? А все очень просто - мы выбираем все декорации на карте с помощью статичного глобального ректа bj_mapInitialPlayableArea, высчитываем расстояние между взятой декорацией и точкой, от которой идет отсчет, и, если она удовлетворяет нашим требованиям - мы производим с ней действия. Немного полистав учебник геометрии и вспомнив из векторной геометрии, как можно вычислить расстояние между координатами, я написал такую функцию:
function GetDistanceBetweenCoords takes real x1, real y1, real x2, real y2 returns real
     return SquareRoot((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
endfunction
которая возвращает нам расстояние между координатами. Итак, ядро у нас есть, давайте накинем на него "мяска". Полный листинг своего спелла я приводить не буду (вы можете увидеть его в моей карте Simple Shooter под названием MK209), приведу лишь необходимую часть кода:
function Trig_Example_Enum takes nothing returns nothing
     local destructable d = GetEnumDestructable() // Берем декорацию и начинаем проверять расстояние между ней и юнитом в переменной
     if GetDistanceBetweenCoords(GetWidgetX(d), GetWidgetY(d), GetWidgetX(udg_someUnit), GetWidgetY(udg_someUnit)) <= 300. then
         call KillDestructable(d)
     endif
     set d = null
endfunction

function Trig_Example_Conditions takes nothing returns boolean
     if GetSpellAbilityId() == 'ANcl' then
         set udg_someUnit = GetTriggerUnit() // Прошу прощения за глобалку, мне было лень писать пример через хэш :/
         call EnumDestructablesInRect(bj_mapInitialPlayableArea, null, function Trig_Example_Enum) // Набираем декорации и делаем с ними что-нибудь через объявленную функу
     endif
     return false
endfunction
Итак, что мы сделали? Занесли кастера в переменную, выбрали все декорации на карте и после сравнения расстояния убили все декорации в радиусе 300. от юнита. "Систему" можно совершенствовать как угодно (например, через сравнение GetDestructableTypeId() сравнивать тип декорации и уничтожать только деревья), все ограничено только вашей фантазией. К... Кхм... "Статье" я приложил карту-пример. Спасибо всем за внимание, до новых встреч :)
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
37
12 лет назад
0
и конечно же, встал вопрос
дектораций
На статью не тянет, на самом деле. Расскажи побольше различных частных случаев хотябы, или примеров применения. Но и то врятли потянет.
Хотя написано хорошо.
0
9
12 лет назад
0
ScorpioT1000, ошибку исправил, спасибо. Частные случаи я в целом привел, не знаю, что еще можно придумать. На статью не тянет, поэтому я и написал
"Статье"
а по грамматике
и конечно же, встал вопрос
тут надо тогда уж так
и, конечно же, встал вопрос
0
37
12 лет назад
0
если вокруг "и" две запятые, то вторая опускается
хотя тоже спорное правило
кароче на статью это не тянет, только захламлять список статей и рекламировать твою карту.
добавь хотябы временные тесты, сколько занимает времени, чем тестировалось, сравни выборку в ректе и выборку в глобалрекие, но на радиусе как в первом ректе, скрины как ты делаешь выборку, можно же нарисовать схему, как он это делает.
0
9
12 лет назад
0
Увы, я в этом не шарю. В таком случае сносите "статью".
если вокруг "и" две запятые, то вторая опускается
в данном случае это вводная конструкция :)
0
37
12 лет назад
0
Т.е. ты пишешь о том, в чем сам не разбираешься?
Создай небольшой регион, проведи в нем энум 1000 раз, потом отдельно проведи энум твоим способом 1000 раз так, чтобы радиус был равен половине диагонали данного региона, и исходил из его центра, т.е. приблизительно тех же юнитов. Создай таймеры перед запуском и узнавай, сколько времени прошло, после запуска. Выводи это всё, результаты - в статью.
0
9
12 лет назад
0
ScorpioT1000, хорошо, большое спасибо за разъяснения :3
Эн, а что делать, если таймер показывает 0.000? О_О
0
37
12 лет назад
0
Покажи, как ты это делаешь
код
потом всё потрем)
0
9
12 лет назад
Отредактирован Hanabishi
0
Ну... Чур без смеха, расчеты на быстродействие веду впервые
scope Test
{

    include "cj_types.j"
    
    private void Enum()
    {
        KillDestructable(GetEnumDestructable());
    };
    
    callback onUnitSpellEffect('ANcl')
    {
        timer t = CreateTimer();
        int i = 0;
        unit u = GetTriggerUnit();
        rect r = Rect(GetWidgetX(u) - 200., GetWidgetY(u) - 200., GetWidgetX(u) + 200., GetWidgetY(u) + 200.);
        TimerStart(t, .001, true, null)
        while(i < 1000)
        {
            EnumDestructablesInRect(r, null, function Enum);
            i++;
        };
        BJDebugMsg(R2S(TimerGetElapsed(t)));
        RemoveRect(r);
        flush locals;
    };

};
1
26
12 лет назад
1
Глупость.
Вот так намного лучше и быстрее:
globals
    rect r = Rect(-300,-300,300,300)
endglobals

function B takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

function A takes nothing returns nothing
    call MoveRectTo(r,GetUnitX(GetSpellAbilityUnit()),GetUnitX(GetSpellAbilityUnit()))
    call EnumDestructablesInRect(r,null,function B)
endfunction
0
9
12 лет назад
0
Ооокей, я тоже уже об этом подумал -_-
0
18
12 лет назад
0
Hanabishi, твой способ чёто не пашет,да и для муи не придётся ли массив делать
Ty3uK, твой способ как передать параметры в пик нужные мне координаты?,например у меня движется даммик он не в глобалке
ка по мне то легче уже создавать локальный рект и уничтожать,главное что б они уничтожились и не так сильно подвесает оно)
0
9
12 лет назад
0
Klop, я его в хэш сохраняю (дамми) и ок
0
37
12 лет назад
0
TimerStart(t, .001, true, null)
while(i < 1000)
цикл и всё остальное надо запускать в функции, переданной таймеру вместо null
0
18
12 лет назад
0
в хеш а если у меня таймера нету?)
да если декораций много каждой дистанцию проверить это ппц и каждой координаты вызывать
создание локального ректа меньше проблем сделает
0
37
12 лет назад
0
Klop, Hanabishi, это может действительно быстрее работать.
Ty3uK, сделай тесты уже
0
9
12 лет назад
0
Дада, завтра запилю
0
17
12 лет назад
0
хмм попробую использовать.
0
18
12 лет назад
0
так что там тест будет?)
Чтобы оставить комментарий, пожалуйста, войдите на сайт.