오토핫키(AutoHotKey) 기초강좌 #10 - 매크로 만들기 응용 5 (함수1)




 전체 강좌

 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강 - 매크로 제작 예제

















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


벌써 10번째 강좌네요.^^


이제 두강 남았습니다.


제가 생각했던 것 보다 많은 내용을 다루게 되어 기초강좌 치고는 내용이 어려워 진 것 같네요...ㅠ


하지만 이 강좌를 보시는 모든 분들이 자기만의 매크로 제작에 성공하셨으면 합니다!!


기초 강좌의 내용들만 100% 익히시면 어떠한 게임의 매크로도 만들 수 있으니 힘내시기 바랍니다!


그럼 10번째 강좌를 시작하겠습니다.


오늘은 개인적으로 "프로그래밍의 꽃"이라고 생각하는 "사용자 함수"에 대해 배워 볼 것입니다.


"함수? 그게 뭐지?"라고 생각하시는 분이 많으실 것입니다.

이해를 돕기위해서 수학시간에 배운 "함수"에 비유해서 설명드리겠습니다. 


모두가 익숙한 함수는 f(x)!! (일렉트릭 숔...!!)

수식 하나를 적어보죠.



등식의 왼쪽에 있는 f(x)를 "함수"라고 하고 오른쪽에 있는 것이 함수의 내용을 나타냅니다. 변수 x에 특정 값을 대입하면 그 값에 대한 계산 결과를 의미하는 것이 f(x) 즉, "함수"입니다.


이를 프로그래밍에서 "함수"의 개념과 접목시켜 보겠습니다.


함수를 작성하는 방법은 아래와 같습니다.


 함수이름 (변수)

 {

   내용

 } 


"함수이름"은 "f", "변수"는 "x", "내용"은 "3x+2"와 같습니다. 함수를 실행시키면 중괄호 내부의 내용을 위에서부터 한줄씩 실행하게 됩니다.


수학시간에 배웠던 함수와 기본적인 틀이 똑같죠?

하지만 한가지 다른점이 있습니다. 수학시간에 배운 함수는 내용을 계산하면 답이 정해져 있지만 프로그래밍에서는 프로그램을 작성하는 사람이 직접 답을 정해서 반환 하거나 답이 없도록 작성할 수 있습니다. (다음 강좌에서 자세히 알려드리겠습니다.)


우리가 사용하는 오토핫키 명령어들은 대부분 함수로 미리 작성이 되어 있으며 우리는 사용방법에 맞게 사용만 하는 것입니다. 이와 같이 어떠한 동작을 하는 함수를 직접 만드는 것을 "사용자 함수"라고 합니다.


"그럼 함수는 언제 사용하느냐?"에 대해 생각해 봅시다.


함수는 사용하지 않아도 됩니다. 하지만 스크립트를 작성할 때에 똑같은 내용의 코드가 여러번 들어가게되면 코드가 길어지고 복잡해 집니다. 이럴때에 반복되는 코드를 함수에 집어넣고 실제로 사용할 때에는 함수를 호출만 하면 훨씬 깔끔하게 스크립트를 작성할 수 있습니다. 강좌에서 배운내용들을 응용해서 매크로를 만드시다 보면 점점 스크립트 내용이 많아지는 것을 확인하실 수 있을 것입니다. 그럴 때 오늘 배우는 함수를 사용하시면 됩니다.


이제 함수를 어떻게 사용하는지 알아봅시다.


우선 아래와 같이 코드를 수정하세요.


오토핫키 전역변수


변수는 생명이 있습니다. 중괄호 내부에서 선언된 변수는 중괄호를 벗어나면 사라지게 됩니다. 하지만 어디에서도 사용할 수 있는 변수가 있습니다. 


두번째 강좌에서 GUI코드 아래에 "매크로시작"이라는 변수를 만들었던 것 기억나시죠? 버튼과 핫키를 통해서 동작시킬 때는 그림처럼 "global"을 적어주지 않아도 변수를 사용할 수 있었는데 함수를 사용할 때에는 인식하지 못하더라구요.


