1 (изменено: sergeant.coolagin, 2011-09-17 22:32:29)

Тема: AHK: Хатка джойстика и мышь

Мне нужно подкоректировать скрипт. Использую хатку джойстика как мышь. Работает. Мне нужно, чтобы когда я изменяю угол хатки(значение не -1) одновременно мышь смещалась в соответствующую сторону и зажималась какая-то кнопка. Допустим, R. Но когда хатка возвращается на центральную позицию(значение -1), кнопка "R" оставалась зажатой. Действие "R up" надо повесить на другой хоткей.
Вот полный скрипт:

#SingleInstance force
#InstallKeybdHook
#InstallMouseHook




HatDelay = 1

HatMoveBy = 10

HatMoveSpeed = 0


SetTimer, HatMouse, %HatDelay%

SetTimer, JoyPOV1, %HatDelay%

flag := 0


JoyPOV1:
if %flag% = 1
{
Send {R Down}
}
else
{
Return
}
Return

Joy1::
{
flag := 0
}
Return

HatMouse:
   
   GetKeyState, JoyPOV, JoyPOV

   if JoyPOV = -1  ; No angle.
   {

   }
   else
   {
     flag := 1
   }
   if JoyPOV = 0 ; Up
   {
     MouseMove,0,-%HatMoveBy%,%HatMoveSpeed%,R
   }
   else if JoyPOV = 4500 ; up/right
   {
     MouseMove,%HatMoveBy%,-%HatMoveBy%,%HatMoveSpeed%,R
   }
   else if JoyPOV = 9000 ; right
   {
     MouseMove,%HatMoveBy%,0,%HatMoveSpeed%,R
   }
   else if JoyPOV = 13500 ; right/down
   {
     MouseMove,%HatMoveBy%,%HatMoveBy%,%HatMoveSpeed%,R
   }
   else if JoyPOV = 18000 ; down
   {
     MouseMove,0,%HatMoveBy%,%HatMoveSpeed%,R
   }
   else if JoyPOV = 22500 ; down/left
   {
     MouseMove,-%HatMoveBy%,%HatMoveBy%,%HatMoveSpeed%,R
   }
   else if JoyPOV = 27000 ; left
   {
     MouseMove,-%HatMoveBy%,0,%HatMoveSpeed%,R
   }
   else if JoyPOV = 31500 ; left/up
   {
     MouseMove,-%HatMoveBy%,-%HatMoveBy%,%HatMoveSpeed%,R
   }
  
return

Я не понимаю, что я делаю неправильно. Кажется, все правильно. Но кнопка R вообще не жмется. Работает только мышь. Можно вот тут:

 if JoyPOV = -1  ; No angle.
   {

   }
   else
   {
     flag := 1
   }

Вместо "flag := 1" вписать "Send {R Down}" и тогда кнопка R будет работать, когда я буду смещать хатку, но она будет тут же отпускаться, когда я буду возвращать хатку в центральную позицию. А мне надо, чтобы кнопка отпускалась по хоткею отдельно.
Я никак не могу понять, что же я не так сделал. Вроде всё правильно. Если хатка на центре, то ничего не делать. Если хатка в другом положении, то установить значения для пер. "flag" 1. Тут же вступает другой таймер. Если flag = 1, тогда зажать кнопку R и держать. Если флаг неравно 1, то вернуться. Как только Joy1 нажмется после того, как хатка была смещенна, то кнопка R должна быть отпущенна. Но кнопка R даже не хочет жаться.

Помогите мне, пожалуйста. Не пойму где я ошибаюсь...

2

Re: AHK: Хатка джойстика и мышь

Что такое "хатка"?

3 (изменено: sergeant.coolagin, 2011-09-17 22:28:59)

Re: AHK: Хатка джойстика и мышь

ypppu пишет:

Что такое "хатка"?

Хатка - это JoyPOV. Хатка, это такая фиговина сверху на джойстике, которая имеет 9 позиций. На центре(-1), 0 градусов, 45 градусов, 90 градусов, 135 , 180, 225, 270, 315. В скрипте оно пишется еще с двумя нулями.
Вот она:
http://i27.fastpic.ru/big/2011/0917/8b/f37de98c23301333896453e0dcc15f8b.jpeg
http://i31.fastpic.ru/big/2011/0917/4d/ca5f2a42e071b0154c755776fd7df84d.jpeg

