FogOfWar.js

/* 
 * Last Edit: Daniel Lorentz 3/6/21
 * Fog of War class
 * Class handles all of the fog of war elements
 */
/*jslint node: true, vars: true */
/*global gEngine, Scene, GameObjectset, TextureObject, Camera, vec2,
  Renderable, FontRenderable, SpriteRenderable, LightRenderable,
  GameObject, Hero, Minion, Dye, Light */
/* find out more about jslint: http://www.jslint.com/help.html */

"use strict";  // Operate in Strict mode such that variables must be declared before used!
/**
 * Creates and operates a Fog Of War effect.
 * @name FogOfWar
 * @constructor
 */
function FogOfWar(){
    this.mViewer = [];
    //this is a FogRenderable, lets us change the individual pixels
    this.overlay = null;
    this.delta = 0.5;
    this.changed = false;
}

/**
 * Creates the renderable to be displayed over areas of unknown.
 * @param {Image} theOverlay - picture to be used for unknown areas.
 * @param {int} width - width of world in WC.
 * @param {int} centerX - center of WC.
 * @param {int} centerY - center of WC.
 */
FogOfWar.prototype.setOverlay = function(theOverlay, width, centerX, centerY, 
    fogTranslusivness, unexploredTranslusivness){
    this.overlay = new FogRenderable(theOverlay, fogTranslusivness, 
    unexploredTranslusivness);
    this.overlay.getXform().setSize(width, width);
    this.overlay.getXform().setPosition(centerX, centerY);
    this.overlay.updatePixelArray(centerX, centerY, 0);
};

/**
 * Adds a new object with a Field of View to rendered FOW.
 * @param {object} target - target for FOG to follow, must have Xform.
 * @param {int} radius - radius in pixels of the viewable area.
 */
FogOfWar.prototype.addViewer = function (target, radius){
    var viewer = new FogOfWarViewer();
    viewer.setTarget(target, radius);
    this.mViewer.push(viewer);
};

/**
 * Removes an object from having a Field of View, does not delete object.
 * @param {object} target - object to be have Field of View removed.
 * @return True if successfully removed. 
 */
FogOfWar.prototype.removeViewer = function (target){
    for(var i = 0; i < this.mViewer.length; i++){
        if(this.mViewer[i].getTarget() === target){
            this.mViewer.splice(i, 1);
            return true;
        }
    }
    return false;
};

/**
 * Changes the Field of View radius for object.
 * @param {object} target - object that has already been created.
 * @param {int} radius - new radius for fild of view in World Coordinates.
 * @return True if radius successfully updated.
 */
FogOfWar.prototype.updateRadius = function (target, radius){
    for(var i = 0; i < this.mViewer.length; i++){
        if(this.mViewer[i].getTarget() === target){
            this.mViewer[i].setRadius(radius);
            return true;
        }
    }
    return false;
};

/**
 * Updates the Fog Of War to match the current location of all objects
 * with a Field of View. Must be run.
 */
FogOfWar.prototype.update = function (){
    let changed = this.changed;
    for(var i = 0; i < this.mViewer.length && !changed; i++){
        if(this.mViewer[i].checkMove()){
            //console.log("position changed");
            changed = true;
        }
    }
    if (changed){
        this.overlay.setAsFoggy();
        for(var i = 0; i < this.mViewer.length; i++){
            changed = true;
            this.mViewer[i].update();
            this.overlay.updatePixelArray(
                    this.mViewer[i].getX(),
                    this.mViewer[i].getY(),
                    this.mViewer[i].getRadius());
        }
        this.overlay.applyTexture();
        this.changed = false;
    }
};

/**
 * Draws the Fog Of War. Must be run to display Fog Of War effect.
 * @param {Camera} aCamera - Camera that Fog Of War will be drawn with.
 */
FogOfWar.prototype.draw = function (aCamera){
    this.overlay.draw(aCamera);
};

/**
 * Scene calls this funciton for all objects that are only visable in a Field of View.
 * Only prints objects who's X and Y location are within a Viewer's Field of View.
 * @param {Camera} aCamera - Camera where object will be drawn if visable.
 * @param {Object} aObject - Object with Xform to check if within a Field of View.
 */
FogOfWar.prototype.drawObject = function(aCamera, aObject){
    var visable = false;
    // find the distance from aObject to all mViewers
    for(var i = 0; i < this.mViewer.length; i++){
        // distance formula sqrt((x2 - x1)^2 + (y2 - y1)^2)
        var objectX = aObject.getXform();
        var vX = this.mViewer[i].getX(), vY = this.mViewer[i].getY();
        var oX = objectX.getXPos(), oY = objectX.getYPos();
        var distance = Math.sqrt((oX - vX)*(oX - vX)+(oY - vY)*(oY - vY));
        // if distance between aObject and this mViewer, it is 
        // visable in the FOV
        //var radius = 
        if(distance < this.mViewer[i].getRadius()){
            visable = true;
        }
    }
    
    // if visable in FOV, draw
    if(visable){
        aObject.draw(aCamera);
    }
};
/**
 * Changes how dark the Fog state is rendered. A nubmer of 0 has the fog
 * completely transparent. 255 sets the fog to completely opaque.
 * @param {Number} fogTranslusivity - Number between 0 and 255.
 */
FogOfWar.prototype.setFogTranslusiveness = function(fogTranslusivity){
    this.overlay.setFogTranslusiveness(fogTranslusivity);
    this.changed = true;
};

/**
 * Get the current value of Fog visability. 
 * @returns {Number} - Curent value of Fog visability
 */
FogOfWar.prototype.getFogTranslusiveness = function(){
    return this.overlay.getFogTranslusiveness();
};


/**
 * Changes how dark the Unknown/Unexplored state is rendered. A nubmer of 0 has the unknown
 * completely transparent. 255 sets the unknown to completely opaque.
 * @param {Number} unexploredTranslusivness - Number between 0 and 255.
 */
FogOfWar.prototype.setUnexploresTranslusiveness = function(unexploredTranslusivness){
    this.overlay.setUnexploresTranslusiveness(unexploredTranslusivness);
    this.changed = true;
};

/**
 * Get the current value of Unknown/Unexplored visability. 
 * @returns {Number} - Curent value of Unknown visability
 */
FogOfWar.prototype.getUnexploresTranslusiveness = function(){
    return this.overlay.getUnexploresTranslusiveness();
};