1

Тема: Реализация отлова нажатия клавиши и вариативность последующих действий

Всех приветствую. Возникла надобность в скрипте, сначала опишу принцип в игре, чтобы было проще понимать, что хочу от скрипта.
Клавиша пробел  - отвечает за вход в снайперский режим, а повторное ее нажатие за выход из него.
ЛКМ - выстрел.

Я пытаюсь сделать скрипт, чтобы после выстрела в снайперском режиме, осуществлялся выход из него.  В чем вся сложность:  если я вошел в снайперский режим, но не стал стрелять и нажал пробел снова, чтобы выйти из снайперского режима. После 2х дней мучений, я дошел до такой реализации (она выполняет поставленную задачу):


*~$Space::
    ++count
    if count = 1
    {
        SetTimer, LBchek, 50
    }
    else if count = 2
    {
        Reload
    }
return

LBchek:
GetKeyState, state, LButton
if state = D
Gosub, Res
return

Res:
SetTimer, LBchek, Off
Send {Space}
count := 0
return

Так в чем же мой вопрос: мне кажется, что я пошел идиотским путем и сделал быдло код из-за незнания языка. Предложите пожалуйста более грамотную реализацию. Мне таковой кажется что-то в духе:

+ открыть спойлер

*~$Space::
Loop {
    GetKeyState, state, LButton
        if state = D
        break
        Gosub, 1
        else
    GetKeyState, state, Space
        if state = D
        break
        Gosub, 2
}
return

1:
Send {Space}
return

2:
reload
return

*~$Space::
Loop {
    GetKeyState, state, LButton
        if state = D
        Send {Space}
        else
    GetKeyState, state, Space
        if state = D
        break
        Reload
}
return

На самом деле я перевертел наверное сотню вариантов издевательств над теми примерами под спойлером, но ни один не оказался работоспособным.

2

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Лично мне не понятен вопрос.
Опишите последовательность действий, которые хотите, чтоб выполнял скрипт.

3

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

#If M
*~$LButton:: Send % "{Space}" . (M := "")
#If
*~$Space:: M := !M 
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

4

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

serzh82saratov спасибо и рад снова тебя видеть. Я давненько уже не объявлялся на форуме, а сейчас вот снова появилась необходимость. Помню из нашего с тобой общения, ты вроде не программист и ахк для тебя хобби. Подскажи, как ты изучал язык? По мере надобности сделать новый скрипт читал материал, пока не накопилась база? Или сразу залпом читал всю справку и запоминал? Я вот не могу вырасти выше, чем писать простенькие макросы, но просто диву даюсь, какие штуки вы тут ребята делаете. А еще становится очень грустно, когда вижу, что код, который у меня занимает страницу, ты реализовал в 4 строки.

5

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Подскажи, как ты изучал язык?

Мучал всех на форуме кучей глупых вопросов, пока полностью не пойму любезно предоставленные мне решения. Ну и конечно постоянное перечитывание непонятных мест в русской справке.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

6 (изменено: elektrovenik, 2015-02-23 20:39:22)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

serzh82saratov пишет:
#If M
*~$LButton:: Send % "{Space}" . (M := "")
#If
*~$Space:: M := !M 

Cергей, пожалуйста объясни образование каждой строки этого кода и заключенные в них действия.
Сижу читаю справку:

+ открыть спойлер

МояПеременная =     ; Это традиционный метод
МояПеременная := "" ; Это современный метод

; Это традиционный метод чтения:
КопияПеременнойМоеЧисло = %МоеЧисло%
КопияПер1 = %Пер1%
MsgBox Значение Пер1 равно %Пер1%.
    ; Это современный метод:
КопияПеременнойМоеЧисло := МоеЧисло
КопияПер1 := Пер1
MsgBox % "Значение Пер1 равно" . Пер1 . "."

Но ничего не понимаю...

7 (изменено: serzh82saratov, 2015-02-23 21:41:16)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

1. http://ahkscript.org/docs/commands/_If.htm Если выражение = правда, то хоткей действителен. В данном случае "выражение" это значение переменной "M".
2. Тогда при нажатии LButton, также нажимается Space, и переменной M, присваивается пустое значение, то есть то что в кавычках.
3. Закрывает условие для последующих хоткеев.
4. При нажатии Space, переменной M присваивается 1 если она же пуста или равна нулю, или 0 в обратном случае. Это делает оператор "!":

Логическое НЕ (!). Если операнд пуст или равен 0, результатом применения логического НЕ является 1, что означает "истина". Иначе, результат - 0 (ложь). Например: !x or !(y and z). Примечание: слово NOT является синонимом !. Единственным отличием между ними является более высокий приоритет символа !.

