API Docs for:
Show:

File: src/fov-rot.js

(function(root) {
    'use strict';

    /**
    * Represents a FovROT in the game map. requires ROT.js
    * @class FovROT
    * @constructor
    * @param {Game} game - Game instance this obj is attached to.
    */
    var FovROT = function FovROT(game) {
        this.game = game;
        this.fovMap = new RL.Array2d();
        this.visibleTiles = [];
        this.visibleTileKeys = [];
    };

    FovROT.prototype = {
        constructor: FovROT,

        /**
        * Game instance this obj is attached to.
        * @property game
        * @type Game
        */
        game: null,

        /**
        * Array2d storing fovROT visibility fovMap
        * @property fovMap
        * @type Array2d
        */
        fovMap: null,

        /**
        * Field Range of view 90, 180, or 360.
        * @property fieldRange
        * @type Number
        */
        fieldRange: 360,

        /**
        * Direction of fov (used as default) (not used for fieldRange 360) valid directions: ['up', 'down', 'left', 'right', 'up_left', 'up_right', 'down_left', 'down_right'].
        * @property direction
        * @type String
        */
        direction: 'up',

        /**
        * Max visible distance in tiles
        * @property maxViewDistance
        * @type Number
        */
        maxViewDistance: 10,

        /**
         * All visible map tiles
         * Array of objects: {x: null, y: null, tile: null, range: null}
         * @property visibleTiles
         * @type {Array}
         */
        visibleTiles: null,

        /**
         * Array of visible tile keys used to prevent duplicates in this.visibleTiles.
         * @property visibleTileKeys
         * @type {Array}
         * @private
         */
        visibleTileKeys: null,

        /**
        * Validates a fieldRange value.
        * @method validateFieldRange
        * @param {Number} fieldRange - Field Range of view valid values: `90`, `180`, or `360`.
        */
        validateFieldRange: function(fieldRange){
            var validRanges = [90, 180, 360];
            if(validRanges.indexOf(fieldRange) === -1){
                throw new Error('fieldRange must be one of: ' + validRanges.join(','));
            }
        },

        /**
        * Converts a string direction to an rot direction
        * @method directionStringToArray
        * @param {String} direction - Direction of fov (used as default) (not used for fieldRange 360) valid directions: ['up', 'down', 'left', 'right', 'up_left', 'up_right', 'down_left', 'down_right'].
        * @return {Array} [x, y]
        */
        directionStringToArray: function(direction){
            var coord = RL.Util.getOffsetCoordsFromDirection(direction);
            return [coord.x, coord.y];
        },

        /**
        * Calculates the fovROT data relative to given coords.
        * @method update
        * @param {Number} x - The map coordinate position to calculate FovROT from on the x axis.
        * @param {Number} y - The map coordinate position to calculate FovROT from on the y axis.
        * @param {Number} [fieldRange = this.fieldRange || 360] - Field Range of view 90, 180, or 360.
        * @param {String|ROT.DIRS[8].x} [direction = this.direction || 'up'] - Direction of fov (not used for fieldRange 360) valid directions: ['up', 'down', 'left', 'right', 'up_left', 'up_right', 'down_left', 'down_right'];.
        * @param {Number} [maxViewDistance = this.maxViewDistance] - Max visible distance in tiles.
        * @param {Entity} [entity] - The entity to check tile visibility with.
        */
        update: function(x, y, fieldRange, direction, maxViewDistance, entity){

            if(fieldRange === void 0){
                fieldRange = this.fieldRange;
            }

            if(direction === void 0){
                direction = this.direction;
            }

            if(fieldRange !== 360 && typeof direction === 'string'){
                direction = this.directionStringToArray(direction);
            }
            this.direction = direction;
            if(maxViewDistance === void 0){
                maxViewDistance = this.maxViewDistance;
            }

            this.validateFieldRange(fieldRange);

            this.visibleTiles = [];
            this.visibleTileKeys = [];
            this.fovMap.reset();
            var entityCanSeeThrough = this.getEntityCanSeeThroughCallback(entity);
            var fov = new ROT.FOV.RecursiveShadowcasting(entityCanSeeThrough);

            var setMapTileVisible = this.setMapTileVisible.bind(this);

            if(fieldRange === 360){
                fov.compute(x, y, maxViewDistance, setMapTileVisible);
            }
            else {
                if(fieldRange === 180){
                    fov.compute180(x, y, maxViewDistance, direction, setMapTileVisible);
                }
                else if(fieldRange === 90){
                    fov.compute90(x, y, maxViewDistance, direction, setMapTileVisible);
                }
            }
        },

        /**
        * Retrieves the visibility of the tile at given coords
        * @method get
        * @param {Number} x - The map coord position to get FovROT visibility from.
        * @param {Number} y - The map coord position to get FovROT visibility from.
        * @return {Bool}
        */
        get: function(x, y){
            return this.fovMap.get(x, y);
        },

        /**
        * Checks if a tile blocks line of sight
        * @method entityCanSeeThrough
        * @param {Entity} entity - The entity to make a callback for.
        * @return {Function}
        */
        getEntityCanSeeThroughCallback: function(entity){
            var game = this.game;
            return function(x, y){
                return game.entityCanSeeThrough(entity, x, y);
            };
        },

        /**
        * Sets the visibility of a checked map tile
        * @method setMapTileVisible
        * @param {Number} x - The map coord position to set.
        * @param {Number} y - The map coord position to set.
        * @param {Number} range - The distance from this fov origin.
        * @param {Number} visibility - The visibility of this tile coord.
        */
        setMapTileVisible: function(x, y, range, visibility){
            this.fovMap.set(x, y, visibility);
            if(visibility){
                var tile = this.game.map.get(x, y);
                if(tile){
                    var key = x + ',' + y;
                    // check for duplicates
                    if(this.visibleTileKeys.indexOf(key) === -1){
                        this.visibleTiles.push({
                            x: x,
                            y: y,
                            value: tile,
                            range: range
                        });
                        this.visibleTileKeys.push(key);
                    }
                }
            }
        },

        /**
        * Sets the size of the map to mange fovROT within.
        * @method setSize
        * @param {Number} width - Width of current map in tiles.
        * @param {Number} height - Height of current map in tiles.
        */
        setSize: function(width, height){
            this.fovMap.setSize(width, height);
        }

    };

    root.RL.FovROT = FovROT;

}(this));