「パス」と呼ばれるリストを使用して、パスを記述するウェイポイントを保存し、「スネーク」と呼ばれる二重リンクリストを使用して、移動するオブジェクトとパスを保存します。
主要なオブジェクトは、移動する新しいウェイポイントを定義します。次のオブジェクトは、これらのウェイポイントによって定義されたパスに沿って移動します。
各オブジェクトには、ある距離で定義されたセキュリティゾーンがあります。先頭のオブジェクトが停止すると、後続のオブジェクトは、前のオブジェクトのセキュリティゾーンに触れるまで移動します。
これらを実装する方法の疑似コードを次に示します。これは、責任の分散とカプセル化の点で最もエレガントなソリューションではない可能性があることに注意してください。
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の最後の要素がPathの最後から2番目のWayPointを通過するたびに、最後のWayPointを削除する必要があります。それに応じて、SnakeのすべてのMovingObjectsでdistanceFromEndも減らすことを忘れないでください。