M := 1
MsgBox % !M
M := "text"
MsgBox % !M
M := ""
MsgBox % !M
M := 0
MsgBox % !M
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

8 (изменено: elektrovenik, 2015-02-24 01:13:34)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Сергей, тебе удалось в объяснении пропустить самое важное:
% "{Space}" . (M := "") ; тут ты применяешь конкатенцию, чтобы сложить  "% "{Space}" - я не знаю даже как это обозвать, строка, выражение, массив... и переменную М равную нулю. Зачем это делается? Как логически понять действие складывания пусть будет выражения и переменной равной нулю? Что мы получаем на выходе - новую переменную или новое выражение?
Я понимаю строку *~$LButton:: Send {Space} - при нажатии LButton посылается нажатие пробела
Я не понимаю строку *~$LButton:: Send % "{Space}" - при нажатии LButton посылается нажатие и при это что еще происходит?

9 (изменено: serzh82saratov, 2015-02-24 01:40:22)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

*~$LButton:: Send % "{Space}" . (M := "")

тоже что и:

*~$LButton:: 
    Send {Space} 
    M =
    Return

Сделано для сокращения кода.

Send {Space}

Тоже что и:

Send % "{Space}"

переменную М равную нулю.

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

MsgBox % "{Space}" . (M := "")

То есть команде Send передаётся только {Space}. С нулём передавалось бы {Space}0.

MsgBox % "{Space}" . (M := 0)

Так как в конце строки приклеивается пустота:

(M := "")

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

10

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

serzh82saratov пишет:

Сделано для сокращения кода.

Это и вообще спорная оптимизация, а тем более в примерах, даваемых новичку. Тут, по-моему, это просто вредно.

11

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

12

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Оптимизация кода по размеру и есть сокращение. Что касается пользы, то тут лучше всё в своё время. Сначала основное, а потом уже хитрости.

13

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Ну так задача в топике и состоит в сокращении. Так зачем сокращать на половину.  Далее тс сетует на то что  давно не продвигается в изучении анк,  так что думаю что в данном случае всё адекватно,  и тс получил именно то что хотел,  с подробшейшими пояснениями,  и новым опытом.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

14 (изменено: elektrovenik, 2015-02-24 13:42:12)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Еще раз большое спасибо! Сергей объяснил все нормально, достаточно понятно. Трудности возникают действительно при понимании синтаксиса:
Я уже начинаю переводить для себя код программы в слова, чтобы понять, но все-равно трудно.

#If M
*~$LButton:: Send % "{Space}" . (M := "")
#If
*~$Space:: M := !M

Я правильное понимаю, что #If M - начало условия, а #If - конец условия? Т.е. #If к горячей клавише *~$Space:: отношения не имеет? 

#Если переменная М = правда (является истиной)
*~$ Нажатие ЛКМ будет также посылать выражение строка {space} объединенная с переменной М и результат выражения будет пустота. Поэтому будет послано только нажатие ЛКМ.
Условие закрывается
*~$ Нажатие пробела обратит результат в "не пусто", тогда нажатие лкм будет посылать и нажатие пробела.

Но я не понимаю, как оперировать "пусто" и "не пусто"
Вот если М := 0, то !M := 1 - это я понимаю. А если М := "" (пустоте), то чему равно !M ? Не пустоте? То есть тут даже не нужны числа?

Лкм должно посылать выражение объединяющее строку {Space} c пустой переменной М. Результатом такого выражения является пустота. Но посылается то не пустота, а нажатие пробела.
Да и что значит "{space}"? Я понимаю {vk20}, или {space} - это виртуальный код клавиши и ее имя.  Значит, когда я пишу Send {vk20}; Send {Space} - все понятно. А что же тогда Send "{space}". Я посылаю строку с именем клавиши? Попробовав скрипт Send "{space}" на выходе я получил " ". Почему же в скрипте Сергея с нажатием лкм посылается чистое нажатие пробела, без кавычек?

15

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

! — это логический оператор. Соответственно на выходе он даст одно из логических значений: True или False. Пустая переменная в логическом смысле считается False. Значит, обращение её логического смысла оператором ! даст True.

То бишь, учитывая, что ! оперирует логическими величинами, АНК предварительно преобразует пустую переменную в логическое значение. И уже к этому значению применяет !. Пустые и нулевые преобразуются к False, остальные к True.

Лкм должно посылать выражение объединяющее строку {Space} c пустой переменной М. Результатом такого выражения является пустота. Но посылается то не пустота, а нажатие пробела.

Нет, выражения не посылаются. Они разрешаются/вычисляются интерпретатором. И уже то, что получилось в результате решения выражения передаётся команде Send. Здесь это будет строка {Space}, поскольку пустая переменная М содержит пустую строку и ничего не добавляет к результирующей строке.