그래서 그림처럼 앞에다가 "global"을 적어주시면 스크립트 어디에서든 "매크로시작"이라는 변수를 사용하실 수 있습니다. 이처럼 스크립트 어디에서든 사용할 수 있는 변수를 만드실 때에는 반드시 "global 변수명"으로 사용하셔야 합니다.


오토핫키 함수


지난 강좌에서 배운 내용의 스크립트를 수정한 것입니다.


아래의 빨간 박스가 위에서 알려드린 함수를 만드는 방법입니다. 함수이름을 "함수1"이라고 적었습니다. 소괄호("()") 안에는 변수가 들어가야 하지만 필요없을 경우 그림처럼 비워두시면 됩니다. "4.bmp"를 클릭하는 코드를 잘라내어 내용부분에 붙여넣었습니다.

"함수1"을 실행하면 중괄호 내부의 코드를 한줄씩 실행하고 중괄호를 벗어나면 함수는 끝나게 됩니다.


위에 있는 빨간 박스는 함수를 사용한 부분입니다. 4번 이미지를 찾아서 클릭하는 부분을 "함수1"에 구현하고 실제로 사용할 때에는 간단하게 한줄로 적어서 사용한 것입니다. 사용방법은 위 그림처럼 "함수이름 + (변수)"의 형태로 사용할 수 있습니다.


모두 수정하셨으면 프로그램을 실행 해 보세요.


4번 이미지를 찾아서 클릭하는 부분을 함수로 옮겨적었다 뿐이지 똑같이 동작하는 것을 확인하실 수 있을 것입니다. 



그럼 한번 더 실습을 해 보겠습니다.


아래와 같이 스크립트를 수정하세요.



"Button시작" 내부에 있던 코드를 "함수1"로 모두 옮겨 왔습니다. 함수를 만들 때 GUI에 할당된 변수들을 넘겨 받도록 했습니다. 버튼이나 핫키에서는 바로 사용이 가능한데 함수에서는 불어오지 못하더라구요...^^ (이렇게 사용해도 문제는 없지만 아시는분 알려주시면 감사하겠습니다.)

그냥 While 안에 있는 코드를 몽땅 복사해서 붙혀넣었습니다.ㅋㅋ


이제 사용해 봅시다.



우선 함수 안에서 클리어횟수를 체크해야하기 때문에 "클리어횟수"변수를 "global"로 바꿔 주었습니다.

그 다음 While의 내부에 "함수1(반복횟수, 2번이미지클릭, 클릭안함)"을 적어 함수를 호출합니다. 시작버튼을 누르면 반복적으로 함수1을 반복해서 호출하는 것입니다.


스크립트가 엄청 깔끔해졌죠?? 프로그램을 실행시켜 보시면 똑같이 동작하는 것을 확인 하실 수 있습니다.



이렇게 해서 오늘의 강좌가 끝났습니다.


오늘 배우신 함수는 앞으로 프로그램을 만드실 때 99% 사용하게 될 것입니다. 이제 막 걸음마를 때는 시점에서는 개념을 이해하기도 힘들 수는 있지만 스크립트를 반복해서 작성하고, 작성한 스크립트를 실행해보면서 동작을 이해하시면 빠른 시일 내에 반드시 깨우치는 순간이 올 것입니다.


다음 강좌에서는 함수를 사용하는 방법에 대해서 추가로 설명 드릴 것입니다. 개념적으로 이해가 안되시는 분은 반드시 이해 하셔야 다음 강좌를 따라올 수 있을 것이기 때문에 반드시 반복해서 실습해 보시기를 바랍니다.


이상으로 10번째 강좌를 마치겠습니다.


오늘도 고생하셨습니다.^^

블로그 이미지

킴영감

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

