오토핫키(AutoHotKey) 기초강좌 #12 - 매크로 제작 예제




 전체 강좌

 1강 - 오토핫키(AutoHotKey) 소개

 2강 - 프로그래밍의 시작, GUI 만들기

 3강 - 매크로 프로그래밍 1 (Button, Loop, if 사용법)

 4강 - 매크로 프로그래밍 2 (ImageSearch, Send, Sleep)

 5강 - 매크로 프로그래밍 3 (Gui Submit)

 6강 - 매크로 만들기 응용 1 (if 응용, CoordMode)

 7강 - 매크로 만들기 응용 2 (핫키, if 응용)

 8강 - 매크로 만들기 응용 3 (While, GUI와 변수의 활용 1)

 9강 - 매크로 만들기 응용 4 (GUI와 변수의 활용 2)

 10강 - 매크로 만들기 응용 5 (함수1)

 11강 - 매크로 만들기 응용 6 (함수2)

 12강 - 매크로 제작 예제

















안녕하세요~ 킴영감입니다.


지난 시간을 끝으로 모바일 게임 매크로를 제작하기 위한 기본적인 것들을 배웠습니다.


이번 강좌에는 지난 강좌 끝에 말씀드린 것 처럼 메크로를 제작하기 위한 팁을 드리려고 합니다.


이전 강좌를 모두 이해하신 분들은 바로 응용하실 수 있을 것이라고 생각합니다.


그럼 마지막 강좌를 시작하겠습니다.


1. 순서도 그리기


두번째 강좌에서 했던 것 처럼 오늘 작성할 스크립트의 순서도를 그려보겠습니다.



대부분의 게임들이 여러개의 컨텐츠를 가지고 있기 때문에 두 가지 컨텐츠를 위 그림과 같이 반복하고 대기시간을 가지도록 만들어 보겠습니다. 컨텐츠1과 컨텐츠2에 들어갈 스크립트의 순서도를 아래와 같이 그렸습니다.



화면을 검색하는 함수를 만들어 어느화면에 있는지 판단하고 각 화면에서 클릭해야 하는 버튼을 클릭하는 것이 기본 틀입니다. 반복해서 돌다가 열쇠나 에너지 부족 등으로 컨텐츠를 종료하는 부분이 있습니다.


그럼 함께 스크립트를 작성해 보겠습니다.


2. GUI 구성


GUI는 매크로의 상태를 나타낼 수 있는 Text, 대기시간을 나타내는 Text, 클리어횟수를 나타내는 Text, 시작과 종료를 하는 Button으로 구성했습니다. 코드는 아래와 같습니다.



기존 강좌에서 실습한 내용과 비슷하기 때문에 설명은 안드려도 되겠죠??^^


그럼 다음으로 넘아갑니다~



3. 매크로 스크립트


여기부터는 스크립트를 보면서 설명드리겠습니다. 위에 있는 순서도는 아래와 같이 작성할 수 있습니다.



우선 어느화면인지 판단하는 함수에서 받아올 결과를 저장할 변수인 "화면"이라는 변수를 만들었습니다. While 내부의 첫번째 줄에 있는 "화면 := 화면검색()"부분이 어느화면인지 받아오는 부분입니다. 그 다음으로 if를 사용해서 화면인식에서 받아온 결과에 따라 다른 이미지를 찾도록 구성했습니다. 화면 3일때는 팝업에 의해서 화면이 가려진 상태를 의미한다고 생각하시면 됩니다. 예를 들어 열쇠를 모두 사용했다는 팝업이 뜨면 "화면3에 해당하는 버튼"이 팝업을 단는 버튼이 될 수 있고 이후에 "컨텐츠2"를 도는 함수를 실행합니다. 