Но это не очень-то важно. Вопрос скорее просто про переменные, таймеры, хоткеи и нажатия клавишь. Эту переменную JoyPOV можно заменить какой-то другой. Правда, скрипт после этого станет чуток сложнее...

Может есть какие-то другие решения? Может можно через LOOP или GetKeyState... Не знаю...

4 (изменено: ypppu, 2011-09-29 19:02:40)

Re: AHK: Хатка джойстика и мышь

Насколько я знаю, один таймер прерывает другой, поэтому с трудом представляю, как всё это должно работать. Я использовал бы Loop совместно с GoSub.
Вообще лучше начинать разбираться с малого: написать 5-10 строк, которые стабильно работают, затем постепенно прикручивать всё остальное, каждый раз проверяя, всё ли работает.

5 (изменено: Grey, 2011-09-18 00:44:15)

Re: AHK: Хатка джойстика и мышь

У меня нет джойстика, по этому ни чем конкретно помочь не могу.

sergeant.coolagin пишет:

...Если хатка на центре, то ничего не делать.

По синтаксису пустого блока не должно быть, если ничего не делать, то ставьте Enter, чтобы завершить поток:

...
HatMouse:
   
   GetKeyState, JoyPOV, JoyPOV

   if JoyPOV = -1  ; No angle.
   {
     return
   }
   else
   {
     flag := 1
   }
   if JoyPOV = 0 ; Up
   {
     MouseMove,0,-%HatMoveBy%,%HatMoveSpeed%,R
   }
   else if JoyPOV = 4500 ; up/right
   {
...

если всё же нужно ещё, что-то делать в данной метке, то формулируйте проверку условия по другому:

...
HatMouse:
   
   GetKeyState, JoyPOV, JoyPOV

   if JoyPOV != -1  ; No angle.
   {
      flag := 1
   }
   else if JoyPOV = 0 ; Up
   {
     MouseMove,0,-%HatMoveBy%,%HatMoveSpeed%,R
   }
   else if JoyPOV = 4500 ; up/right
   {
...

6

Re: AHK: Хатка джойстика и мышь

Grey пишет:

По синтаксису пустого блока не должно быть, если ничего не делать, то ставьте Enter, чтобы завершить поток:

Может быть Return?

7

Re: AHK: Хатка джойстика и мышь

Ну да, извиняюсь - опечатался.

8 (изменено: sergeant.coolagin, 2011-09-24 15:22:47)

Re: AHK: Хатка джойстика и мышь

В общем, посидел, переписал сначала скрипт и вроде как бы получилось.

#NoEnv
#SingleInstance force
#InstallKeybdHook
#InstallMouseHook
SendMode DirectInput
SetWorkingDir %A_ScriptDir%

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Global Variabless ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HatDelay = 1 ; Время таймера

HatMoveBy = 10 ; Кол-во пикселей перемещения мыши за 1 цикл

HatMoveSpeed = 0 ; Скорость перемещения

HatMouseLookOn = {O Down}
HatMouseLookOff = {O Up}

Flag := 0

SetTimer, HatMouse, %HatDelay%


HatMouse:

{
GetKeyState, State, JoyPOV
if State = -1 ; Если хатка в центральном положении

    {
    if Flag = 0 ; Если нажмется Joy1 после перемещения хатки.

        {
        Send %HatMouseLookOff%
        }

    else if Flag = 1 ; Если Joy1 еще не был нажат после перемещения хатки

        {
        Send %HatMouseLookOn%
        }

    else ; Если был, то отпустить нажатие кнопки.

        {
        Return
        }
    }
else ; Если хатка сместилась со своего центрального положения.
    {
    Flag := 1
    Send %HatMouseLookOn% ; Включить нажатие кнопки.
    }

if State = 0 ; Если хатку переместить вверх.
    {
    MouseMove, 0, -%HatMoveBy%,%HatMoveSpeed%, R ; Перемещать мышку наверх.
    }

else if State = 4500 ; Если хатку переместить направо/вверх.
    {
    MouseMove, %HatMoveBy%, -%HatMoveBy%, %HatMoveSpeed%, R ; Перемещать мышку направо/вверх.
    }

else if State = 9000 ; Если хатку переместить направо.
    {
    MouseMove, %HatMoveBy%, 0, %HatMoveSpeed%, R ; Перемещать мышку направо.
    }

else if State = 13500 ; Если хатку переместить направо/вниз.
    {
    MouseMove, %HatMoveBy%, %HatMoveBy%, %HatMoveSpeed%, R ; Перемещать мышку направо/вниз.
    }

else if State = 18000 ;  Если хатку переместить вниз.
    {
    MouseMove, 0, %HatMoveBy%, %HatMoveSpeed%, R ; Перемещать мышку вниз.
    }

else if State = 22500 ;  Если хатку переместить налево/вниз.
    {
    MouseMove, -%HatMoveBy%, %HatMoveBy%, %HatMoveSpeed%, R ; Перемещать мышку налево/вниз.
    }

else if State = 27000 ;  Если хатку переместить налево.
    {
    MouseMove, -%HatMoveBy%, 0, %HatMoveSpeed%, R ; Перемещать мышку налево
    }

else if State = 31500 ;  Если хатку переместить налево/вверх.
    {
    MouseMove, -%HatMoveBy%, -%HatMoveBy%, %HatMoveSpeed%, R ; Перемещать мышку
    }


}
Return

Joy1::
{
Flag := 0 ; Отпустить кнопку.
MouseMove, 1024, 576, 0 ; Вернуть указатель мыши в центральное положение
}
Return

Теперь при смещении хатки с центрального положения мышка смещается, зажимается нужная кнопка. После возвращения хатки в центральное положение, кнопка остается зажатой. После нажатия нужного хоткея(Joy1) кнопка перестает быть нажатой. Все работает правильно. Но я использую данный скрипт в играх. А игры используют Send Mode Direct Imput насколько я знаю. Но в данном скрипте мышь перемещается, как по рабочему столу... И когда мышь фактически достигает угла, то и в игре мышь перестает двигаться. Я частично решил эту проблему:

Joy1::
{
Flag := 0 ; Отпустить кнопку.
MouseMove, 1024, 576, 0 ; Вернуть указатель мыши в центральное положение
}
Return

После нажатия хоткея мышь возвращается в центарльное положение на моем мониторе.
Но бесконечно вращаться в игре я не могу. Делаю пару кругов вокруг своей оси и всё. Приходится сбивать хоткеем положение мыши и опять включать хаткой...
Как же сделать правильно, чтобы можно было вращаться бесконечно?
Помогите мне, пожалуйста.
P.S. Я не мазохист, я не играю в шутеры на джое... Мне это действительно нужно.

9

Re: AHK: Хатка джойстика и мышь

sergeant.coolagin пишет:

Но в данном скрипте мышь перемещается, как по рабочему столу...

MouseMove не будет корректно работать в Direct3D, потому как эта команда ориентируется по координатам экрана (DirectDraw), а в полноэкранном приложении (имею ввиду любую игру), там система координат исчисляется в трёхмерной проекции. Думаю надо посмотреть в сторону mouse_event, пример:

SetBatchLines, -1
var:=10, dvar:=10
Return

vkbb:: ; +
   var+=dvar
   ToolTip, % "add var: "var, 640, 512
   Sleep, 750
   ToolTip
   Return
RCtrl & vkbb::
   var-=dvar
   ToolTip, % "sub var: "var, 640, 512
   Sleep, 750
   ToolTip
   Return

/*
vkbd:: ; -
   var2+=dvar
   ToolTip, % "add var2: "var2, 640, 512
   Sleep, 750
   ToolTip
   Return
RCtrl & vkbd::
   var2-=dvar
   ToolTip, % "sub var2: "var2, 640, 512
   Sleep, 750
   ToolTip
   Return

vk08:: ; backspace
   var3+=dvar
   ToolTip, % "add var3: "var3, 640, 512
   Sleep, 750
   ToolTip
   Return
RCtrl & vk08::
   var3-=dvar
   ToolTip, % "sub var3: "var3, 640, 512
   Sleep, 750
   ToolTip
   Return
*/

F12::
   KeyWait, F12
   rctrlf12i++
   SetTimer, counterrctrlf12, -350
   Return
counterrctrlf12:
   If rctrlf12i=1
      SetTimer, action1rctrlf12, -10
   Else If rctrlf12i=2
      SetTimer, action2rctrlf12, -10
   Else If rctrlf12i=3
      SetTimer, action3rctrlf12, -10
   Else If rctrlf12i=4
      SetTimer, action4rctrlf12, -10
   rctrlf12i=
   Return
action1rctrlf12: ; 1
   dvar:=1
   ToolTip, % "dvar is: "dvar, 640, 512
   Sleep, 750
   ToolTip
   Return
action2rctrlf12: ; 10
   dvar:=10
   ToolTip, % "dvar is: "dvar, 640, 512
   Sleep, 750
   ToolTip
   Return
action3rctrlf12: ; 100
   dvar:=100
   ToolTip, % "dvar is: "dvar, 640, 512
   Sleep, 750
   ToolTip
   Return
action4rctrlf12: ; 500
   dvar:=500
   ToolTip, % "dvar is: "dvar, 640, 512
   Sleep, 750
   ToolTip
   Return

Right:: ; поворот в право
   While GetKeyState("Right", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, var
                              , Int, 0
                              , UInt, 0
                              , Int, 0)
         Sleep, 30
      }
   Return

Left:: ; поворот в лево
   While GetKeyState("Left", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, -var
                              , Int, 0
                              , UInt, 0
                              , Int, 0)
         Sleep, 30
      }
   Return

