Skip to main content
Add missing extends, reduce number of stored waypoints
Source Link
BerndBrot
  • 1.1k
  • 6
  • 16
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() { }
    // + stuff for doubly-linked list elements
}
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();
        }
    }
}
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();
            }
        }
    }
}
class Snake extends DoublyLinkedList {
    property Path;
    property MovingObjects = array();
}
abstract class MovingObject {
    property Snake; // shared among all moving objects of the same snake
    property position;
    const securityDistance = 10;
    abstract function move() { }
    // + stuff for doubly-linked list elements
}
class MovingObjectLeader {
    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 {
    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();
        }
    }
}
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();
        }
    }
}
improved OOP design
Source Link
BerndBrot
  • 1.1k
  • 6
  • 16

Here's some pseudo-code for how these things could be implemented. Be aware that this ismight not by any meansbe the most elegant solution in terms of distribution of responsibilities and encapsulation.

class Path extends List { 
    property WayPoints = array(); 

    property// securityDistanceFind =out 10;

the x, y coordinates functiongiven moveAlong(currentPosition,the distance, nextWayPoint,traveled positionInTheSnake)on {the path
    function getPositionFromDistanceFromEnd(distance) {
  distanceToEndOfPath = ... // something involving currentWayPoint = this->getDistanceToEnd>first();
        ifwhile(distanceToEndOfPath < positionInTheSnakedistance *> this->securityDistance0) {
            returndistanceBetweenWayPoints = this->getPositionFromEnd>getDistance(positionInTheSnake *currentWayPoint, thiscurrentWayPoint->securityDistance>next());
        }
     if(distanceBetweenWayPoints > distance) {
        return (currentPosition + distance on the path)
  position = ... }

// travel remaining distance //between FindscurrentWayPoint outand thecurrentWayPoint->next();
 distance to the end of the path recursively
    function getDistanceToEnd(WayPoint, distanceCarriedOver = 0)return {position;
        if(WayPoint == this->last()) {
 } else {
         return distanceCarriedOver;
      distance -= }distanceBetweenWayPoints;
        distanceCarriedOver += this->getDistance(WayPoint, WayPoint->next());
       currentWayPoint return= getDistanceToEnd(WayPointcurrentWayPoint->next(), distanceCarriedOver);
    }
    function getPositionFromEnd(distance) {
  }
      return (some position);}
    }
}
class Snake extends DoublyLinkedList {
    property Path;
    property MovingObjects = array();
}
abstract class MovingObject {
    property Snake; // shared among all moving objects of the same snake
    property position;
    const securityDistance = 10;
    abstract function move() { }
    // + stuff for doubly-linked list elements
}
class MovingObjectLeader {
    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 {
    property distanceFromEnd;
    function move() {
        this->position>distanceFromEnd =+= this->Snake->Path>speed;

        // If too close to leader: stop in order to respect security distance
        if(this->moveAlong>distanceFromEnd > this->leader()->distanceFromEnd - this->securityDistance) {
            this->distanceFromEnd = this->leader()->distanceFromEnd - this->securityDistance;
        }

        this->position = this->Snake->speed>getPositionFromDistanceFromEnd(this->distanceFromEnd); 

        if(this->hasFollower()) {
            this->follower->move();
        }
    }
}

Path->WayPoints becomes bigger and bigger the longer the game goes on. If your Snake exists for quite some time, you need to delete the last WayPoint whenever the last element of the Snake has passed the second-to-last WayPoint of Path. Remember to also reduce distanceFromEnd in all MovingObjects of Snake accordingly.

Here's some pseudo-code for how these things could be implemented. Be aware that this is not by any means the most elegant solution in terms of distribution of responsibilities and encapsulation.

class Path extends List { 
    property WayPoints = array();
    property securityDistance = 10;

    function moveAlong(currentPosition, distance, nextWayPoint, positionInTheSnake) {
        distanceToEndOfPath = ... // something involving this->getDistanceToEnd()
        if(distanceToEndOfPath < positionInTheSnake * this->securityDistance) {
            return this->getPositionFromEnd(positionInTheSnake * this->securityDistance);
        }
        
        return (currentPosition + distance on the path)
    }