"컨텐츠2"를 다 돌고 다시 돌아오면 다음줄에 있는 대기시간에 원하는 만큼의 시간을 입력하고 (ms단위), 대기시간 만큼 대기하게 됩니다. 대기시간동안 대기하는 부분의 코는 While의 조건으로 "대기시간이 0보다 클때" 라고 작성한 뒤 위에서 3001로 정해준 대기시간을 1씩 빼게되면 1초씩 3000번을 대기하는 것이기 때문에 3000초를 대기하는 것입니다. Gui, Submit을 이용해서 1초마다 대기시간을 표시하는 화면을 업데이트 해주게 됩니다.


화면검색1 함수는 아래와 같습니다.



화면검색은 어느화면인지 판단만 하면 되기 때문에 마우스를 클릭하는 부분은 뺐습니다. 각 화면마다 숫자를 할당하고 그 화면에만 있는 이미지를 찾으면 그에 할당된 숫자를 리턴하게 됩니다. (이게 핵심적인 부분입니다.)


다음으로 "컨텐츠2" 함수와 컨텐츠2에서 사용할 "화면검색2" 함수를 보여드리겠습니다.


위 그림에 있는 if와 else if의 조건으로 들어가 있는 화면 = 4, 화면 = 5, 화면 = 6 을 화면2 = 4, 화면2 = 5, 화면2 = 6 으로 고치셔야 합니다ㅠ 혼동을 드려 죄송합니다ㅠ



"컨텐츠2" 함수는 이미지를 찾아서 버튼을 클릭합니다. 여기서는 열쇠를 모두 다 썼을 경우에 탈출하는 부분을 화면이 6일때로 해 놓았습니다. 매인에서 "컨텐츠2"라는 함수를 호출한 것이기 때문에 돌아가기 위해서는 return을 사용하셔야 합니다.


아래의 "화면검색2" 는 2번 컨텐츠의 화면을 찾는 함수입니다.


마지막으로 나머지 부분의 스크립트는 아래와 같습니다.



종료버튼과 F2 를 이용한 멈춤 기능을 구현 한 것입니다.


이렇게 해서 12번째 강좌가 모두 끝났습니다.



오늘 강좌는 이때 까지 배운 내용들을 가지고 어떻게 매크로를 만들 수 있는지에 대한 가이드라인을 보여드린 것이라 할 수 있습니다. 적절히 응용하신다면 여러분들이 매크로를 만드는데 큰 틀이 될 수 있습니다. 추가적으로 상태를 나타내는 변수를 활용한다면 정말 멋진 매크로를 구현 하실 수 있을 것입니다.


12강동안 제 강좌를 보신분들 모두에게 감사드리고 꼭 매크로 제작에 성공하시기를 바랍니다.


이것으로 오토핫키 기초강좌를 마치며, 저는 조금 휴식기간을 가진 뒤에 "오토핫키에서 매크로를 만드는데 필요한 중급정도 기능에 관한 사용법 강좌"로 돌아오겠습니다.


감사합니다.



블로그 이미지

킴영감

프로그래밍과 게임공략, 게임과 관련된 프로그램에 대한 내용을 다룹니다.

