본문 바로가기
개발 연습/메이플랜드 매크로_파이썬

(파이썬연습) 메이플랜드 매크로 만들기1_캐릭터 인식

by 멍뭉부 2024. 2. 2.
728x90

안녕하세요,

오늘은 파이썬을 연습할 겸 메이플랜드라는 게임에서 캐릭터를 인식하는 매크로를 만드는 작업에 대해 소개해드리려고 합니다.

 

우선 말씀드리고 싶은 것은, 게임 매크로는 비인가 프로그램으로 간주되어 사용 시 게임 정지 등의 불이익을 받을 수 있으니, 절대 실제 게임 환경에서 이러한 매크로를 사용하려는 생각은 하지 않으시길 바랍니다.

이 포스팅은 순수하게 학습 목적으로만 활용된것임을 명심해주시기 바랍니다.

 

매크로를 만들기 위해 가장 중요한 부분 중 하나는 바로 게임 내에서 자신의 캐릭터를 어떻게 인식하느냐입니다.

캐릭터를 정확히 인식해야만 현재 위치를 파악하고, 몬스터에게 접근하는 등의 조작을 수행할 수 있게 됩니다.

 

개인적으로 캐릭터 인식 방법에 대해 많은 고민을 했습니다.

많은 방법을 고려해보았지만, 결국 저는 가장 단순한 방법을 선택했습니다.

바로 캐릭터의 머리 부분을 좌측과 우측으로 각각 캡쳐하여 특정 폴더에 저장한 후,

이 이미지들을 사용하여 게임 내에서 캐릭터를 인식하는 것인데요.

 

어찌되었건.. 잘작동하여 이 방식을 통해 캐릭터의 x축과 y축 좌표를 얻어낼 수 있습니다.

아래는 이 과정을 구현하기 위한 코드입니다.

 

[전체소스]

import 는 각각 cv2, numpy as np, pyautogui 을 사용하였습니다.

def find_character_coordinates():
    print("캐릭터 인식 작업 수행중..")

    left_character_image = cv2.imread("C:\\Dump\\left_char.png", cv2.IMREAD_COLOR)
    right_character_image = cv2.imread("C:\\Dump\\right_char.png", cv2.IMREAD_COLOR)

    character_x, character_y = None, None

    while True:
        screenshot_pillow = pyautogui.screenshot()
        screenshot = np.array(screenshot_pillow)

        left_result = cv2.matchTemplate(
            screenshot, left_character_image, cv2.TM_CCOEFF_NORMED
        )
        right_result = cv2.matchTemplate(
            screenshot, right_character_image, cv2.TM_CCOEFF_NORMED
        )

        threshold = 0.7

        if cv2.minMaxLoc(left_result)[1] >= threshold:
            character_location = cv2.minMaxLoc(left_result)[3]
            character_x, character_y = character_location[0], character_location[1]
            print(f"좌측 면 캐릭터가 인식되었습니다. 좌표: ({character_x}, {character_y})")
            break

        if cv2.minMaxLoc(right_result)[1] >= threshold:
            character_location = cv2.minMaxLoc(right_result)[3]
            character_x, character_y = character_location[0], character_location[1]
            print(f"우측 면 캐릭터가 인식되었습니다. 좌표: ({character_x}, {character_y})")
            break
        pyautogui.keyDown("left")
        pyautogui.keyDown("alt")
        time.sleep(3)
        pyautogui.keyUp("left")
        pyautogui.keyUp("alt")

        screenshot_pillow = pyautogui.screenshot()
        screenshot = np.array(screenshot_pillow)

        left_result = cv2.matchTemplate(
            screenshot, left_character_image, cv2.TM_CCOEFF_NORMED
        )

        if cv2.minMaxLoc(left_result)[1] >= threshold:
            character_location = cv2.minMaxLoc(left_result)[3]
            character_x, character_y = character_location[0], character_location[1]
            print(f"좌측으로 이동 후 캐릭터가 인식되었습니다. 좌표: ({character_x}, {character_y})")
            break

        pyautogui.keyDown("right")
        pyautogui.keyDown("alt")
        time.sleep(3)
        pyautogui.keyUp("right")
        pyautogui.keyUp("alt")

        screenshot_pillow = pyautogui.screenshot()
        screenshot = np.array(screenshot_pillow)

        right_result = cv2.matchTemplate(
            screenshot, right_character_image, cv2.TM_CCOEFF_NORMED
        )

        if cv2.minMaxLoc(right_result)[1] >= threshold:
            character_location = cv2.minMaxLoc(right_result)[3]
            character_x, character_y = character_location[0], character_location[1]
            print(f"우측으로 이동 후 캐릭터가 인식되었습니다. 좌표: ({character_x}, {character_y})")
            break

        print("캐릭터 인식 실패. 좌측으로 이동 후 다시 시도합니다.")

    print("캐릭터 인식이 종료되었습니다.")
    return character_x, character_y

 

