답변:
찾고자하는 중요한 것이 없다면 A *를 사용하는 것이 좋습니다.
비슷한 문제를 해결해야했습니다. 끊임없이 변화하는 "비용"과 장벽이있는 큰 미로 같은 그리드에서 길을 찾는 것입니다.
문제는 타워 디펜스 게임에서 경로를 해결해야하는 엔티티 수는 일반적으로 그래프의 노드 수보다 훨씬 큽니다. A *는 이것을 처리하기에 가장 적합한 알고리즘 이 아닙니다 . 무언가가 바뀔 때마다 새로 해결해야하기 때문입니다. 하나의 경로 만 찾으면 적절하지만 제 경우에는 다른 위치에 나타날 수 있고 각각 자체 경로가있는 엔티티를 처리 할 수있었습니다.
플로이드 - Warshall의 내 경우에 내가 노드 변경, 그것은 때마다 모든 이웃 노드에 대한 비용을 다시 계산하는 사용자 정의 알고리즘을 쓴하지만 알고리즘이 훨씬 더 적합하고 있는 경우 이웃은 호출이 변경되었습니다 재귀 적으로 그들.
게임을 시작할 때 모든 "목표"노드에서이 알고리즘을 실행합니다. 그런 다음 단일 노드가 변경 될 때마다 (예를 들어, 통과 할 수 없게 됨) 해당 노드에서 노드를 시작하면 변경 사항이 영향을받는 모든 노드에 전파되어 중지됩니다. 따라서 전체 재 계산이 필요하지 않으며 알고리즘은 경로 찾기가 필요한 엔티티 수와 완전히 독립적입니다.
내 알고리즘은 기본적으로 (의사 코드)와 같습니다.
update_node method in Node class:
$old <- $my_score
find $neighbor node among all neighbors such that
$neighbor.score + distance_to($neighbor) is minimal
$my_score <- $neighbor.score + distance_to($neighbor)
$next_node <- $neighbor
if ($my_score != $old)
for each $neighbor
$neighbor.update_node()
노드가 대상인지 또는 어떤 종류의 장벽인지에 따라 초기 점수.
TD에서 사용한 경로 알고리즘은 게임에 포함 된 개체 수로 인해 일반 A * 경로에서 거꾸로되었습니다. 목표에서 나쁜 녀석으로 라우팅하는 대신 목표에서 보드의 모든 빈 사각형으로 라우팅했습니다.
시간이 오래 걸리지 않으며 "비용"을 찾을 때까지 계속 보드를 반복하고 차단 된 경로에 대해 좋은 피드백을 제공합니다 (해당하는 경우). Floyd의 알고리즘을 사용하면 데이터 종속 조회를 수행하지 않고 스트림의 데이터를로드하고 작동하기 때문에 A *에 비해 빠르고 캐시 친화적입니다.
보드를 무한 비용으로 설정 한 다음 목표 제곱을 비용 0으로 설정 한 다음 보드를 반복하여 인접 셀 비용이 현재 비용에 여행 비용을 더한지 확인하십시오. 여행 비용은 휴리스틱을 넣는 곳입니다 (제 경우 대각선 여행 비용은 무한하지만 탑을 통한 여행 비용은 높았으므로 탑을 통해 먹을 수는 있었지만 선택)
비용 그리드를 확보 한 후에는 셀에서 가장 가파른 비용 기울기를 테스트하여 그로부터 "흐름"그리드를 신속하게 구축 할 수 있습니다. 그들은 길을 찾을 필요가 없기 때문에 방대한 양의 나쁜 녀석들에게 정말 효과적입니다.
또 다른 이점은 방해물을 조정할 때마다 (또는 게임에서 크립이 타워 중 하나를 통과 할 때)이 작업 만 수행하면된다는 것입니다. 크리프 / 몹이 필드에 들어갈 때마다 (수천 몹과 초당 수십 명이 상당히 어려웠을 것).
길 찾기는 빠르며 일반적인 타워 방어 게임과 비슷한 크기로 무언가가 바뀔 때마다 정식 A * 또는 Dijkstra 패스를 실행하는 데 아무런 문제가 없습니다. 완전히 새로 고치기 위해 1 밀리 초 미만으로 잘 이야기하고 있습니다. 모든 종류의 적응 형 길 찾기는 끔찍하게 복잡해집니다. 세계에서 가장 큰 타워 방어 그리드를 만들지 않는 한 간단하게 수행하십시오.
A * 길 찾기는 어떻게 작동합니까? 시작하기에 좋은 장소 일 수 있습니다 :-)
간단한 해결책은 속이는 것입니다.
막 다른 곳이 없도록 맵을 미리 설계하십시오. 그런 다음 각 교차점에 캐릭터가 경로를 선택하도록하는 트리거를 추가하십시오 (예 : 항상 왼쪽으로 회전, 항상 오른쪽으로 회전 또는 임의).