Т.е. после решения выражения получается код


Send {Space}

Он и будет выполняться.

16 (изменено: elektrovenik, 2015-02-24 18:11:47)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Спасибо YMP, теперь многое стало понятно.

17 (изменено: serzh82saratov, 2015-02-24 22:23:06)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Сергей объяснил все нормально, достаточно понятно.

Я старался, но кто то был не внимателен:

Почему же в скрипте Сергея с нажатием лкм посылается чистое нажатие пробела, без кавычек?

9 пост пишет:

  Знак процента значит что параметр команды представлен как выражение. В выражении, то что в кавычках это текст

---

Но я не понимаю, как оперировать "пусто" и "не пусто"
Вот если М := 0, то !M := 1 - это я понимаю. А если М := "" (пустоте), то чему равно !M ? Не пустоте? То есть тут даже не нужны числа?

7 пост пишет:

Логическое НЕ (!). Если операнд пуст или равен 0, результатом применения логического НЕ является 1

---

Лкм должно посылать выражение объединяющее строку {Space} c пустой переменной М. Результатом такого выражения является пустота. Но посылается то не пустота, а нажатие пробела.

9 пост пишет:

Так как в конце строки приклеивается пустота:

---Ещё раз:

А что же тогда Send "{space}". Я посылаю строку с именем клавиши? Попробовав скрипт Send "{space}" на выходе я получил " ".

Send "{space}"

или:

Send % "{space}"

Если хорошо присмотрется, есть разница?
Почему тогда нет вопроса в том, что не печатается такой текст:

% " "
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

18

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Это полный аналог кода в более "простой записи":

#If M
*~$LButton:: 
    Send {Space} 
    M =
    Return
#If
*~$Space:: 
    If M =
        M = 1
    Else
        M = 0
    Return
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

19 (изменено: elektrovenik, 2015-02-24 22:53:11)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Сергей, я позволю себе тебя поправить: тут причина не невнимательность, а "запаренность". Т.к. твои пояснения были в двух постах (7 и 9), мне приходилось скролить страницу туда-сюда. Помимо этого, ты давал пояснения, в которых код или куски кода скрипта выделял в соответствующий формат "соde". Он в свою очередь разбивает текст, превращая в длинный столб. Поверь, я перечитывал оба поста десятки раз, просто форма подачи несколько подвела и в итоге я терял то, что понимал 5 минут назад.
Это ни в коем случае не умаляет того факта, что ты старался пояснить как мог.

20

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Это ни в коем случае не умаляет того факта, что ты старался пояснить как мог.

Тут главное, не то что я там старался, а в том насколько ты стараешься понять.

просто форма подачи несколько подвела

Ну тут я точно не ас. То есть, в 16 посте, ты уже сообщал о полном понимании?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

21

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Сергей, мне кажется ты меня неверно понял и у тебя ко мне возник негатив, хотя я абсолютно ничего плохого в твой адрес не подумал и тем более не сказал. Фраза "форма подачи подвела" заключала в себе следущее:

+ открыть спойлер
Send A

посылает А

Send B

посылает Б

Send C

посылает С

Loop {
Send A
sleep 50
Send B
sleep 50
Send C
}
return

Цикл, в котором отправляется А, затем пауза 50мс, отпраляется B, снова пауза 50мс, отправляется С

Или форма подачи, которую проще воспринять, т.к. не приходится скролить и отвлекаться.

+ открыть спойлер

Send A - посылает А
Send B - посылает B
Send C - посылает С

Loop {
Send A
sleep 50
Send B
sleep 50
Send C
}
Цикл, в котором отправляется А, затем пауза 50мс, отпраляется B, снова пауза 50мс, отправляется С

22

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

M =

На форуме проскальзывало, что в будущих версиях ahk такая форма записи будет недействительна.
Поэтому стоит привыкать к

M := ""

23

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

Добрый день!
На сколько я понимаю от проблемы скипта дискуссия ушла в обсуждение синтаксиса? но я хотел бы вернуться к скрипту потому как плаваю в этом вопросе.
Автор темы как и я наверно новичок (у меня так вообще AHK первый и единственный опыт)
и проблема возникла из-за отсутствия логически построенного задание на разработку. мне в таких ситуациях помогает построение блок схемы. но можно и в текстовом варианте.

и так прямой порядок:
Необходимо присвоить клавише пробел вхождение в режим прицеливания


*Space :: 
{
Send {RButton}
}

Необходимо левой кнопке мыши присвоить выстрел и выход из прицеливания


*LButton::
{
Send {LButton}
sleep 10
Send {Rbutton}
}

