1

Тема: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

Неделю пытался разобраться сам, чтобы не надоедать нубскими ворпросами. Однако, еще немного и у меня начнется психоз на этой почве. Выход из положения я нашел и скрипт стабильно работает. Однако, хотелось бы на будущее понять, как можно прервать выполнение цикла именно в тот момент, когда будет достигнуто условие заданное в другом цикле.
Не буду приводить свои варианты, так как их уже было очень много. И ни один не работает так, как хотелось бы. Либо цикл вообще не прерывается, либо прерывается, но не на середине выполнения, а только по окончании всего цикла.
Есть 2 цикла. Один проверяет конкретный пиксель на соответствие нужному цвету:

    Loop
    {
    PixelGetColor, MobHP, 590, 75, BGR
    If MobHP = 0x141416
        Break
    else
        {
        If MobHP <> 0x141416
        Return
        }
    }

Другой цикл, просто набор нажатий клавишь:

    Loop
    {
    SendInput, 3
    Sleep, 1000
    SendInput, q
    Sleep, 2000
    SendInput, 2
    Sleep, 4500
    SendInput, w
    Sleep, 4500
    SendInput, 2
    Sleep, 4200
    SendInput, 3
    Sleep, 1000
    SendInput, e
    Sleep, 4000
    SendInput, 2
    Sleep, 3500
    SendInput, q
    Sleep, 5500
    SendInput, 2
    }
    Gosub, Block3

И вот как их состыковать я уже голову сломал. Нужно, чтобы второй цикл прерывался и переходил к следующему блоку скрипта по достижению условия в первом цикле, то есть, как только цвет пикселя станет соответствовать заданному цвету.
Чего я только не вставлял для этого во второй цикл. Результата только два. Либо второй цикл вообще не прерывается, либо прерывается, но не в середине, когда условие в первом цикле уже достигнуто, а только когда дойдет до конца.
Не могу сказать, что перелопатил весь форум, но честно пытался найти схожую тему. Не нашел. Поэтому и обращаюсь с просьбой помочь понять, как это можно сделать.

2

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

Никак, в AHK два цикла не могут выполняться параллельно, т. к. не поддерживается многопоточность. Можно объединить оба цикла в один — после каждого посыла клавиш во втором цикле проверять цвет пиксела.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3 (изменено: Скиталец, 2012-06-05 15:49:58)

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

teadrinker пишет:

Никак, в AHK два цикла не могут выполняться параллельно, т. к. не поддерживается многопоточность. Можно объединить оба цикла в один — после каждого посыла клавиш во втором цикле проверять цвет пиксела.

Пробовал. Вот один из вариантов:

    Loop
    {
    SendInput, 3
    Sleep, 1000
    SendInput, q
    Sleep, 2000
    SendInput, 2
    PixelGetColor, MobHP, 590, 73, BGR
    If MobHP = 0x131315
        Gosub, Block3
    Sleep, 4500
    SendInput, w
    Sleep, 4500
    SendInput, 2
    PixelGetColor, MobHP, 590, 73, BGR
    If MobHP = 0x131315
        Gosub, Block3
    Sleep, 4200
    SendInput, 3
    Sleep, 1000
    SendInput, e
    Sleep, 4000
    SendInput, 2
    PixelGetColor, MobHP, 590, 73, BGR
    If MobHP = 0x131315
        Gosub, Block3
    Sleep, 3500
    SendInput, q
    Sleep, 5500
    SendInput, 2
    PixelGetColor, MobHP, 590, 73, BGR
    If MobHP = 0x131315
        Gosub, Block3
    }

И все равно переход к блоку 3 происходит только по окончании всего цикла. Хотя цвет пикселя может стать заданным и где нибудь в середине цикла. Не могу сказать, что это очень сильно мешает. Все стабильно работает. Но хочется понять, где делаю что-то не так... Так как хочется, чтобы скрипт жил не самостоятельной жизнью, а делал именно то, что ему написали, без самодеятельности.

4

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