    // Finds out the distance to the end of the path recursively
    function getDistanceToEnd(WayPoint, distanceCarriedOver = 0) {
        if(WayPoint == this->last()) {
            return distanceCarriedOver;
        }
        distanceCarriedOver += this->getDistance(WayPoint, WayPoint->next());
        return getDistanceToEnd(WayPoint->next(), distanceCarriedOver);
    }
    function getPositionFromEnd(distance) {
        return (some position);
    }
}
class Snake extends DoublyLinkedList {
    property Path;
    property MovingObjects = array();
}
abstract class MovingObject {
    property Snake; // shared among all moving objects of the same snake
    property position;
    abstract function move() { }
    // + stuff for doubly-linked list elements
}
class MovingObjectLeader {
    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 {
    function move() {
        this->position = this->Snake->Path->moveAlong(this->Snake->speed);
        if(this->hasFollower()) {
            this->follower->move();
        }
    }
}

Here's some pseudo-code for how these things could be implemented. Be aware that this might not be the most elegant solution in terms of distribution of responsibilities and encapsulation.

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();
            }
        }
    }
}
class Snake extends DoublyLinkedList {
    property Path;
    property MovingObjects = array();
}
abstract class MovingObject {
    property Snake; // shared among all moving objects of the same snake
    property position;
    const securityDistance = 10;
    abstract function move() { }
    // + stuff for doubly-linked list elements
}
class MovingObjectLeader {
    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 {
    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 becomes bigger and bigger the longer the game goes on. If your Snake exists for quite some time, you need to delete the last WayPoint whenever the last element of the Snake has passed the second-to-last WayPoint of Path. Remember to also reduce distanceFromEnd in all MovingObjects of Snake accordingly.

Code clean-up and complete summary on top
Source Link
BerndBrot
  • 1.1k
  • 6
  • 16

Use a List called "Path" to store the way-points that describe your path, and a doubly-linked list called "Snake" to store the moving objects and Path.

The leading object defines new way-points as it travels. The following objects move along the path as defined by these way-points.

Each object has a security zone defined by some distance. If the leading object stops, the following objects move on only until they would touch the security zone of their predecessor.

Here's some pseudo-code for how these things could interact:be implemented. Be aware that this is not by any means the most elegant solution in terms of distribution of responsibilities and encapsulation.

class Path extends List { 
    property WayPoints = array();
    property securityDistance = 10;

    function moveAlong(currentPosition, distance, nextWayPoint, positionInTheSnake) {
        distanceToEndOfPath = ... // something involving this->getDistanceToEnd()
        if(distanceToEndOfPath < positionInTheSnake * this->securityDistance) {
            return this->getPositionFromEnd(positionInTheSnake * this->securityDistance);
        }
        
        return (currentPosition + distance on the path)
    }

    // Finds out the distance to the end of the path recursively
    function getDistanceToEnd(WayPoint, distanceCarriedOver = 0) {
        if(WayPoint == this->last()) {
            return distanceCarriedOver;
        }
        distanceCarriedOver += this->getDistance(WayPoint, WayPoint->next());
        return getDistanceToEnd(WayPoint->next(), distanceCarriedOver);
    }
    function getPositionFromEnd(distance) {
        return (some position);
    }
}
class Snake extends DoublyLinkedList {
    property Path;
    property MovingObjects = array();
}
abstract class MovingObject {
    property Snake; // shared among all moving objects of the same snake
    property position;
    abstract function move() { }
    // + stuff for doubly-linked list elements
}
class MovingObjectLeader {
    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 {
    function move(alreadyTraveled = 0) {
        this->position = this->Snake->Path->moveAlong(this->Snake->speed);
        if(this->hasFollower()) {
            this->follower->move();
        }
    }
}

The leading object defines new way-points as it travels. The following objects move along the path as defined by these way-points.

Each object has a security zone defined by some distance. If the leading object stops, the following objects move on only until they would touch the security zone of their predecessor.

Use a List called "Path" to store the way-points that describe your path, and a doubly-linked list called "Snake" to store the moving objects and Path. Here's some pseudo-code for how these things could interact:

class Path extends List { 
    property WayPoints = array();
    property securityDistance = 10;

    function moveAlong(currentPosition, distance, nextWayPoint, positionInTheSnake) {
        distanceToEndOfPath = ... // something involving this->getDistanceToEnd()
        if(distanceToEndOfPath < positionInTheSnake * this->securityDistance) {
            return this->getPositionFromEnd(positionInTheSnake * this->securityDistance);
        }
        
        return (currentPosition + distance on the path)
    }

    // Finds out the distance to the end of the path recursively
    function getDistanceToEnd(WayPoint, distanceCarriedOver = 0) {
        if(WayPoint == this->last()) {
            return distanceCarriedOver;
        }
        distanceCarriedOver += this->getDistance(WayPoint, WayPoint->next());
        return getDistanceToEnd(WayPoint->next(), distanceCarriedOver);
    }
    function getPositionFromEnd(distance) {
        return (some position);
    }
}
class Snake extends DoublyLinkedList {
    property Path;
    property MovingObjects = array();
}
abstract class MovingObject {
    property Snake; // shared among all moving objects of the same snake
    property position;
    abstract function move() { }
    // + stuff for doubly-linked list elements
}
class MovingObjectLeader {
    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 {
    function move(alreadyTraveled = 0) {
        this->position = this->Snake->Path->moveAlong(this->Snake->speed);
        if(this->hasFollower()) {
            this->follower->move();
        }
    }
}

The leading object defines new way-points as it travels. The following objects move along the path as defined by these way-points.

Each object has a security zone defined by some distance. If the leading object stops, the following objects move on only until they would touch the security zone of their predecessor.

Use a List called "Path" to store the way-points that describe your path, and a doubly-linked list called "Snake" to store the moving objects and Path.

The leading object defines new way-points as it travels. The following objects move along the path as defined by these way-points.

Each object has a security zone defined by some distance. If the leading object stops, the following objects move on only until they would touch the security zone of their predecessor.

Here's some pseudo-code for how these things could be implemented. Be aware that this is not by any means the most elegant solution in terms of distribution of responsibilities and encapsulation.

class Path extends List { 
    property WayPoints = array();
    property securityDistance = 10;

    function moveAlong(currentPosition, distance, nextWayPoint, positionInTheSnake) {
        distanceToEndOfPath = ... // something involving this->getDistanceToEnd()
        if(distanceToEndOfPath < positionInTheSnake * this->securityDistance) {
            return this->getPositionFromEnd(positionInTheSnake * this->securityDistance);
        }
        
        return (currentPosition + distance on the path)
    }

    // Finds out the distance to the end of the path recursively
    function getDistanceToEnd(WayPoint, distanceCarriedOver = 0) {
        if(WayPoint == this->last()) {
            return distanceCarriedOver;
        }
        distanceCarriedOver += this->getDistance(WayPoint, WayPoint->next());
        return getDistanceToEnd(WayPoint->next(), distanceCarriedOver);
    }
    function getPositionFromEnd(distance) {
        return (some position);
    }
}
class Snake extends DoublyLinkedList {
    property Path;
    property MovingObjects = array();
}
abstract class MovingObject {
    property Snake; // shared among all moving objects of the same snake
    property position;
    abstract function move() { }
    // + stuff for doubly-linked list elements
}
class MovingObjectLeader {
    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 {
    function move() {
        this->position = this->Snake->Path->moveAlong(this->Snake->speed);
        if(this->hasFollower()) {
            this->follower->move();
        }
    }
}
added 2284 characters in body
Source Link
BerndBrot
  • 1.1k
  • 6
  • 16
Loading
doubly-linked list instead of simple list
Source Link
BerndBrot
  • 1.1k
  • 6
  • 16
Loading
Source Link
BerndBrot
  • 1.1k
  • 6
  • 16
Loading