댓글을 달아 주세요

  • 이전 댓글 더보기
  • 지나가는나그네 2015.11.17 23:47  댓글주소  수정/삭제  댓글쓰기

    비슷 한걸 찾았네요.
    http://autohotkey.com/board/topic/91678-pause-settimer/

    제일 하단에 Person93 라는 회원이 올린 스크립트입니다.

    PasueSettimer핫키를 누르면 SettimerABC의 카운트는 설정된 값까지 상승하되, 지정된 명령은 대기합니다.

    사용자가 임의로 정한 시간에(PauseSettimer 누른후 10초 후든 20초후든) ResumeTimmer를 핫키를 누르면 대기중이던 ABC의 명령이 동작.

  • 지나가는나그네 2015.11.18 14:18  댓글주소  수정/삭제  댓글쓰기

    A_Index 사용벙에 관해서 궁금한게 있습니다.
    이미지1.bmp ~ 이미지10.bmp 있는데요.
    이미지1 ~ 이미지 10까지만 찾으려고 하는데
    아래 스크립트에서는 11,12,13,14 ~ 9999 무한대로 찾고 있네요.

    Loop에 10을 주는거 말고 어떤 조건을 줘야지 10까지만 찾을 수 있을까요?


    ;-----------------------------
    Loop
    {
    nt := + A_Index

    이미지서치("폴더\폴더\이미지" nt ".bmp)
    }
    return

    • 킴영감 2015.11.19 10:14 신고  댓글주소  수정/삭제

      제일 간단한 방법이 횟수를 카운트하는 변수를 만들고 한번 수행할때마다 변수에 1씩 더해줘서 10이 되면 탈출하도록 하시는 것입니다.
      아래와 같이 코드를 작성하시면 됩니다.
      카운트변수 := 1
      Loop
      {
      nt := + A_Index
      이미지서치("폴더폴더이미지" nt ".bmp)
      카운트변수 := 카운트변수 + 1
      if(카운트변수 > 10)
      {
      break
      }
      }
      return

  • 2015.11.25 20:05  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • 킴영감 2015.11.28 14:27 신고  댓글주소  수정/삭제

      함수에 대해서 공부가 필요하신듯 하네요^^ 기초강좌 10, 11강을 보시면 조금 도움이 될 것 같습니다.
      코드상에서 클릭{FoundX, FoundY} 이부분을 클릭(FoundX, FoundY)로 바꿔주시면 됩니다^^

    • hamtal 2015.11.28 17:16 신고  댓글주소  수정/삭제

      감사합니다...간단한걸 틀려놨었네요... 비활성이란건 처음봐서 옮기다가... 잘 배우고 있습니다... 또 막힌다면 신세 좀 져도 괜찮을까요?

    • 킴영감 2015.11.28 17:18 신고  댓글주소  수정/삭제

      궁금한점 있으시면 언제든지 댓글로 문의 주시면 됩니다~^^

  • 배태웅 2015.12.01 01:26  댓글주소  수정/삭제  댓글쓰기

    설명이 매우 상세하게 되어있네요 프로그램 따라하다 보니 재밌네요.. 그런에 오류 찾는게 힘드네요.. nohide를 써야하는데 nohid 라고 치니깐 창이 사라져버리고..ㅎㅎㅎ 뭐지 하면서 다 찾아보았네요 ㅠㅠ
    지금 5강까지 따라왔는데 신기하네요 ㅎㅎ 혹시 이 툴을 exe 실행파일로는 못만드나요??

  • 감사합니다 2015.12.06 18:38  댓글주소  수정/삭제  댓글쓰기

    오토핫키 처음 접하고 인터넷 뒤지면서 loop,if,이미지서치정도만 가지고 만드느라 너무 힘들었는데 함수호출이나 while 등등 접하니까 정말 신세계네요. 감사합니다

  • 궁금합니다. 2016.01.20 10:48  댓글주소  수정/삭제  댓글쓰기


    card := false
    cardchoice := false
    loop
    {

    pixelsearch, Px, Py, 954, 684,1130, 780, 0x00AADE, 3, fast ; 강화 선택창이 활성화
    if (ErrorLevel = 0) ;
    {
    card := true
    }
    if (ErrorLevel = 1) ;
    {
    card := false
    }

    while(card := true)
    {
    MouseClick, left, 1057, 738
    }
    }

    이렇게 했는데요
    왜 무한대로 바로 와일문으로 가버리죠? 분명히 픽셀서치에서 경우가 false인데요..

  • 질문 2016.02.06 16:21  댓글주소  수정/삭제  댓글쓰기

    게임안에서
    Send, {Enter} 가 먹히지 않는데 이유가 무엇인가요?

    • 킴영감 2016.02.07 21:19 신고  댓글주소  수정/삭제

      키보드 입력은 대상 프로그램이 활성화 되어있어야 합니다.
      프로그램이 활성화 되어있는데도 안먹힌다면 무슨프로그램을 사용하시는지 알려주시면 테스트해보겠습니다.^^

    • 질문 2016.02.10 02:50  댓글주소  수정/삭제

      말하시는 프로그램이 게임프로그램인가요?
      아니면 오토핫키 프로그램인가요?

    • 킴영감 2016.02.10 03:05 신고  댓글주소  수정/삭제

      게임을 돌리는 프로그램이요~

    • 2016.02.10 14:30  댓글주소  수정/삭제

      비밀댓글입니다

    • 킴영감 2016.02.11 00:57 신고  댓글주소  수정/삭제

      음 다른 키보드 입력이 된다면 enter키가 다른 기능으로 사용되고 있어서 그럴 가능성이 높습니다.
      만약 enter키를 직접 누르셨을 때 원하는 동작을 한다면 뭐가 문제인지 확인을 해봐야겠지만 직접 누르실때에도 안된다면 게임상에서 메세지를 보내는 기능을 하는 키를 찾거나 버튼의 이미지를 찾아서 클릭하도록 하는 방법이 있습니다.

    • 질문 2016.02.16 16:52  댓글주소  수정/삭제

      다른분에게 물어보니 게임안에서 enter가 버그로되었다고하네요
      빠른답변감사합니다

  • send 2016.02.22 14:55  댓글주소  수정/삭제  댓글쓰기

    혹시 키보드를 치는 명령어가 Send 말고 다른것이 있나요?

  • 2016.02.27 11:19  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • 킴영감 2016.02.27 15:45 신고  댓글주소  수정/삭제

      우선 listview, ifinstring, lv_add 등 명령어에 대한 이해가 부족하신 것 같습니다. 각 명령어들의 사용방법을 먼저 숙지하시고 정확한 사용방법에 따라 사용하는 것이 올바른 순서입니다.

      리스트뷰에 있는 각각의 항목에 데이터를 넣으려면 ,(콤마)로 구분되어야합니다. 하지만 수박(과일) 이라고 되어있는 것을 그냥 lv_add로 추가하셨으니 당연히 Name 부분에 모두 들어가는 것입니다.

      질문하신 내용을 구현할 수 있는 방법은 많지만 우선 처음에 말씀드렸던 것처럼 사용하시는 각 명령어의 사용방법과 역할 또는 의미를 먼저 공부하시고 시도하시는 것이 좋을 것 같습니다.^^

    • 킴영감 2016.02.27 15:52 신고  댓글주소  수정/삭제

      힌트를 드리자면 지금 작성되어 있는 스크립트에서
      ifinstring,a_loopfield,%seach%
      {
      lv_add("",a_loopfield)
      }
      이 부분을 수정하시면 간단하게 구현할 수 있습니다.

      만약 수박을 찾으면 a_loopfield에 "수박(과일)" 이 들어가 있을 것이고 이것을 다시 loop와 ifinstring을 사용해서 "수박"과 "과일"로 분리해서 Lv_Add로 추가해주면 되는 것입니다.^^

  • 2016.02.27 19:47  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • 킴영감 2016.02.27 23:06 신고  댓글주소  수정/삭제

      제가 힌트를 아무리 많이 드린다고 원하시는 프로그램을 만들수 있는것이 아니기 때문에 해당 명령어를 공부하시라고 말씀드린 것입니다.

      위에서 말씀하신 것으로 예를 들면 lv_add("",a_loopfield,?)로 한다고 수가 Name에 들어가고 나머지부분이 ?부분에 information 열로 들어가게 되는 것이 아닙니다. 완전 잘못 생각하고 계신다는 것입니다.ㅠ
      적어도 각 명령어의 사용법 정도는 아셔야 힌트를 드리는데 이렇게 질문하시면 저도 모르는 부분은 찾아보고 테스트 해보고 시간들 들여서 답변을 드리는데 보람이 없습니다.ㅠ

      이번 한번은 답변을 드릴테니 보시고 꼭 공부해 보시기 바랍니다.

      gosub,load
      Gui, Add, ListView, x62 y40 w590 h260 ,Name | information
      Gui, Add, Edit, x702 y70 w110 h20 vseach,
      Gui, Add, Button, x712 y90 w100 h30 , 검색
      Gui, Show, x127 y87 h383 w1044
      Gui Show
      Return


      guiclose:
      ExitApp
      return

      button검색:
      {
      LV_Delete()
      gui,submit,nohide
      loop, parse , fl0, `n
      {
      ifinstring,a_loopfield,%seach%
      {
      ;정보 = a_loopfield
      loop, parse, a_loopfield, `,
      {
      if(A_Index = 1)
      {
      name = %A_LoopField%
      }
      else
      {
      info = %A_LoopField%
      }
      }
      LV_Add("", name, info)
      }
      }
      }
      return

      load:
      fl0=
      (
      감자,채소
      수박,과일
      양파,채소
      오이,채소
      호박,채소
      사과,과일
      )
      return

      어딜 가셔도 이렇게 만들어 주는 곳은 없을 것입니다.ㅠ 제가 시간을 들여서 답을 알려드린것에 보람을 느낄 수 있게 꼭 공부를 하시기 바랍니다.^^

      제 블로그나 홈페이지에 프로그래밍에 대한 기초적인 내용들을 강좌로 올려놓았으니 기초강좌부터 보시고 모두 이해하신 다음에야 원하는 프로그램을 수월하게 만들 수 있을 것입니다.

  • 2016.02.28 10:25  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  • 마틴 2016.12.09 08:21  댓글주소  수정/삭제  댓글쓰기

    안녕하세요, 강좌 잘 보고 갑니다.
    간단명료하게 필요한 것만 정리해주셔서 너무나 좋았고
    밤새 정주행했습니다. 좋은 강의 감사합니다.

  • 2016.12.18 20:17  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  • 유능제강 2017.04.06 15:27  댓글주소  수정/삭제  댓글쓰기

    강좌 잘 봤습니다^^
    많은 부분을 배웠다고 생각하네요 ㅎㅎ
    언제쯤 중급으로 돌아오시나요?ㅎ

  • 2018.01.23 11:45  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  • 2018.01.24 16:27  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  • 2018.01.25 03:27  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • 킴영감 2018.01.25 11:17 신고  댓글주소  수정/삭제

      settimer는 발동시키는게 아니라 설정하는겁니다. 개념을 다시 잡으셔야할 것 같네요ㅠ 유튜브 강의를 다시한번 보시면 좋을 것 같습니다^^ 이번 질문의 답변을 드리자면 H1과 Loop사이에 settimer가 있어야 됩니다. 원리를 이해하는것이 중요하니 강의를 꼭 다시 보시기 바랍니다^^

  • 2018.01.26 11:28  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • 킴영감 2018.01.26 15:36 신고  댓글주소  수정/삭제

      라벨에 끝나는지점에 Return이 하나도 없네요... 추가하신 뒤 다시 테스트 해보시기 바랍니다.
      프로그램만드는게 급해서 기본적인 내용들을 무시하시면 결과적으로 더 오랜시간이 걸리게 됩니다. 강의에 나오는 내용을 충실히 보시기 바랍니다.^^

  • 2018.02.13 19:34  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • 킴영감 2018.02.15 04:03 신고  댓글주소  수정/삭제

      우선 두개의 녹스 창 이름을 다르게 바꾸셔야 합니다.
      활성이면 WinGetPos를 사용해서 각각 영역을 지정해주시면 되고
      비활성이면 창이름이 다르면 바로 적용됩니다.^^

  • 2018.05.25 02:19  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다