Reference Source

src/layer.mjs

import { Parallax } from './parallax.mjs';

export class Layer {
    /**
     * The configuration object of this layer.
     * @private
     * @type {Object}
     * @param {number} horizontalSpeed - The horizontal speed of the layer.
     * @param {number} verticalSpeed - The vertical speed of the layer.
     * @param {number} plane - The plane this parallax layer will occupy.
     * @param {Diob[] | MapObject[]} backgrounds - An array of instances that will serve as the background. These are automatically toggled to repeat.
     * @param {Set} instances - A set of instances currently on the layer.
     */
    config = {
        // Move the instance with the camera if the parallax is set to 0
        horizontalSpeed: 0,
        verticalSpeed: 0,
        plane: 1,
        backgrounds: new Set(),
        instances: new Set()
    }
    /**
     * Creates a new Parallax layer with the supplied configuration.
     * When creating a layer, all instances and backgrounds should already be on the map.
     * @param {Object} pConfig - The configuration of the parallax layer.
     * @prop {number} pConfig.horizontalSpeed - The horizontal speed of the layer.
     * @prop {number} pConfig.verticalSpeed - The vertical speed of the layer. 
     * @prop {number} pConfig.plane - The plane this layer will occupy.
     * @param {Diob[] | MapObject[]} pConfig.backgrounds - An array of instances that will serve as the background. These are automatically toggled to repeat.
     * @prop {Diob[] | MapObject[]} pConfig.instances - The instances that will be added to the layer. 
     */
    constructor(pConfig) {
        this.updateConfigSpeed(pConfig, true);

        if (!typeof pConfig.plane === 'number') {
            Parallax.logger.prefix('Parallax-Module').warn('Expected a number for "pConfig.plane", but received:', typeof pConfig.plane, '\n Default plane of "1" used.');
        } else {
            this.config.plane = pConfig.plane;
        }

        const instanceConfig = {
            x: this.config.horizontalSpeed,
            y: this.config.verticalSpeed
        }

        if (Array.isArray(pConfig.instances)) {
            pConfig.instances.forEach(pInstance => {
                pInstance.plane = this.config.plane;
                this.add(pInstance, instanceConfig)
            });
        }

        if (Array.isArray(pConfig.backgrounds)) {
            // Backgrounds automatically loop
            instanceConfig.loop = true;
            pConfig.backgrounds.forEach(pInstance => {
                pInstance.plane = this.config.plane;
                this.add(pInstance, instanceConfig)
            });
        }
    }
    /**
     * Updates the configuration speed of the layer.
     * @param {Object} pConfig - The speed configuration of the parallax layer.
     * @prop {number} pConfig.horizontalSpeed - The horizontal speed of the layer.
     * @prop {number} pConfig.verticalSpeed - The vertical speed of the layer. 
     * @param {boolean} pUpdateLayerConfigOnly - If only to update the layer config and not the instance config.
     */
    updateConfigSpeed(pConfig, pUpdateLayerConfigOnly) {
        this.updateHorizontalSpeed(pConfig.horizontalSpeed, pUpdateLayerConfigOnly);
        this.updateVerticalSpeed(pConfig.verticalSpeed, pUpdateLayerConfigOnly);
    }
    /**
     * Updates the horizontal speed of this layer.
     * @param {number} pHorizontalSpeed - The new horizontal speed.
     * @param {boolean} pUpdateLayerConfigOnly - If only to update the layer config and not the instance config.
     */
    updateHorizontalSpeed(pHorizontalSpeed, pUpdateLayerConfigOnly) {
        const inValidHorizontal = pHorizontalSpeed && typeof pHorizontalSpeed !== 'number';

        if (inValidHorizontal) {
            Parallax.logger.prefix('Parallax-Module').warn('Expected a number for "pHorizontalSpeed", but received:', typeof pHorizontalSpeed);
            return
        }

        this.config.horizontalSpeed = pHorizontalSpeed;

        if (!pUpdateLayerConfigOnly) {
            const update = (pInstance) => {
                const parallaxInfo = Parallax.instanceWeakMap.get(pInstance);
                parallaxInfo.x = pVerticalSpeed;
            }

            this.instances.forEach(pInstance => {
                update(pInstance);
            });
            this.backgrounds.forEach(pInstance => {
                update(pInstance);
            });
        }
    }
    /**
     * Updates the vertical speed of the layer.
     * @param {number} pVerticalSpeed - The new vertical speed. 
     * @param {boolean} pUpdateLayerConfigOnly - If only to update the layer config and not the instance config.
     */
    updateVerticalSpeed(pVerticalSpeed, pUpdateLayerConfigOnly) {
        const inValidVertical = pVerticalSpeed && typeof pVerticalSpeed !== 'number';

        if (inValidVertical) {
            Parallax.logger.prefix('Parallax-Module').warn('Expected a number for "pVerticalSpeed", but received:', typeof pVerticalSpeed);
            return
        }

        this.config.verticalSpeed = pVerticalSpeed;

        if (!pUpdateLayerConfigOnly) {
            const update = (pInstance) => {
                const parallaxInfo = Parallax.instanceWeakMap.get(pInstance);
                parallaxInfo.y = pVerticalSpeed;
            }

            this.instances.forEach(pInstance => {
                update(pInstance);
            });
            this.backgrounds.forEach(pInstance => {
                update(pInstance);
            });
        }
    }
    /**
     * Adds the instance to the parallax layer.
     * When using this API the instance should already be on the map.
     * @param {Diob} pInstance - The instance to add to the layer.
     * @param {Object} pConfig - The personal config of this instance. Akin to the parallax info passed via the `Parallax.add` API.
     * @prop {number} pConfig.x - The horizontal speed of this instance. (This will be ignored and the layer's speed will be used.)
     * @prop {number} pConfig.y - The vertical speed of this instance. (This will be ignored and the layer's speed will be used.)
     * @prop {boolean} pConfig.loop - Whether this instance will be treated as a background and loop seamlessly.
     */
    add(pInstance, pConfig) {
        if (this.config.instances.has(pInstance)) return;
        this.config.instances.add(pInstance);
        const config = pConfig 
            ? {
                x: this.config.horizontalSpeed,
                y: this.config.verticalSpeed,
                loop: pConfig.loop
            }
            : {
                x: this.config.horizontalSpeed,
                y: this.config.verticalSpeed
            }
        pInstance.plane = this.config.plane;
        Parallax.add(pInstance, config);
    }
    /**
     * Removes the instance from the parallax layer.
     * @param {Diob} pInstance - The instance to remove from the layer.
     */
    remove(pInstance) {
        this.config.instances.delete(pInstance);
        Parallax.remove(pInstance);
    }
}