답변:
"Path"라는 목록을 사용 하여 경로를 설명하는 웨이 포인트 를 저장하고 "Snake"라는 이중 연결 목록 을 사용하여 움직이는 객체와 경로를 저장하십시오.
선행 객체는 여행 할 때 새로운 웨이 포인트를 정의합니다. 다음 객체는 이러한 웨이 포인트로 정의 된 경로를 따라 이동합니다.
각 개체에는 일정한 거리로 정의 된 보안 영역이 있습니다. 선행 개체가 중지되면 다음 개체는 이전 보안 영역에 닿을 때까지만 이동합니다.
이러한 것들이 어떻게 구현 될 수 있는지에 대한 의사 코드가 있습니다. 이것은 책임 분배 및 캡슐화 측면에서 가장 우아한 솔루션이 아닐 수도 있습니다.
class Position {
property x;
property y;
}
class WayPoint extends ListNode {
property position;
}
class Path extends List {
property WayPoints = array();
// Find out the x, y coordinates given the distance traveled on the path
function getPositionFromDistanceFromEnd(distance) {
currentWayPoint = this->first();
while(distance > 0) {
distanceBetweenWayPoints = this->getDistance(currentWayPoint, currentWayPoint->next());
if(distanceBetweenWayPoints > distance) {
position = ... // travel remaining distance between currentWayPoint and currentWayPoint->next();
return position;
} else {
distance -= distanceBetweenWayPoints;
currentWayPoint = currentWayPoint->next();
}
}
}
function addWayPoint(position) {
// Vector describing the current and new direction of movement
currentDirection = this->first() - this->second();
newDirection = position - this->first();
// If the direction has not changed, there is no need to add a new WayPoint
if( this->sameDirection(currentDirection, newDirection) {
this->first->setPosition(position);
} else {
this->add(position);
}
}
}
class Snake extends DoublyLinkedList {
property Path;
property MovingObjects = array();
}
abstract class MovingObject extends DoublyLinkedListNode {
property Snake; // shared among all moving objects of the same snake
property position;
const securityDistance = 10;
abstract function move() { }
}
class MovingObjectLeader extends MovingObject {
property direction;
function move() {
this->position += this->direction * this->Snake->speed;
this->Snake->Path->addWayPoint(this->position);
if(this->hasFollower()) {
this->follower->move();
}
}
}
class MovingObjectFollower extends MovingObject {
property distanceFromEnd;
function move() {
this->distanceFromEnd += this->Snake->speed;
// If too close to leader: stop in order to respect security distance
if(this->distanceFromEnd > this->leader()->distanceFromEnd - this->securityDistance) {
this->distanceFromEnd = this->leader()->distanceFromEnd - this->securityDistance;
}
this->position = this->Snake->getPositionFromDistanceFromEnd(this->distanceFromEnd);
if(this->hasFollower()) {
this->follower->move();
}
}
}
Path-> WayPoints는 게임이 계속 될수록 커지고 커집니다. 스네이크가 꽤 오랫동안 존재하는 경우 스네이크의 마지막 요소가 경로의 두 번째에서 마지막 웨이 포인트를 지날 때마다 마지막 WayPoint를 삭제해야합니다. 또한 모든 Snake 이동 오브젝트에서 distanceFromEnd를 줄여야합니다.
기본적으로 두 가지 데이터 구조 (나머지 코드에 따라 논리, 침입 또는 실제)가 필요합니다. 첫 번째는 객체의 체인을 추적하고 다른 하나는 경로를 추적합니다.
체인 단순히 다른 개체를 따르는 개체를 알아야합니다. 가장 간단한 경우에는 단순히 A 다음에 B가되지만 더 많은 추종자를 포함 할 수 있습니다. 체인에 지정된 리더 가 있습니다.
경로 각 체인마다 경로가 필요합니다. 게임 작동 방식에 따라 이것이 어떻게 구성되는지가 결정됩니다. 대부분의 경우 일종의 연결 목록이됩니다. 체인의 모든 사람이 따라야 할 위치를 추적합니다.
이제 체인 의 리더 가 경로에 항목을 추가합니다 . 움직일 때마다 목록의 머리 부분에 무언가가 추가됩니다. 체인의 각 개체는 목록의 위치를 기억합니다. 이동할 때 간단히 목록의 다음 항목으로 이동합니다 (필요한 경우 적절하게 보간 됨). 체인의 마지막 항목이 목록의 항목을 지나갈 때 해당 항목을 놓을 수 있습니다 (꼬리에 있음).
은유 적으로 지도자는 추종자들을 위해 빵 부스러기 흔적을 남깁니다. 목록의 마지막 팔로어는 이동 경로를 사용합니다.
목록에 개별 지점이 포함되어 있는지 또는 경로의 정점 또는 기타가 포함되어 있는지 여부는 전적으로 게임 엔진에 의해 결정됩니다. 그러나 어쨌든 목록 자체를 피할 수는 없습니다.
조회 A * 경로 찾기. 게임 엔터티 / 객체가 위치를 이동하거나 따라 가도록하는 일반적이고 쉬운 방법입니다.