너비 기반 탐색 알고리즘을 바탕으로 era에 구현해봤다

이름하여 AZSS Dungeon Pathfinder(아즈사 씨 던전 길탐색기)


@PATHFINDER_IS_ROUTE(XV,YV)

#DIM DYNAMIC XV;기준 좌표

#DIM DYNAMIC YV


SELECTCASE D3D_CURRENT_MAPDATA:XV:YV

    CASE 0,2,3,5,6,7,8,13,24,32,9,19,29,39

        RETURN 0

    CASE 1,4,14,15,34

        RETURN 1

ENDSELECT


;길찾기 알고리즘 도중에 쓰이는 통과 가능 판정

@PATHFINDER_CAN_PASS(XV,YV,DIRECTION)

#DIM DYNAMIC XV;기준 좌표

#DIM DYNAMIC YV

#DIM DYNAMIC DIRECTION;0~3


CALL D3D_CHECK_WALL(XV,YV,DIRECTION)

RETURN RESULT^1


;길찾기 알고리즘

@PATHFINDER_BFS(XV,YV,TXV,TYV)

#DIM DYNAMIC XV;시작 지점 좌표

#DIM DYNAMIC YV

#DIM DYNAMIC NUMV;1차원으로 변환한 좌표

#DIM DYNAMIC TXV;목표지점 좌표

#DIM DYNAMIC TYV

#DIM DYNAMIC TNUMV;1차원 목표 좌표

#DIM DYNAMIC TEMPX

#DIM DYNAMIC TEMPY

#DIM DYNAMIC TEMPV

#DIM DYNAMIC LCOUNT,2


NUMV = PATHFINDER_XY_TO_KEY(XV,YV)

TNUMV = PATHFINDER_XY_TO_KEY(TXV,TYV)


;방문여부 초기화

FOR LCOUNT,0,(PATHFINDER_MAXX * PATHFINDER_MAXY) + 1

    PATHFINDER_VISITA:LCOUNT = -1

NEXT

VARSET PATHFINDER_QUEUE

VARSET PATHFINDER_QUEUELEN


;연결 여부 초기화

FOR LCOUNT,0,(PATHFINDER_MAXX * PATHFINDER_MAXY)

    CALL PATHFINDER_KEY_TO_XY(LCOUNT)

    TEMPX = RESULT:0

    TEMPY = RESULT:1

    CALL PATHFINDER_IS_ROUTE(TEMPX,TEMPY)

    IF RESULT != 0

        FOR LCOUNT:1,0,4

            CALL PATHFINDER_CAN_PASS(TEMPX,TEMPY,LCOUNT:1)

            PATHFINDER_LINK:LCOUNT:(LCOUNT:1) = RESULT

        NEXT

    ELSE

        CONTINUE

    ENDIF

NEXT

;TEMPX = 0

;TEMPV = 0

;시작지점 설정 및 큐 삽입

PATHFINDER_VISITA:NUMV = -2

CALL PATHFINDER_ENQUEUE(NUMV)


DO

    IF !PATHFINDER_QUEUELEN

        ;큐가 모두 소진된 경우 종료

        BREAK

    ENDIF

    ;디큐 작업 TEMPV가 현재 탐색중인 좌표값

    TEMPV = PATHFINDER_DEQUEUE()

    DEBUGPRINTFORML TEMPV = {TEMPV} TNUMV = {TNUMV}

    IF TEMPV == TNUMV

        ;목표 위치에 도달한 경우 종료

        BREAK

    ENDIF

    CALL PATHFINDER_KEY_TO_XY(TEMPV)

    TEMPX = RESULT:0

    TEMPY = RESULT:1

    FOR LCOUNT,0,4

        IF PATHFINDER_LINK:TEMPV:LCOUNT != 0

            CALL PATHFINDER_NEAR_KEY(TEMPV,LCOUNT)

            IF PATHFINDER_VISITA:RESULT == -1

                PATHFINDER_VISITA:RESULT = TEMPV

                CALL PATHFINDER_ENQUEUE(RESULT)

            ENDIF

        ELSE

            DEBUGPRINTFORML PATHFINDER_LINK:{TEMPV}:{LCOUNT} != 0

        ENDIF

    NEXT

LOOP 1


PATHFINDER_PATH:0 = TEMPV

