git @ Cat's Eye Technologies Gemooy / master src / yoob / cursor.js
master

Tree @master (Download .tar.gz)

cursor.js @masterraw · history · blame

/*
 * This file is part of yoob.js version 0.12
 * Available from https://github.com/catseye/yoob.js/
 * This file is in the public domain.  See http://unlicense.org/ for details.
 */
if (window.yoob === undefined) yoob = {};

/*
 * An object representing a position and direction in some space.  The space
 * may be one-dimensional (a yoob.Tape, or a string representing a program
 * source) or a two-dimensional Cartesian space (such as a yoob.Playfield.)
 * A direction vector accompanies the position, so the cursor can "know which
 * way it's headed", but this facility need not be used.
 *
 * These methods are written for efficiency rather than inheritability, so
 * if you e.g. override setX() in a subclass, you will want to override
 * advance() et al too.
 */
yoob.Cursor = function() {
    this.init = function(cfg) {
        cfg = cfg || {};
        this.setX(cfg.x || 0);
        this.setY(cfg.y || 0);
        this.setDx(cfg.dx || 0);
        this.setDy(cfg.dy || 0);
        return this;
    };

    this.clone = function() {
        return new yoob.Cursor().init({
            x: this.x,
            y: this.y,
            dx: this.dx,
            dy: this.dy
        });
    };

    /*** Chainable setters ***/

    this.setX = function(x) {
        this.x = x;
        return this;
    };

    this.setY = function(y) {
        this.y = y;
        return this;
    };

    this.setDx = function(dx) {
        this.dx = dx;
        return this;
    };

    this.setDy = function(dy) {
        this.dy = dy;
        return this;
    };

    /*** Accessors ***/

    this.getX = function() {
        return this.x;
    };

    this.getY = function() {
        return this.y;
    };

    this.getDx = function() {
        return this.dx;
    };

    this.getDy = function() {
        return this.dy;
    };

    this.isHeaded = function(dx, dy) {
        return this.dx === dx && this.dy === dy;
    };

    /*** Motion ***/

    this.moveTo = function(x, y) {
        this.x = x;
        this.y = y;
        return this;
    };

    this.moveBy = function(dx, dy) {
        this.x += dx;
        this.y += dy;
        return this;
    };

    this.moveLeft = function(amount) {
        if (amount === undefined) amount = 1;
        this.x -= amount;
        return this;
    };

    this.moveRight = function(amount) {
        if (amount === undefined) amount = 1;
        this.x += amount;
        return this;
    };

    this.advance = function() {
        this.x += this.dx;
        this.y += this.dy;
        return this;
    };

    /*** Orientation ***/

    this.rotateClockwise = function() {
        if (this.dx === 0 && this.dy === -1) {
            this.dx = 1; this.dy = -1;
        } else if (this.dx === 1 && this.dy === -1) {
            this.dx = 1; this.dy = 0;
        } else if (this.dx === 1 && this.dy === 0) {
            this.dx = 1; this.dy = 1;
        } else if (this.dx === 1 && this.dy === 1) {
            this.dx = 0; this.dy = 1;
        } else if (this.dx === 0 && this.dy === 1) {
            this.dx = -1; this.dy = 1;
        } else if (this.dx === -1 && this.dy === 1) {
            this.dx = -1; this.dy = 0;
        } else if (this.dx === -1 && this.dy === 0) {
            this.dx = -1; this.dy = -1;
        } else if (this.dx === -1 && this.dy === -1) {
            this.dx = 0; this.dy = -1;
        }
        return this;
    };

    this.rotateCounterclockwise = function() {
        if (this.dx === 0 && this.dy === -1) {
            this.dx = -1; this.dy = -1;
        } else if (this.dx === -1 && this.dy === -1) {
            this.dx = -1; this.dy = 0;
        } else if (this.dx === -1 && this.dy === 0) {
            this.dx = -1; this.dy = 1;
        } else if (this.dx === -1 && this.dy === 1) {
            this.dx = 0; this.dy = 1;
        } else if (this.dx === 0 && this.dy === 1) {
            this.dx = 1; this.dy = 1;
        } else if (this.dx === 1 && this.dy === 1) {
            this.dx = 1; this.dy = 0;
        } else if (this.dx === 1 && this.dy === 0) {
            this.dx = 1; this.dy = -1;
        } else if (this.dx === 1 && this.dy === -1) {
            this.dx = 0; this.dy = -1;
        }
        return this;
    };

    this.rotateDegrees = function(degrees) {
        while (degrees > 0) {
            this.rotateCounterclockwise();
            degrees -= 45;
        }
        return this;
    };
}