Во-первых, здесь явная синтаксическая ошибка — в команде PixelGetColor опции BGR не существует, в этом формате значение возвращается по умолчанию. Если ты выполнишь такой скрипт, то увидишь, что всё прекрасно работает:

    Loop
    {
    SendInput, 3
    Sleep, 1000
    SendInput, q
    Sleep, 2000
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    
    MobHP := 12345   ; здесь присваиваем значение "вручную"
    If MobHP = 12345
        Gosub, Block3
    
    Sleep, 4500
    SendInput, w
    Sleep, 4500
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        Gosub, Block3
    Sleep, 4200
    SendInput, 3
    Sleep, 1000
    SendInput, e
    Sleep, 4000
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        Gosub, Block3
    Sleep, 3500
    SendInput, q
    Sleep, 5500
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        Gosub, Block3
    }
    
Block3:
    MsgBox, Block3
    return
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5 (изменено: teadrinker, 2012-06-05 17:21:42)

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

Спасибо за пример. Не совсем понятно, для чего присваивание вручную? Если не затруднит, можно чуть подробней? Чтобы знать на будущее.
Что же касается самого скрипта, то он как-то странно себя ведет в таком варианте. Вроде бы, цикл прерывается, НО. Именно из-за этого я и забросил этот путь при самостоятельных изысках. Переход в блок 3 осуществляется даже когда цвет пикселя не соответствует заданному. Причем, как-то совсем непонятно. Выполняется три строки из блока 3 (до перемещение курсора, включительно) и осуществляется возврат в цикл. Чтобы не объяснять на пальцах, приведу скрипт с этим блоком. То, что дальше, там уже никаких вопросов не возникает, все работает нормально.

Block2:
    Loop
    {
    SendInput, 3
    Sleep, 1000
    SendInput, q
    Sleep, 2000
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    MobHP := 0x131315
    If MobHP = 0x131315
        Gosub, Block3
    Sleep, 4500
    SendInput, w
    Sleep, 4500
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        Gosub, Block3
    Sleep, 4200
    SendInput, 3
    Sleep, 1000
    SendInput, e
    Sleep, 4000
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        Gosub, Block3
    Sleep, 3500
    SendInput, q
    Sleep, 5500
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        Gosub, Block3
    }

Block3:
    {
    PixelSearch, Me2X, Me2Y, 380, 155, 680, 345, 0xFF00FF
    SendInput, {Esc}
    MouseClick, left, Me2X - 80, Me2Y + 20
    Sleep, 300
        {
        PixelGetColor, boxdrop, 420, 380, BGR
        Sleep, 300
        If boxdrop = 0x62584D
            {
            MouseClick, left, 530, 370
            Sleep, 3000
            Gosub, Block8
            }
        }
    Sleep, 1000
    PixelSearch, DropX, DropY, Me2X - 10, Me2Y - 55, Me2X + 170, Me2Y + 125, 0x91F5F5, 18
    MouseMove, DropX, DropY
    }
        if ErrorLevel
            Gosub, Block8
        else
            Gosub, Block4

6

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

Скиталец, не нужно бессмысленно цитировать предыдущий пост целиком. Я отредактировал твой пост.

Скиталец пишет:

Не совсем понятно, для чего присваивание вручную?

Только для того, чтобы показать, что если значение соответствует заданному, условие выполняется.

Скиталец пишет:

Что же касается самого скрипта, то он как-то странно себя ведет в таком варианте.

А ты уверен, что правильно используешь команду Gosub? После выполнения подпрограммы, указанной в Gosub, происходит возврат в исходную точку, т. е. обратно в цикл. Возможно, тебе нужно воспользоваться Goto.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

Хотя грамотнее было бы так:

Block2:
    Loop
    {
    SendInput, 3
    Sleep, 1000
    SendInput, q
    Sleep, 2000
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        break
    Sleep, 4500
    SendInput, w
    Sleep, 4500
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        break
    Sleep, 4200
    SendInput, 3
    Sleep, 1000
    SendInput, e
    Sleep, 4000
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        break
    Sleep, 3500
    SendInput, q
    Sleep, 5500
    SendInput, 2
    PixelGetColor, MobHP, 590, 73
    If MobHP = 0x131315
        break
    }
    Goto, Block3
    return
 
