1 (изменено: avgur, 2012-01-21 23:23:58)

Тема: AHK: Конвеер для горячих клавиш

АНК только осваиваю, вот решил попытаться написать скрипт для любимой игры:

Process, Priority, , High ;скрипт с высоким приоритетом
Critical

$1::
{
SendInput,{F6}
SendInput,{F2}
SendInput,{1}
Sleep, 45
SendInput,{F1}
Sleep, 855
Return
}

$2::
{
SendInput,{F6}
SendInput,{F2}
SendInput,{2}
Sleep, 45
SendInput,{F1}
Sleep, 855
Return
}

$3::
{
SendInput,{F6}
SendInput,{F2}
SendInput,{3}
Sleep, 45
SendInput,{F1}
Sleep, 855
Return
}

$4::
{
SendInput,{F6}
SendInput,{F2}
SendInput,{4}
Sleep, 45
SendInput,{F1}
Sleep, 855
Return
}

$5::
{
SendInput,{F6}
SendInput,{F2}
SendInput,{5}
Sleep, 45
SendInput,{F1}
Sleep, 855
Return
}

Клавиши F1, F2, F6 - это просто тоглы в игре, придающие умениям различный эффект.
Клавиши 1,2,3. . . 10 - собственно умения (в скрипте я привел только 5 штук, чтобы не выкладывать простыню).

Сначала я не знал про Critical и испытывал неудобства при одновременно или быстром последовательном нажатии клавиш 1-5. Но с Critical получился очень приятный эффект "конвеера" или "буфера", т.е. все нажатия клавиш 1-5 выполняются последовательно (в том порядке в каком я их нажимал).
Но мне очень хотелось бы изменить размер этого конвеера до значения 2. Т.е. при последовательном очень быстром нажатии клавиш 1,2,3,4,5 (ну или в любой другой последовательности) выполнялось только 2 потока (если конечно я правильно понимаю значение этого слова), а остальные нажатия просто игнорировались до тех пор пока не выполниться хотябы первое нажатие.
Я прочитал то что нашел про Crtical, #MaxThreads, #MaxThreadsPerHotkey, #MaxThreadsBuffer, Thread interrup, но для моего ума слишком мало простых примеров, чтобы понять куда это вписывать и как можно использовать. Посему прошу помощи более опытных пользователей.

2

Re: AHK: Конвеер для горячих клавиш

Нужно создать свою очередь, например так:

#MaxThreads 2
i:=0
return
#MaxThreadsPerHotkey 2
f1::Add("f1")
f2::Add("f2")
f3::Add("f3")
#MaxThreadsPerHotkey 1
f1()
{
   msgbox f1
}
f2()
{
   msgbox f2
}
f3()
{
   msgbox f3
}
Add(FuncName)
{
   global i, Queue
   if(i>=2)
      return
   Critical On
   i++
   Critical Off
   if(i=1)
   {
	  while(i>0)
	  {
		 %FuncName%()
	     Critical On
	     FuncName := Queue
	     i--
	     Critical Off
	  }
   }
   else
      Queue := FuncName
   return
}

FuncName- первая в очереди функция, она либо уже выполняется, либо сейчас начнёт
Queue- это функция, которая ждёт своей очереди.
i- количество функций в очереди
Add()- добавляет функцию в очередь, если там есть свободные места.

3

Re: AHK: Конвеер для горячих клавиш

Для 2-х поточного конвейера скрипт работает отлично.
Я попытался переделать его для 3-х и более поточного конвейера клавиш:


#MaxThreads 3
global i, Queue
i:=0
return
#MaxThreadsPerHotkey 3
f1::Add("f1")
f2::Add("f2")
f3::Add("f3")
#MaxThreadsPerHotkey 1
f1()
{
   msgbox f1
}
f2()
{
   msgbox f2
}
f3()
{
   msgbox f3
}


Add(FuncName)
{ 							
   if(i>=3)
      return   							
	i:=i+1   							
   if(i=1)
   {
      while(i>0)
      {
        %FuncName%()							
	FuncName := Queue 
	i:=i-1 							
      }
   }
   else	
        Queue := FuncName   
return
}

Но тут получается Queue - это последнее нажатие. Т.е. нажимаю последовательно клавиши 1, 2 и 3, в конвейер идет клавиша 1, потом клавиша 3 и еще раз клавиша 3, вместо той последовательности 1, 2, 3 что нажималась.