댓글을 달아 주세요

  • CHEKI 2016.01.27 02:00  댓글주소  수정/삭제  댓글쓰기

    Gui, Add, Text, x0 y10 w200 h150 +Center, 레이븐 New Ver
    Gui, Add, Button, x10 y30 w100 h25 +Center, 매크로 시작
    Gui, Add, Button, x10 y60 w100 h25 +Center, 매크로 중지
    Gui, Add, Button, x25 y120 w150 h25 +Center, 레이븐 매크로 종료
    Gui, Add, Text, x120 y30 w70 h25 vA +Center, 중지
    Gui, Add, Text, x120 y60 w70 h25 vB +Center, 0 회
    Gui, Show

    매크로작동 := false

    return








    Button매크로시작:
    {
    매크로작동 := true

    Gui,Submit,NoHide
    GuiControl, , A, 작동

    Loop
    {
    ImageSearch, xX, yY, 0,0, A_ScreenWidth, A_ScreenHeight, *70 C:\Users\kakao\Pictures\Auto Script\레이븐New ver\탐험.PNG
    if ((ErrorLevel = 0) && (매크로작동 := true))
    {
    frist()
    }
    }
    }
    return

    Frist()
    {
    Send {Click %xX% %yY%}
    Sleep, 1000
    }
    return
















    Button매크로중지:
    {
    매크로작동 := false

    Gui,Submit,NoHide
    GuiControl, , A, 중지
    }
    return

    Button레이븐매크로종료:
    {
    매크로작동 := false
    ExitApp
    }
    return

















    F2::
    {
    매크로시작 := true

    Gui,Submit,NoHide
    GuiControl, , A, 작동
    }
    return

    F3::
    {
    매크로작동 := false

    Gui,Submit,NoHide
    GuiControl, , A, 중지
    }
    return

    F4::
    {
    매크로작동 := false
    ExitApp
    }
    return

    기본적으로 이렇게 짜놓았는데 이미지서치 괄호 안에있는 Frist()가 Frist()랑 해놓아도 탐험이라는 이미지로 가서 클릭하지않고 그자리를 클릭하던데 어떻게 해야할까요 ㅠㅠ 이미지서치 괄호에 있는 Frist()를 Send {Click %xX% %yY%} 로 바꿨을때는 잘되는데 함수 배워도 잘 이해도 안되고 써먹을 줄도 모르고 막막하네요

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

      함수의 개념을 못잡으신 것 같네요^^
      강좌 내용 중 두번째 예시를 다시한번 읽어보시기 바랍니다.

      질문에 대한 답변을 드리면 Frist()함수 내부에 있는 xX와 yY라는 변수는 매크로시작 내부에 있는 xX와 yY와 다른 것이기 때문에 Frist()함수 내부에 있는 xX와 yY는 올바른 값을 가지고 있지 않습니다.

      이를 올바르게 동작시키기 위해서는 Frist함수를 사용할때 변수를 같이 넘겨주셔야하며 강좌의 두번째 내용을 보고 따라하시면 됩니다^^

    • CHEKI 2016.01.27 17:05  댓글주소  수정/삭제

      Gui, Add, Text, x0 y10 w200 h150 +Center, 레이븐 New Ver
      Gui, Add, Button, x10 y30 w100 h25 +Center, 매크로 시작
      Gui, Add, Button, x10 y60 w100 h25 +Center, 매크로 중지
      Gui, Add, Button, x25 y120 w150 h25 +Center, 레이븐 매크로 종료
      Gui, Add, Text, x120 y30 w70 h25 vA +Center, 중지
      Gui, Add, Text, x120 y60 w70 h25 vB +Center, 0 회
      Gui, Add, Text, x120 y100 w70 h25 vC +Center, 처음
      Gui, Show

      매크로작동 := false

      return





      Button매크로시작:
      {
      매크로작동 := true

      Gui,Submit,NoHide
      GuiControl, , A, 작동

      처음들어감 := true

      While((매크로작동 := true) && (처음들어감 := true))
      {
      ImageSearch, xX, yY, 0,0, A_ScreenWidth, A_ScreenHeight, *70 C:\Users\kakao\Pictures\Auto Script\레이븐New ver\탐험.PNG
      if ((ErrorLevel = 0) && (매크로작동 := true))
      {
      Frist()
      }
      }
      return


      }




      Frist()
      {
      ImageSearch, xX, yY, 0,0, A_ScreenWidth, A_ScreenHeight, *70 C:\Users\kakao\Pictures\Auto Script\레이븐New ver\탐험.PNG
      if ((ErrorLevel = 0) && (매크로작동 := true))
      {
      Gui,Submit,NoHide
      GuiControl, , C, 이미

      Send {Click %xX% %yY%}
      Sleep, 1000

      처음들어감 := false
      }
      }
      return


















      Button매크로중지:
      {
      매크로작동 := false

      Gui,Submit,NoHide
      GuiControl, , A, 중지

      Gui,Submit,NoHide
      GuiControl, , C, 처음
      }
      return

      Button레이븐매크로종료:
      {
      매크로작동 := false
      ExitApp
      }
      return

















      F2::
      {
      매크로시작 := true

      Gui,Submit,NoHide
      GuiControl, , A, 작동
      }
      return

      F3::
      {
      매크로작동 := false

      Gui,Submit,NoHide
      GuiControl, , A, 중지
      }
      return

      F4::
      {
      매크로작동 := false
      ExitApp
      }
      return

      하나만 더 물어봐도 될까요 ㅠㅠ
      이렇게 만들었는데

      위에서 매크로시작이 작동되면
      처음들어감 := true 로 되면서
      탐험버튼을 찾고 Frist()를 실행하는데

      Frist()에 라고 짜놓은 부분에
      한번 Frist()를 마치고 나면
      처음들어감 := false 가 되서 더이상
      처음들어감이 :=true 가 안됬으면 하는데
      다시 탐험이 있는화면에 가면 처음들어감이 true로 되있는지
      Frist()안에 있는 내용을 실행하게 되네요 ㅠㅠ

      한번만 하면 더이상 ture로 바뀌지 않게 하려면 어떻게 해야 하나요 ?

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

      답변을 드리기 전에 조언하나 드리자면 프로그래밍을 배울때는 강좌를 처음부터 꼼꼼히 보고 똑같이 만드는 것을 목표로 하시는 것이 좋습니다. 적용을 할 때에도 기본적인 형태는 변하지 않기 때문에 강좌에 있는 코드와 비교해 잘못적은 부분이 없는지 꼼꼼하게 확인해보시는 것을 권합니다^^

      while과 if의 조건문이 모두 잘못되어 있습니다. := 은 변수에 값을 넣을때 쓰는 것이기 때문에 처음들어감에 계속 true가 들어가는 것입니다. 값을 비교할 때에는 = 을 쓰셔야합니다.^^
      while((매크로작동 = true) && (처음들어감 = true)) 로 바꾸시고
      if ((ErrorLevel = 0) && (매크로작동 = true))로 바꾸시면 됩니다.

  • rkdals128 2016.01.29 15:32  댓글주소  수정/삭제  댓글쓰기

    Gui, Add, Text, x62 y9 w130 h20 +Center, 레이븐 For NAVER
    Gui, Add, Button, x22 y39 w50 h40 , 실행
    Gui, Add, Button, x22 y89 w50 h40 , 종료

    Gui, Add, Text, x12 y149 w60 h20 v현재, 현재: 중지
    Gui, Add, Text, x12 y169 w60 h20 v클리어횟수, 0 회
    Gui, Add, Text, x12 y189 w75 h20 v던전중, 던전중: X

    Gui, Add, Text, x130 y209 w40 h20 , 단축키
    Gui, Add, Text, x130 y229 w60 h20 , F2 :: 실행
    Gui, Add, Text, x130 y249 w60 h20 , F3 :: 종료

    Gui, Show

    작동시작 := false

    Return

    GuiClose:
    ExitApp



    Button실행:
    {
    작동시작 := true

    Gui,Submit,NoHide
    GuiControl, , 현재, 현재: 실행

    CoordMode, Mouse, Screen
    CoordMode, Pixel, Screen


    global 클리어횟수 := 0
    화면 := 0
    global 던전플레이중 := false
    global 던전중 := false


    while (작동시작 := true)
    {
    WinGetPos, pos_x, pos_y, 1680, 1050, BlueStack Frontend
    x_right := 1680 + pos_x
    X_bottom := 1050 + pos_y

    화면 := 화면검색1()

    if (화면 = 1)
    {
    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\not game image\레이븐.PNG
    if (ErrorLevel = 0)
    {
    Send {Click %xX% %yY%}
    Sleep, 23000

    Click 1641, 53
    Sleep, 500

    Click 1635, 916
    Sleep, 500
    Click 1635, 916
    Sleep, 500
    Click 1635, 916
    Sleep, 500
    Click 1635, 916
    Sleep, 5000
    Click 1635, 916
    Sleep, 10000

    Click 1605, 87
    Sleep, 500

    Click 1045, 740
    Sleep, 3000

    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\탐험.PNG
    if (ErrorLevel = 0)
    {
    화면검색1()
    }
    }
    }
    else if (화면 = 2)
    {
    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\탐험.PNG
    if (ErrorLevel = 0)
    {
    Send {Click %xX% %yY%}
    Sleep, 1000

    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\9STAGE.PNG
    if (ErrorLevel = 0)
    {
    Click 108, 485
    Sleep, 1500
    Click 108, 485
    Sleep, 1500
    Click 108, 485
    Sleep, 1500
    Click 108, 485
    Sleep, 1500

    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\5STAGE.PNG
    if (ErrorLevel = 0)
    {
    Click 384, 372
    Sleep, 1000

    Click 1137, 792
    Sleep, 3000

    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\탐험시작.PNG
    if (ErrorLevel = 0)
    {
    화면검색1()
    }
    }
    }
    }
    }
    else if (화면 = 3)
    {
    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *50 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\탐험시작.PNG
    if (ErrorLevel = 0)
    {
    Send {Click %xX% %yY%}
    Sleep, 10000

    던전플레이중 := true

    Gui,Submit,NoHide
    GuiControl, , 던전중, 던전중: O

    화면검색1()

    }
    }
    else if (화면 = 4)
    {
    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\다시하기.PNG
    if (ErrorLevel = 0)

    Gui,Submit,NoHide
    GuiControl, , 던전중, 던전중: X

    클리어횟수()


    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\탐험미션완료.PNG
    if (ErrorLevel = 0)
    {
    보상받기()
    }

    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\다시하기.PNG
    if (ErrorLevel = 0)
    {
    Send {Click %xX% %yY%}
    sleep, 7000
    }

    화면검색1()
    }
    }
    }


    화면검색1()
    {
    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\not game image\레이븐.PNG
    if (ErrorLevel = 0)
    {
    return 1
    }
    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\탐험.PNG
    if (ErrorLevel = 0)
    {
    return 2
    }
    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\탐험시작.PNG
    if (ErrorLevel = 0)
    {
    return 3
    }
    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\다시하기.PNG
    if (ErrorLevel = 0)
    {
    return 4
    }
    }

    클리어횟수()
    {
    클리어횟수 := 클리어횟수 + 1
    Gui,Submit,NoHide
    GuiControl, , 클리어횟수, %클리어횟수% 회
    }

    보상받기()
    {
    ImageSearch, xX, yY, %pos_x%, %pos_y%, %x_right%, %x_bottom%, *70 C:\Users\kakao\Desktop\레이븐 매크로 개발용\in game image\탐험미션완료.PNG
    if (ErrorLevel = 0)
    {
    Click 1432, 644
    Sleep, 2000
    }
    }





    Button종료:
    {
    작동시작 := false

    ExitApp
    }


    F2::
    {
    작동시작 := true
    }

    F3::
    {
    작동시작 := false
    ExitApp
    }

    이렇게 해놨는데 이미지를 누르지 않네요 ㅠㅠ

    • 킴영감 2016.01.29 16:26 신고  댓글주소  수정/삭제

      코드상에 문제는 없어보입니다. 우선 관리자권한으로 실행시켜보시고, 이미지를 저장해 놓은 폴더 명을 띄어쓰기 없이 영어로 해보시기바랍니다.

  • 음.... 함수를 쓰는데 왜 전역변수를 쓰나요??? 2019.03.07 23:44  댓글주소  수정/삭제  댓글쓰기

    함수는 당연히 지역변수를 써서 그함수의 내용의 변경 없이 필요한 인자값만 받아와서 결과만 리턴해주면되는데.. 기본적으로 함수를 제작할땐 다른 작업에 쓸수 있도록 만들어야되는데...