다른 액션에 위 함수를 호출함으로써 캐릭터의 현재 좌표값을 구할 수 있습니다.

우선 난잡한부분이 많은데.. 코딩을 많이 해본것도 아닐뿐더러 게임이라 역시 여러가지 변수가 많았습니다.

일부에 대해 추가적으로 말쓰드리려고 합니다.

 

    left_character_image = cv2.imread("C:\\Dump\\left_char.png", cv2.IMREAD_COLOR)
    right_character_image = cv2.imread("C:\\Dump\\right_char.png", cv2.IMREAD_COLOR)

    character_x, character_y = None, None

우선 처음 부분이죠.  앞서 말씀드렸듯이 캐릭터의 이미지를 미리 지정 경로에 넣어두고.

이 이미지를 프로그램에서 불러와서 사용하는 과정입니다.

 

ㅋㅋㅋ 이런식으로 대충 머리만 스크린샷 찍어두었습니다. 캐릭터가 변경되면 또 찍어줘야하는 번거러움이,,ㅜㅜ .

 

원래는 pyautogui 모듈에서 쓰이는 이미지 서치를 사용했지만, 이상하게 메이플랜드에서 막아놨는지 이미지가 서치되지  않아서 cv2 모듈을 이용하여 이미지 서치를 하였습니다.

그리고 character_x, character_y = None, None 을 통해 함수가 호출될때마다 캐릭터 좌표는 초기화 되도록 해둡니다.

 

캐릭터 좌표구하는 함수의 로직은 아래와 같습니다.

 

1. 기존에 저장해두었던 캐릭터 좌측면 머리, 우측면 머리의 이미지를 현재 게임화면에서 찾습니다.

2. 만약 못찾을 경우 점프하면서 좌측으로 캐릭터를 3초간 이동하고 다시 스캔하고, 그래도 못찾으면 우측으로 캐릭터 3초간 이동 후 스캔합니다.

(게임 내 숲이나 몬스터, 포탈 등으로 인해 캐릭터가 가려져있을때를 위해서입니다.)

3. 찾을때까지 위 로직을 무한반복

4. 인식되면 해당 캐릭터의 x축, y축 리턴

 

 

이렇게 해서 자신의 캐릭터 좌표를 확인하는 함수를 만들어봤습니다.

물론 자신의 캐릭터 인식하는 방법에 대해서는 더 좋은방법을 찾아봐야겠지만, 매크로를 실제로 사용하는건 아니니까요. 

그냥 넘어가도록 합시다.

 

아직 몬스터 인식 및 사냥 등 여러가지 해야할게 많네요.

업무 자동화 연습을 재미도 찾으면서 하려고 매크로를 만들어보면서 배우고는 있지만 실제 활용하시는 분은 없도록 해주십쇼. (실제 정지먹습니다.)

 

 

 

 

728x90