Добавлен , опубликован
Способ реализации:
Версия Warcraft:
Алгоритм позволяющий отловить вход или выход из воды
Идея использовать цикл внутри каждого потока - nvc123
Обновление
Теперь построение региона происходит во время инициализации карты, а не после начала игры
+ алгоритм быстрее строит регион
Карта-пример прилагается
Время построения региона, при условии что вся карта будет заполнена водой:
64x64 - меньше секунды
128x128 - меньше секунды
256x256 - ~4 секунды
480x480 - ~15 секунд
Алгоритм в виде подключаемой библиотеки:
Событие на вход в воду:
function TriggerRegisterEnterWater takes trigger whichTrigger, boolexpr filter returns event
Событие на выход из воды:
function TriggerRegisterLeaveWater takes trigger whichTrigger, boolexpr filter returns event
cJass
library CustomRegion initializer Init
{
    define regionType = false //false - вода, true - земля
    
    private region CustomRegion;
    private float maxX;
    private float minX;
    private float maxY;
    private float minY;
    private float pointX;
    private float pointY;
    private bool b = true;
    
    public void Run()
    {
        int i = 0;
        loop
        {
            if( IsTerrainPathable(pointX, pointY, PATHING_TYPE_FLOATABILITY) == regionType )
            {
                RegionAddCell( CustomRegion, pointX, pointY );
            }
            
            pointY = pointY-32.;
            if( pointY < minY )
            {
                pointX = pointX-32.;
                pointY = maxY;
            }
            
            i++;
            
            if( pointX < minX )
            {
                b = false;
                break;
            }
            exitwhen( i == 5600 )
        }
        if( b )
        {
            ExecuteFunc("CustomRegion_Run");
        }
    }
    
    private void Init()
    {
        maxX = GetRectMaxX(bj_mapInitialPlayableArea);
        minX = GetRectMinX(bj_mapInitialPlayableArea);
        maxY = GetRectMaxY(bj_mapInitialPlayableArea);
        minY = GetRectMinY(bj_mapInitialPlayableArea);
        pointX = maxX;
        pointY = maxY;
        CustomRegion = CreateRegion();
        
        ExecuteFunc("CustomRegion_Run");
    }
    
    event TriggerRegisterEnterWater(trigger whichTrigger, boolexpr filter)
    {
        return TriggerRegisterEnterRegion( whichTrigger, CustomRegion, filter );
    }
    
    event TriggerRegisterLeaveWater(trigger whichTrigger, boolexpr filter)
    {
        return TriggerRegisterLeaveRegion( whichTrigger, CustomRegion, filter );
    }
}
vJass
library CustomRegion initializer Init
    globals
        private region CustomRegion
        private real maxX
        private real minX
        private real maxY
        private real minY
        private real pointX
        private real pointY
        private boolean b = true
    endglobals
    
    public function Run takes nothing returns nothing
        local integer i = 0
        loop
            if IsTerrainPathable(pointX, pointY, PATHING_TYPE_FLOATABILITY) == false then
                call RegionAddCell( CustomRegion, pointX, pointY )
            endif
            
            set pointY = pointY-32.
            if pointY < minY then
                set pointX = pointX-32.
                set pointY = maxY
            endif
            
            set i = i + 1
            
            if pointX < minX then
                set b = false
                exitwhen true
            endif
            exitwhen( i == 5600 )
        endloop
        if b then
            call ExecuteFunc("CustomRegion_Run")
        endif
    endfunction
    
    private function Init takes nothing returns nothing
        set maxX = GetRectMaxX(bj_mapInitialPlayableArea)
        set minX = GetRectMinX(bj_mapInitialPlayableArea)
        set maxY = GetRectMaxY(bj_mapInitialPlayableArea)
        set minY = GetRectMinY(bj_mapInitialPlayableArea)
        set pointX = maxX
        set pointY = maxY
        set CustomRegion = CreateRegion()
        
        call ExecuteFunc("CustomRegion_Run")
    endfunction
    
    function TriggerRegisterEnterWater takes trigger whichTrigger, boolexpr filter returns event
        return TriggerRegisterEnterRegion( whichTrigger, CustomRegion, filter )
    endfunction
    
    function TriggerRegisterLeaveWater takes trigger whichTrigger, boolexpr filter returns event
        return TriggerRegisterLeaveRegion( whichTrigger, CustomRegion, filter )
    endfunction