F5::Reload
Esc::ExitApp

Эффект величины значение переменной var напрямую зависит от резолюции монитора, и уровня чувствительности в настройках игры (будет работать и в DirectDraw, только эффект от величины значения будет разный). Для изменения переменной клавиши: +, - и бэкспэйс, количество быстрых нажатий на клавишу ф12 задаёт величину значения переменной (четыре позиции: 1, 10, 100, 500).

10 (изменено: sergeant.coolagin, 2011-09-29 16:42:13)

Re: AHK: Хатка джойстика и мышь

Написал такой скрипт:

SetBatchLines, -1
XAxis:=700, ; Скорость передвижения мыши по горизонтали.
YAxis:=700 ; Скорость передвижения мыши по вертикали.
SleepTime:=30
Flag:=0
Flag2:=0
Return




LButton:: ;Кнопка деактивации осмотра.
{
if Flag2 = 1
{
Send, {RButton Up}{vk01 Down} ; Lbutton
}
else
{
Send, {vk01 Down} ; Lbutton
}
KeyWait, vk01 ; Lbutton
Send, {vk01 Up} ; Lbutton
Flag2:= 0
}
Return


F5:: ; Смотреть влево/вверх
Send {RButton down}
Flag2:= 1
   While GetKeyState("F5", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, -XAxis
                              , Int, -YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
      }
   Return




