너비 기반 탐색 알고리즘을 바탕으로 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
#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 좌표에서 플레이어 위치까지 따라오는 경로 탐색)
결과
현재 테스트 중
좀 멀리 있어도 찾아온다(문은 열려있을경우 들어옴)
적 이동 기능을 만들어보니 잘 작동함
근데 가까이 가니까 겹쳐버리네
겹쳐지는 건 코드 한줄 추가하는걸로 해결