endlibrary
`
ОЖИДАНИЕ РЕКЛАМЫ...
28
оформи ещё в виде подключаемой библиотеки
чтобы не приходилось копировать код с карты на карту а просто прописать
include "enter_water.j"
и заяви на публикацию
28
UrsaBoss, нафига триггеры используешь?
есть же таймеры
и можно просто в 1 потоке циклом всё сделать
без периодического триггера
из за периодического триггера так долго и работает
18
nvc123 насчет таймеров подумаю, там просто нужно сделать 5-10 таймеров. Т.к период в 0.00 медленный.
А насчет loop и потока - я с этого и начинал, далее благополучно варкрафт завершал поток из за перегрузки, примерно на 750 цикле
nvc123 +когда я уничтожал таймер, то появлялся баг и он тупо прогонял if( IsTerrainPathable(pointX, pointY, regionType) == false ) по 10-20 раз, я уже с того времени переделал код, через 20-30 минут попробую переделать на таймерах
nvc123 а ещё после loop'ов, я сделал рекурсию через ExecuteFunc как аналог loop, но в этом случае варкрафт просто вылетел без ошибок во время инициализации
nvc123 потестил с таймерами, прокатило когда я начал паузить их вместо того чтобы уничтожать, сравнил с триггером - тоже самое, нагрузка и время почти одинаковы, в случае с таймерами в качестве единицы скорости послужило их количество
Мне кажется лучше давать триггеру ивенты чем вручную в глобалках создавать массив из таймеров по отдельности (т.к если создать таймеры при инициализации, то будет фриз на несколько секунд)
18
nvc123:
UrsaBoss, а нафига много таймеров?
1 достаточно
ага, думаешь он вывезет на 0.00 периоде?)
будет пол часа лепить регион
28
UrsaBoss, 0,00 период ставить не стоит т.к. он будет тормозить основной поток игры
периода 0,03 вполне достаточно
и толку от многих таймеров?
всеравно они последовательно выполняются
причём обработка самих таймеров тратит дополнительное процессорное время
1 таймер с периодом 0,03 работает быстрее чем твоя система
28
и никаких лагов
library CustomRegion initializer init{
    define regionType  = PATHING_TYPE_FLOATABILITY
    
    private region CustomRegion
    private float maxX
    private float minX
    private float maxY
    private float minY
    private float pointX
    private float pointY
    //debug
    private timer time;

    private void run(){
        timer t=GetExpiredTimer();
        int i=0;
        loop{
            if( IsTerrainPathable(pointX, pointY, regionType) == false ){
                RegionAddCell( CustomRegion, pointX, pointY )
            }
            
            pointY = pointY-32.
            if( pointY < minY ){
                pointX = pointX-32.
                pointY = maxY
            }
            
            i++;
            if(pointX < minX){
                DestroyTimer( t );
                //dubug
                BJDebugMsg(R2S(TimerGetElapsed(time)));
                BJDebugMsg("end");
                
                exitwhen true;
            }
            exitwhen (i==4000);
        }
    }

    private void init(){
        timer t=CreateTimer();
        maxX = GetRectMaxX(bj_mapInitialPlayableArea)
        minX = GetRectMinX(bj_mapInitialPlayableArea)
        maxY = GetRectMaxY(bj_mapInitialPlayableArea)
        minY = GetRectMinY(bj_mapInitialPlayableArea)
        pointX = maxX
        pointY = maxY
        CustomRegion = CreateRegion()
        //degug
        time=CreateTimer();
        TimerStart(time, 100500, false, null);
        
        TimerStart(t, 0.03, true, function run);
    }

}
480*480 полностью заполненную водой заносит за 18 секунд
без воды за 13
если на карте нету других действий выполняемых с самого начала при малом периоде (т.е. других подобных систем) то можно уменьшить период до 0,026
если допустимы незначительные лаги то можно увеличить количество операций с 4000 до 5000
18
nvc123 аааа, точно. Можно же было каждый поток по максимуму выжать, ща перезалью код
28
UrsaBoss, и не стоит использовать условия триггеров
на них есть множество ограничений
не только по количеству операций но и по времени работы
если всёже хочешь использовать триггеры то период не нужен т.к. можно использовать TriggerSleepAction(0)
он сбросит счётчик количества операций и будет ожидать пока не появится свободное процессорное время
таким образом лагов не будет вообще т.к. чем сильнее нагружен процессор тем медленнее будет работать система
но в замен скорость работы раза в 3 медленнее чем у таймера
library waitRegion initializer init{
    define regionType  = PATHING_TYPE_FLOATABILITY
    
    private region CustomRegion
    private float maxX
    private float minX
    private float maxY
    private float minY
    private float pointX
    private float pointY
    //debug
    private timer time;
    
    private void run(){
        int i=0;
        trigger t=GetTriggeringTrigger();
        loop{
            if( IsTerrainPathable(pointX, pointY, regionType) == false ){
                RegionAddCell( CustomRegion, pointX, pointY )
            }
            
            pointY = pointY-32.
            if( pointY < minY ){
                pointX = pointX-32.
                pointY = maxY
            }
            
            i++;
            exitwhen pointX < minX;
            if(i==5000){
                i=0;
                TriggerSleepAction(0);
            }
        }
        DestroyTrigger( t );
        //dubug
        BJDebugMsg(R2S(TimerGetElapsed(time)));
        BJDebugMsg("trigg end");
    }

    private void init(){
        trigger t=CreateTrigger();
        maxX = GetRectMaxX(bj_mapInitialPlayableArea)
        minX = GetRectMinX(bj_mapInitialPlayableArea)
        maxY = GetRectMaxY(bj_mapInitialPlayableArea)
        minY = GetRectMinY(bj_mapInitialPlayableArea)
        pointX = maxX
        pointY = maxY
        CustomRegion = CreateRegion()
        //degug
        time=CreateTimer();
        TimerStart(time, 100500, false, null);
        
        TriggerAddAction(t, function run);
        TriggerRegisterTimerEvent(t, 0, false)
    }
    

}
18
nvc123 в перезалитом ресурсе тебя указать как как автора оптимизированного кода?
21
Если зарегистрировать событие на вход в воду еще до инициализации системы, то когда система будет готова к использованию, триггер обновится или останется с недоднланным регионом?
18
ScopteRectuS библиотеки инициализируются раньше чем триггеры
18
ScopteRectuS:
UrsaBoss, но регион то не сразу генерируется.
нужно протестить, пока что не могу, я ресурс переоформляю
21
оптимизированная версия от nvc123 генерируется от 13 до 18 сек.
18
ScopteRectuS:
оптимизированная версия от nvc123 генерируется от 13 до 18 сек.
попробуй вместо 0.03 в периоде поставить 0.02
ScopteRectuS всё, перезалил ресурс, ща пойду тестить
21
Я не об этом, даже если поставить 0.01 ваша система начнет генерировать регион не во время инициализации карты, а только после того, как пройдет 0.01 сек. Если после генерации региона, все триггеры связанные с ним обновятся, то вопросов нет.
18
ScopteRectuS проверил, если добавить ивент после создания региона (даже до заполнения), то работать всё будет даже после заполнения.
Если добавить ивент на вход до CreateRegion(), то он не будет работать.
Поэтому там нормально всё, триггеры после библиотеки инициализируются, значит и после CreateRegion()
CreateRegion() нельзя делать при объявлении глобалки, не знаю почему, но фаталит
28
CreateRegion() нельзя делать при объявлении глобалки, не знаю почему, но фаталит
Да, нельзя, а почему, не знаю.
28
UrsaBoss, ScopteRectuS, 0,02 не советую иначе будут сильные лаги
PT153, UrsaBoss, блок global предназначен для объявления переменных
в нём нельзя вызывать функции
это не только в jass
это в любом структурном яп так
18
nvc123 но InitHashtable() или CreateTimer() и другие нативки же работают))))
Тем более jass не совсем яп, это какой то костыльный скрипт, vJass хоть немного делает его похожим на ЯП
28
Тем более jass не совсем яп, это какой то костыльный скрипт, vJass хоть немного делает его похожим на ЯП
вджас лишь добавляет объекты и всякий сахар
jass вполне нормальный структурный яп
если по твоему jass плохой яп то попробуй асм
Чтобы оставить комментарий, пожалуйста, войдите на сайт.