Block3:  ; фигурные скобки здесь не нужны
    PixelSearch, Me2X, Me2Y, 380, 155, 680, 345, 0xFF00FF
    SendInput, {Esc}
    MouseClick, left, Me2X - 80, Me2Y + 20
    Sleep, 300
        {
        PixelGetColor, boxdrop, 420, 380, BGR
        Sleep, 300
        If boxdrop = 0x62584D
            {
            MouseClick, left, 530, 370
            Sleep, 3000
            goto, Block8
            }
        }
    Sleep, 1000
    PixelSearch, DropX, DropY, Me2X - 10, Me2Y - 55, Me2X + 170, Me2Y + 125, 0x91F5F5, 18
    MouseMove, DropX, DropY
    if ErrorLevel
        goto, Block8
    else
        goto, Block4
    return
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

teadrinker пишет:

Хотя грамотнее было бы так:

Пробовал я и с командой break. Если с gosab или goto происходят те чудеса, что я описал выше, то с break цикл доходит до конца, хоть ты убейся. Попробовал вставить приведенный Вами скрипт, и увы, все то же самое...
Ладно, все равно спасибо за попытку помочь. Только чую я, что пора мне с этим завязывать, а то скоро уже истерика начнется В принципе, весь скрипт работает стабильно. Только вот никак не могу заставить этот злосчастный цикл прерываться не в конце, а когда нужно. Но да ладно. Еще раз, спасибо

9

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

В случае, когда значение присваивается "вручную", цикл ведь прерывается? Значит, в случае, когда он не желает прерываться, не выполняется условие. Нужно проверять значения, возвращаемые командой PixelGetColor таким образом:

PixelGetColor, MobHP, 590, 73
MsgBox, % MobHP
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

10

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

teadrinker пишет:

В случае, когда значение присваивается "вручную", цикл ведь прерывается? Значит, в случае, когда он не желает прерываться, не выполняется условие. Нужно проверять значения, возвращаемые командой PixelGetColor таким образом:

Меня реально кандрашка скоро хватит... Выдрал из скрипта только эти 2 блока. Исходник все равно не работает. Немного видоизменил скрипт, заменив нажатия клавиш перемещениями курсора, для наглядности. Открыл в ФШ документ, расставил точек и поигрался. В таком виде работает...

Block2:
    Loop
    {
    Sleep, 1000
    MouseMove, 50, 50
    Sleep, 1000
    MouseMove, 100, 50
    Sleep, 1000
    MouseMove, 150, 50
    PixelGetColor, MobHP, 121, 287
    If MobHP = 0x010101
        break
    Sleep, 1000
    MouseMove, 150, 100
    Sleep, 1000
    MouseMove, 150, 150
    PixelGetColor, MobHP, 121, 287
    If MobHP = 0x010101
        break
    Sleep, 1000
    MouseMove, 100, 150
    Sleep, 1000
    MouseMove, 50, 150
    Sleep, 1000
    MouseMove, 50, 100
    PixelGetColor, MobHP, 121, 287
    If MobHP = 0x010101
        break
    Sleep, 1000
    MouseMove, 100, 100
    Sleep, 1000
    MouseMove, 120, 120
    PixelGetColor, MobHP, 121, 287
    If MobHP = 0x010101
        break
    }
    Goto, Block3
    return
 
Block3:
    PixelSearch, Me2X, Me2Y, 0, 0, 1000, 1000, 0xFC40DA
    SendInput, {Esc}
        MouseMove, Me2X - 100, Me2Y - 100
    Sleep, 1000
        {
        PixelGetColor, boxdrop, 400, 400
        Sleep, 1000
        If boxdrop = 0x424242
        {
        MouseMove, 200, 300
        Sleep, 1000
        }
        }
    Sleep, 1000
    PixelSearch, DropX, DropY, 0, 0, 1000, 1000, 0x34FEFF, 18
    MouseMove, DropX, DropY
    Sleep, 1000
    if ErrorLevel
        MouseMove, 20, 40
    else
        MouseMove, 500, 500
    return

Точно, пора завязывать, голова важнее...

11

Re: AHK: Как прервать цикл по достижении заданного условия в другом цикле?

Фуууфффф... Слава Богу... Хоть спокоен теперь за психику... Спасибо за совет, как проверять. Ларчик просто открывался. После нажатия последней клавиши перед проверкой цвета, цвет меняется не мгновенно, а с совсем небольшой задержкой, около 100 миллисекунд. Поставил слип, и все заработало. Спасибо.