PATHFINDER_PATHLEN = 1

DO

    TEMPV = PATHFINDER_VISITA:TEMPV

    SIF TEMPV == -2

        BREAK

    ARRAYSHIFT PATHFINDER_PATH,1,0

    PATHFINDER_PATH:0 = TEMPV

    PATHFINDER_PATHLEN += 1

LOOP 1


;테스트 출력

FOR LCOUNT,0,PATHFINDER_PATHLEN

    CALL PATHFINDER_KEY_TO_XY(PATHFINDER_PATH:LCOUNT)

    PRINTFORML PATHFINDER_PATH:{LCOUNT} = {PATHFINDER_PATH:LCOUNT} ({RESULT:0},{RESULT:1})

NEXT


;XY좌표를 전용 키값으로 변환

@PATHFINDER_XY_TO_KEY(XV,YV)

#FUNCTION

#DIM DYNAMIC XV;좌표

#DIM DYNAMIC YV

RETURNF (PATHFINDER_MAXX * YV) + XV


;전용 키값에서 XY좌표로 변환

@PATHFINDER_KEY_TO_XY(KEYV)

#DIM DYNAMIC KEYV

RETURN KEYV % PATHFINDER_MAXX,KEYV / PATHFINDER_MAXY


@PATHFINDER_NEAR_KEY(KEYV,DIRECTION)

#DIM DYNAMIC KEYV

#DIM DYNAMIC DIRECTION

#DIM DYNAMIC MOD,2

CALL PATHFINDER_KEY_TO_XY(KEYV)

SELECTCASE DIRECTION

    CASE 0

        MOD:0 = 0,-1

    CASE 1

        MOD:0 = 1,0

    CASE 2

        MOD:0 = 0,1

    CASE 3

        MOD:0 = -1,0

ENDSELECT

{

    IF (RESULT:0)+(MOD:0) >= 0 && (RESULT:0)+(MOD:0) < PATHFINDER_MAXX &&

    (RESULT:1)+(MOD:1) >= 0 && (RESULT:1)+(MOD:1) < PATHFINDER_MAXY

}

    RETURN PATHFINDER_XY_TO_KEY((RESULT:0)+(MOD:0),(RESULT:1)+(MOD:1))

ELSE

    DEBUGPRINTFORML PATHFINDER_NEAR_KEY ERROR KEYV = {KEYV} DIRECTION = {DIRECTION}

    RETURN -1

ENDIF


@PATHFINDER_ENQUEUE(KEYV)

#DIM DYNAMIC KEYV

PATHFINDER_QUEUE:(PATHFINDER_QUEUELEN) += KEYV

PATHFINDER_QUEUELEN += 1

RETURN 1


@PATHFINDER_DEQUEUE

#FUNCTION

#DIM TARGETV

TARGETV = PATHFINDER_QUEUE:0

ARRAYSHIFT PATHFINDER_QUEUE,-1,-1

PATHFINDER_QUEUELEN -= 1

RETURNF TARGETV


#DIM CONST PATHFINDER_MAXX = 19

#DIM CONST PATHFINDER_MAXY = 19

;연결되어있음

#DIM PATHFINDER_LINK,(PATHFINDER_MAXX * PATHFINDER_MAXY) + 1,4

;큐 자료구조

#DIM PATHFINDER_QUEUE,(PATHFINDER_MAXX * PATHFINDER_MAXY) + 1

#DIM PATHFINDER_QUEUELEN = 0

;방문기록

#DIM PATHFINDER_VISITA,(PATHFINDER_MAXX * PATHFINDER_MAXY) + 1


#DIM PATHFINDER_PATH,(PATHFINDER_MAXX * PATHFINDER_MAXY) + 1

#DIM PATHFINDER_PATHLEN = 0


그리고 허공에 평타를 치면 

CALL PATHFINDER_BFS(2,2,D3D_PLAYER_XCOORD,D3D_PLAYER_YCOORD)

를 호출하도록 했다 (2,2 좌표에서 플레이어 위치까지 따라오는 경로 탐색)

결과


현재 테스트 중



좀 멀리 있어도 찾아온다(문은 열려있을경우 들어옴)





적 이동 기능을 만들어보니 잘 작동함

근데 가까이 가니까 겹쳐버리네


겹쳐지는 건 코드 한줄 추가하는걸로 해결