4 (изменено: creature.ws, 2012-03-18 04:21:28)

Re: AHK: Конвеер для горячих клавиш


; AHK-L
#MaxThreads 15
#MaxThreadsPerHotkey 15
pipeMaxLength := 15
pipe := []
Return

f1::ShakePipe("f1")
f2::ShakePipe("f2")
f3::ShakePipe("f3")

ShakePipe(FuncName)
{
    global pipe, pipeMaxLength
    if pipe.MaxIndex() >= pipeMaxLength
        Return
    pipe.Insert(FuncName)
    If pipe.Maxindex() = 1
        While pipe.MaxIndex()
            pipe[1].(), pipe.Remove(1)
}
f1()
{
   msgbox f1
}
f2()
{
   msgbox f2
}
f3()
{
   msgbox f3
}

А «несколько конвейеров различной вместительности в одном скрипте» можно, вероятно, использовать так:

Class CQueue
{
    __New(MaxLength) {
        this.MaxLength := MaxLength
    }

    Add(FuncName) {
        if this.MaxIndex() >= this.MaxLength
            Return ""
        this.Insert(FuncName)
        If this.Maxindex() = 1
            While this.MaxIndex()
                this[1].(), this.Remove(1)
    }
}

f1() {
    MsgBox % A_ThisFunc
}
f2() {
    MsgBox % A_ThisFunc
}
f3() {
    MsgBox % A_ThisFunc
}
f4() {
    MsgBox % A_ThisFunc
}
f5() {
    MsgBox % A_ThisFunc
}
f6() {
    MsgBox % A_ThisFunc
}

#MaxThreads 40
#MaxThreadsPerHotkey 20
q1 := new CQueue(4)
q2 := new CQueue(2)

f1::q1.Add("f1")
f2::q1.Add("f2")
f3::q1.Add("f3")
f4::q2.Add("f4")
f5::q2.Add("f5")
f6::q2.Add("f6")

5 (изменено: creature.ws, 2012-04-03 02:03:51)

Re: AHK: Конвеер для горячих клавиш

-del

6

Re: AHK: Конвеер для горячих клавиш

creature.ws
я искренне благодарен за потраченное на меня время.
Пока пробую Ваш первый предложенный скрипт - вроде бы работает хорошо. Теперь вот собираюсь в нем полностью разобраться, не люблю когда не до конца понимаю как оно работает. Думаю еще понадобится добавить горячую клавишу на обнуление конвейера, а так же при if pipe.MaxIndex() > pipeMaxLength заменять последнее в конвейере нажатие на следующее нажатие. Но надеюсь когда-нибудь напишу это сам, честно, не хочу Вас напрягать


ShakePipe(FuncName)
{
    global pipe, pipeMaxLength     ; можно эту строку переместить в начало скрипта?
    if pipe.MaxIndex() >= pipeMaxLength ; pipe.MaxIndex() откуда берется значение индекса?
        Return
    pipe.Insert(FuncName)  ; добавление "нажатия" в конвеер?
    If pipe.Maxindex() = 1
        While pipe.MaxIndex()
            pipe[1].(), pipe.Remove(1) ; pipe[1].() - не представляю что это,  pipe.Remove(1) - уменьшение индекса конвейера на 1 ?
}

Просто с ahk знаком не так давно и даже синтаксис для меня "диковат" после паскале-подобного "кликера", который я юзал раньше.

7 (изменено: creature.ws, 2012-03-18 21:47:50)

Re: AHK: Конвеер для горячих клавиш

Последний скрипт «лучше» первого.

можно эту строку переместить в начало скрипта?

global pipe, pipeMaxLength — объявление глобальных переменных, перемещать вне функции можно, но не нужно.

pipe.MaxIndex() откуда берется значение индекса?

MaxIndex() — встроенный метод возвращающий наибольшее значение индекса обрабатываемого массива.

добавление "нажатия" в конвеер?

pipe[1].() - не представляю что это,  pipe.Remove(1) - уменьшение индекса конвейера на 1 ?

Добавление.  pipe[1].() — запуск функции имя которой сохранено в «ячейке» с индексом 1 массива pipe.
pipe.Remove(1) — удаление значения с индексом 1 (это как выдернуть из стопки тарелок нижнюю)

Но надеюсь когда-нибудь напишу это сам, честно, не хочу Вас напрягать

Примеров достаточно для написания «прямо сейчас»

я искренне благодарен за потраченное на меня время.

Время потрачено на скрипт