F6:: ; Смотреть вверх
Send {RButton down}
Flag2:= 1
   While GetKeyState("F6", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, 0
                              , Int, -YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
      }
   Return




F7:: ; Смотреть вправо/вверх
Send {RButton down}
Flag2:= 1
   While GetKeyState("F7", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, XAxis
                              , Int, -YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
      }
   Return




F8:: ; Смотреть вправо
Send {RButton down}
Flag2:= 1
   While GetKeyState("F8", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, XAxis
                              , Int, 0
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
      }
   Return




F9:: ; Смотреть вправо/вниз
Send {RButton down}
Flag2:= 1
   While GetKeyState("F9", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, XAxis
                              , Int, YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
      }
   Return




F10:: ; Смотреть вниз
Send {RButton down}
Flag2:= 1
   While GetKeyState("F10", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, 0
                              , Int, YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
      }
   Return




F11:: ; Смотреть влево/вниз
Send {RButton down}
Flag2:= 1
   While GetKeyState("F11", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, -XAxis
                              , Int, YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
      }
   Return




F12:: ; Смотреть влево
Send {RButton down}
Flag2:= 1
   While GetKeyState("F12", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, -XAxis
                              , Int, 0
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
      }
   Return

Скрипт работает, но я не могу поставить активацию движения непосредственно на хатку.
Я переназначил хатнку на кнопки с F5 до F12 соответственно в драйвере джойстика. Получается не так как должно быть.
Как сделать так, чтобы было что-то вроде:

JoyPOV 31500:: ; Смотреть влево/вверх
Send {RButton down}
Flag2:= 1
   While GetKeyState("F5", "P")
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, -XAxis
                              , Int, -YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
      }
   Return

