Answers:
使用名为“路径” 的列表存储描述您的路径的航路点,并使用名为“蛇形” 的双向链接列表存储移动的对象和路径。
引导对象在行进时定义新的航路点。以下对象沿着这些航路点定义的路径移动。
每个对象都有一个由一定距离定义的安全区域。如果引导对象停止,则随后的对象将继续前进,直到它们碰到其前任的安全区域为止。
下面是一些伪代码,说明如何实现这些功能。请注意,就职责分配和封装而言,这可能不是最优雅的解决方案。
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就会变得越来越大。如果您的Snake存在了很长一段时间,则每当Snake的最后一个元素经过路径的倒数第二WayPoint时,您都需要删除最后一个WayPoint。请记住,还要相应地减少Snake的所有MovingObjects中的distanceFromEnd。
本质上,您将需要两个数据结构(逻辑的,侵入的或实际的,具体取决于您的其余代码)。第一个将跟踪对象链,第二个将跟踪路径。
链简单地,您需要知道哪些对象跟随其他对象。在最简单的情况下,这将是A跟随B,但可能包括更多的追随者。链中有指定的领导者。
路径对于每个链,您都需要一个路径。根据游戏的工作方式,将决定游戏的结构。在大多数情况下,它将是某种链表。这将跟踪链中每个人需要遵循的位置。
现在,链中的领导者将在路径中添加项目。每次移动都会在列表的开头添加一些内容。链中的每个对象都会记住它在列表上的位置。谈到移动时,它仅移动到列表中的下一项(必要时进行适当插值)。当链中的最后一个项目经过列表中的一个项目时,该项目可以被删除(它将位于末尾)。
隐喻上,领导者为其追随者留下了一条面包屑的痕迹。列表中的最后一个关注者消耗了面包屑。
您的列表中是否包含单个点,还是仅包含路径的顶点,还是其他内容,完全由游戏引擎决定。但无论如何,我看不到您可以避免使用列表本身。
查找A *寻路。这是让您的游戏实体/对象去到/跟随位置的一种通用且简便的方法。