логические ошибки: (точнее неучтенные прямым порядком ситуации)
выход из прицеливания без выстрела

Решение:
отслеживание состояния "в прицеливании / не в прицеливании"
Зависимость присвоения левой кнопки мыши набора команд от состояния прицела.


*Space :: 
{
Send {RButton}
Scopemode := ! Scopemode
}

*LButton::
{
Send {LButton}
If Scopemode = 1
  {
   sleep 10
   Send {Rbutton}
   Scopemode := ! Scopemode
  }
}

Вот что у меня получилось. как и автор темы понимаю что это несколько коряво но зато новичку понятен принцип действия скрипта, и уже теперь можно заниматься его оптимизацией и сокращением.

24 (изменено: elektrovenik, 2015-02-26 20:07:44)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

S.shipilov пишет:

*Space :: 
{
Send {RButton}
Scopemode := ! Scopemode
}

*LButton::
{
Send {LButton}
If Scopemode = 1
  {
   sleep 10
   Send {Rbutton}
   Scopemode := ! Scopemode
  }
}

Вот что у меня получилось. как и автор темы понимаю что это несколько коряво но зато новичку понятен принцип действия скрипта, и уже теперь можно заниматься его оптимизацией и сокращением.

Вы молодец. Тот момент, что сначала идет часть, отвечающая за вариацию (отслеживание состояния прицела), а потом уже часть отвечающая за исполнение - наиболее понятна новичкам (не программистам!!!). Ведь обычный  человек имеет прямой порядок мышления, а не обратный:
Если у меня есть лопата - я иду копать картошку. У меня нет лопаты - мне нечем копать картошку.
а не так:
Я пришел на огород копать картошку - блин, у меня нет лопаты. Ну тогда я пошел обратно, мне же нечем ее копать.

25 (изменено: serzh82saratov, 2015-02-26 21:59:53)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

elektrovenik пишет:

Сергей, мне кажется ты меня неверно понял и у тебя ко мне возник негатив, хотя я абсолютно ничего плохого в твой адрес не подумал и тем более не сказал.

Из каких моих слов навеяло негативом?

S.shipilov пишет:

как и автор темы понимаю что это несколько коряво но зато новичку понятен принцип действия скрипта, и уже теперь можно заниматься его оптимизацией и сокращением.

Ну так ТС сам его и написал, а оптимизировать далее самостоятельно не может, для того и завёл тему. Если делать тоже самое, что делал до этого, то и результат будет прежним.
Если не ясны построчные разъяснения кода, то надо построчно разбирать (вместе) эти самые разъяснения. А не сдаватся:

elektrovenik пишет:

Вообщем ладно парни, Вам огромное спасибо, что пытались до меня донести логический смысл, видимо мне не дано. Буду пользоваться шаблоном, не понимая его работы (что конечно же радости не вызывает).

В 18 посте приведён аналог алгоритма в простейшей записи для понимания новичком, в 19 и 21 посте нет даже намёка на его прочтение.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

26 (изменено: elektrovenik, 2015-02-26 23:24:11)

Re: Реализация отлова нажатия клавиши и вариативность последующих действий

elektrovenik пишет:

Вообщем ладно парни, Вам огромное спасибо, что пытались до меня донести логический смысл, видимо мне не дано. Буду пользоваться шаблоном, не понимая его работы (что конечно же радости не вызывает).

Сергей, эти слова были написаны в тот момент, когда я действительно не мог понять такого построения кода, перечитывая раз за разом твои пояснения из поста 9.
Я хочу подчеркнуть, что дело тут не в том, что объяснения плохи, а в том, что я слишком тугой.
Дальше мне уже было просто стыдно просить объяснить мне это снова или как-то по-другому, я смирился с тем, что моей голове этого не понять.
Но потом я все-таки решился задать те вопросы, которые остались мной не поняты ранее.
На данный момент, благодаря твоим усилиям, а так-же YMP, я действительно полностью понимаю весь код скрипта и примененный синтаксис.
Теперь ставлю для себя иную задачу: нужно наверное пробовать прочитать и хоть примерно усвоить русскую справку по ahk, чтобы примерно знать возможности языка и приемы, применяемые в нем. Потому что меня очень угнетает, что задачу, которая решалась через условие и переменную, я решал через циклы отслеживания нажатия клавиш, что являлось совсем глупым путем решения.

serzh82saratov пишет:

Из каких моих слов навеяло негативом?.

Мне таковыми, показались слова о том, что я не стараюсь понять твоих объяснений. Я не из тех людей, кто задает вопросы просто так. Не будь у меня желания понять что к чему, я бы просто написал "спасибо за скрипт" и стал бы им пользоваться, даже не подумав вникать как он работает.