Как сделать из хатки хоткей? Через таймер думаете получится? Ща попробую. Но все-таки можно ли сделать непосредственно хоткей из хатки? Помогите написать скрипт правильно.

11

Re: AHK: Хатка джойстика и мышь

sergeant.coolagin пишет:

Как сделать из хатки хоткей?

Это не типичный случай, когда у клавиши есть только состояние нажатия/отжатия, или состояние в которое она переключена (шифт и т.д.). У клавиши JoyPOV есть текущее значение которое считывается командой GeKeyState и присваивается переменной (в скрипте POV).

YAxis:=XAxis:=700, SleepTime:=30, Flag2:=Flag:=0
SetTimer, WatchHatKey, 250, Return

LButton::
   If Flag2=1
      Send, {RButton Up}{LButton Down}
   Else
      Send, {LButton Down}
   KeyWait, LButton
   Send, {LButton Up}
   Flag2:=0
   Return

WatchHatKey:
   GetKeyState, POV, JoyPOV
   If POV=-1
      Return
   Else If Pov=0
   {
      Send, {RButton Down}
      Flag2:=1
      Loop
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, 0
                              , Int, -YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
         GetKeyState, POV, JoyPOV
         If POV<>0
            Break
      }
   }
   Else If POV=4500
   {
      Send, {RButton Down}
      Flag2:=1
      Loop
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, XAxis
                              , Int, -YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
         GetKeyState, POV, JoyPOV
         If POV<>4500
            Break
      }
   }
   Else If POV=9000
   {
      Send, {RButton Down}
      Flag2:=1
      Loop
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, XAxis
                              , Int, 0
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
         GetKeyState, POV, JoyPOV
         If POV<>9000
            Break
      }
   }
   Else If POV=13500
   {
      Send, {RButton Down}
      Flag2:=1
      Loop
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, XAxis
                              , Int, YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
         GetKeyState, POV, JoyPOV
         If POV<>13500
            Break
      }
   }
   Else If POV=18000
   {
      Send, {RButton Down}
      Flag2:=1
      Loop
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, 0
                              , Int, YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
         GetKeyState, POV, JoyPOV
         If POV<>18000
            Break
      }
   }
   Else If POV=22500
   {
      Send, {RButton Down}
      Flag2:=1
      Loop
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, -XAxis
                              , Int, YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
         GetKeyState, POV, JoyPOV
         If POV<>22500
            Break
      }
   }
   Else If POV=27000
   {
      Send, {RButton Down}
      Flag2:=1
      Loop
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, -XAxis
                              , Int, 0
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
         GetKeyState, POV, JoyPOV
         If POV<>27000
            Break
      }
   }
   Else If POV=31500
   {
      Send, {RButton Down}
      Flag2:=1
      Loop
      {
         DllCall("mouse_event", UInt, 0x1
                              , Int, -XAxis
                              , Int, -YAxis
                              , UInt, 0
                              , Int, 0)
         Sleep, SleepTime
         GetKeyState, POV, JoyPOV
         If POV<>13500
            Break
      }
   }
   Return

12

Re: AHK: Хатка джойстика и мышь

Спасибо. У меня еще вопрос. А как работает timer вместе с loop?
выполняется программа, потом когда доходит до цикла, запускается цикл и выполняется определенное поличество раз, когда цикл закончился, то остальная часть программы внутри таймера выполняется, заканчивается и только потом таймер начинает выполнение программы заново. Но все это время таймер ждет конца выполнения программы.
Или так, выполняется программа, потом когда доходит до цикла, запускается цикл и выполняется определенное количетсво раз, в каком-то месте когда время таймера истекает, он опять запускает эту же самую программу, доходит до цикла и уже выполняется не 1 а целых 2 цикла и так по нарастающей...
А то я правильную работу таймера понять не могу...

13

Re: AHK: Хатка джойстика и мышь

Думаю, что работает по принципу первого варианта, как пример:

SetTimer, Test, 10
Return

Test:
   Loop, 3
      MsgBox, 262208, Test, % A_Index, 1
;      TrayTip, Test, % A_Index,, 1
   Return

Таймер настроен на быструю частоту, но каждое из окон сообщения отображается секунду, а вот если закомментировать строку с MsgBox, и раскомментировать с TrayTip у которого нет задежки, то можно увидеть настоящую скорость работы таймера.