Source: utils/bounding_box.js

/*
 * File: bounding_box.js
 *
 * defines an Axis Aligned Bounding Box (AABB)
 * 
 */
"use strict";
/**
 * Enum for collision location
 * @memberof BoundingBox
 * @enum
 */
const eBoundCollideStatus = Object.freeze({
    eCollideLeft: 1,
    eCollideRight: 2,
    eCollideTop: 4,
    eCollideBottom: 8,
    eInside: 16,
    eOutside: 0
});

class BoundingBox {
    /**
     * @classdesc Defines a rectangle that is used as the border of a GameObject for collisions
     *<p>Found in Chapter 6, page 297 of the textbook</p>
     * Example: 
     * {@link https://mylesacd.github.io/build-your-own-2d-game-engine-2e-doc/BookSourceCode/chapter6/6.3.bbox_and_collisions/index.html 6.3 Bounding Box}
     * @param {vec2} centerPos - center position of the bounding box in world coordinates
     * @param {float} w - width of the bounding box
     * @param {float} h - height of the bounding box
     * @return {BoundingBox} a new BoundingBox instance
     */
    constructor(centerPos, w, h) {
        this.mLL = vec2.fromValues(0, 0);
        this.setBounds(centerPos, w, h);
    }

    // rotation is ignored.
    // centerPos is a vec2
    /**
     * Sets the bounds of the BoundingBox ignoring rotation
     * @method
     * @param {vec2} centerPos - center position of the bounding box in world coordinates
     * @param {float} w - width of the bounding box
     * @param {float} h - height of the bounding box
     */
    setBounds(centerPos, w, h) {
        this.mWidth = w;
        this.mHeight = h;
        this.mLL[0] = centerPos[0] - (w / 2);
        this.mLL[1] = centerPos[1] - (h / 2);
    }

    /**
     * Tests if the world coordinate point (x,y) is within the BoundingBox
     * @method
     * @param {float} x  - horizontal world coordinate position
     * @param {float} y  - vertical world coordinate position
     * @returns {boolean} if the WC point (x,y) is within the BoundingBox
     */
    containsPoint(x, y) {
        return ((x > this.minX()) && (x < this.maxX()) &&
            (y > this.minY()) && (y < this.maxY()));
    }
    /**
     * Tests if this BoundingBox intersects the otherBound
     * @method
     * @param {BoundingBox} otherBound - the other BoundingBox to test for intersection
     * @returns {boolean} if this BoundingBox intersects the other
     */
    intersectsBound(otherBound) {
        return ((this.minX() < otherBound.maxX()) &&
            (this.maxX() > otherBound.minX()) &&
            (this.minY() < otherBound.maxY()) &&
            (this.maxY() > otherBound.minY()));
    }

    // returns the status of otherBound wrt to this.
    /**
     * Returns the collision status of this BoundingBox with another BoundingBox
     * @method
     * @param {BoundingBox} otherBound - the other BoundingBox to test collision with
     * @returns {eBoundCollideStatus} status - enum of collision location
     */
    boundCollideStatus(otherBound) {
        let status = eBoundCollideStatus.eOutside;

        if (this.intersectsBound(otherBound)) {
            if (otherBound.minX() < this.minX()) {
                status |= eBoundCollideStatus.eCollideLeft;
            }
            if (otherBound.maxX() > this.maxX()) {
                status |= eBoundCollideStatus.eCollideRight;
            }
            if (otherBound.minY() < this.minY()) {
                status |= eBoundCollideStatus.eCollideBottom;
            }
            if (otherBound.maxY() > this.maxY()) {
                status |= eBoundCollideStatus.eCollideTop;
            }

            // if the bounds intersects and yet none of the sides overlaps
            // otherBound is completely inside thisBound
            if (status === eBoundCollideStatus.eOutside) {
                status = eBoundCollideStatus.eInside;
            }
        }
        return status;
    }
    /**
     * Returns the x world coordinate of this BoundingBox's lower left corner
     * @method
     * @returns {float} the x world coordinate of this BoundingBox's lower left corner
     */
    minX() { return this.mLL[0]; }
    
    /**
     * Returns the x world coordinate of this BoundingBox's lower right corner
     * @method
     * @returns {float} the x world coordinate of this BoundingBox's lower right corner
     */
    maxX() { return this.mLL[0] + this.mWidth; }
   
    /**
     * Returns the y world coordinate of this BoundingBox's lower left corner
     * @method
     * @returns {float} the y world coordinate of this BoundingBox's lower left corner
     */
    minY() { return this.mLL[1]; }
   
    /**
     * Returns the y world coordinate of this BoundingBox's  upper left corner
     * @method
     * @returns {float} the y world coordinate of this BoundingBox's upper left corner
     */
    maxY() { return this.mLL[1] + this.mHeight; }
}

export {eBoundCollideStatus}
export default BoundingBox;