UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

306 lines (260 loc) • 6.58 kB
import { intersects1D } from "../../math/interval/intersects1D.js"; import { max2 } from "../../math/max2.js"; import { min2 } from "../../math/min2.js"; import Vector2 from "../Vector2.js"; import { aabb2_contains } from "./aabb/aabb2_contains.js"; import { aabb2_overlap_exists } from "./aabb/aabb2_overlap_exists.js"; class Rectangle { /** * * @param {number} x * @param {number} y * @param {number} width * @param {number} height * @constructor */ constructor(x = 0, y = 0, width = 0, height = 0) { /** * @readonly * @type {Vector2} */ this.position = new Vector2(x, y); /** * @readonly * @type {Vector2} */ this.size = new Vector2(width, height); } /** * * @return {number} */ get x0() { return this.position.x; } /** * * @return {number} */ get x1() { return this.position.x + this.size.x; } /** * * @return {number} */ get y0() { return this.position.y; } /** * * @return {number} */ get y1() { return this.position.y + this.size.y; } /** * * @param {number} x * @param {number} y * @param {number} width * @param {number} height */ set(x, y, width, height) { this.size.set(width, height); this.position.set(x, y); } /** * * @returns {Rectangle} */ clone() { const position = this.position; const size = this.size; return new Rectangle( position.x, position.y, size.x, size.y ); } /** * * @param {Rectangle} other */ copy(other) { this.position.copy(other.position); this.size.copy(other.size); } /** * * @param {number} x0 * @param {number} y0 * @param {number} x1 * @param {number} y1 * @returns {boolean} */ _intersects(x0, y0, x1, y1) { const p = this.position; const s = this.size; const _x0 = p.x; const _y0 = p.y; return intersects1D(x0, x1, _x0, s.x + _x0) && intersects1D(y0, y1, _y0, _y0 + s.y); } /** * * @param {Rectangle} other * @returns {boolean} */ intersects(other) { const x0 = other.position.x; const y0 = other.position.y; const y1 = other.size.y + y0; const x1 = other.size.x + x0; return this._intersects(x0, y0, x1, y1); } /** * * @param {number} x0 * @param {number} y0 * @param {number} x1 * @param {number} y1 * @returns {boolean} */ _overlaps(x0, y0, x1, y1) { const p = this.position; const s = this.size; const _x0 = p.x; const _y0 = p.y; const _x1 = s.x + _x0; const _y1 = _y0 + s.y; return aabb2_overlap_exists( _x0, _y0, _x1, _y1, x0, y0, x1, y1 ); } /** * * @param {Rectangle} other * @returns {boolean} */ overlaps(other) { const x0 = other.position.x; const y0 = other.position.y; const y1 = other.size.y + y0; const x1 = other.size.x + x0; return this._overlaps(x0, y0, x1, y1); } /** * * @param {number} x0 * @param {number} y0 * @param {number} x1 * @param {number} y1 */ _resizeToFit(x0, y0, x1, y1) { const size = this.size; const _x0 = this.position.x; const _y0 = this.position.y; let _y1 = size.y + _y0; let _x1 = size.x + _x0; if (Number.isNaN(_x1)) { _x1 = -Infinity; } if (Number.isNaN(_y1)) { _y1 = -Infinity; } const nX0 = min2(x0, _x0); const nY0 = min2(y0, _y0); const nX1 = max2(x1, _x1); const nY1 = max2(y1, _y1); this.position.set(nX0, nY0); size.set(nX1 - nX0, nY1 - nY0); } /** * * @param {Rectangle} other */ resizeToFit(other) { const x0 = other.position.x; const y0 = other.position.y; const y1 = other.size.y + y0; const x1 = other.size.x + x0; return this._resizeToFit(x0, y0, x1, y1); } /** * * @param {number} x0 * @param {number} y0 * @param {number} x1 * @param {number} y1 * @returns {boolean} */ _contains(x0, y0, x1, y1) { const size = this.size; const position = this.position; const _x0 = position.x; const _y0 = position.y; const _y1 = size.y + _y0; const _x1 = size.x + _x0; return aabb2_contains( _x0, _y0, _x1, _y1, x0, y0, x1, y1 ); } /** * * @param {Rectangle} other * @returns {boolean} */ contains(other) { const x0 = other.position.x; const y0 = other.position.y; const y1 = other.size.y + y0; const x1 = other.size.x + x0; return this._contains(x0, y0, x1, y1); } /** * * @param {Vector2} result */ computeCenter(result) { const p = this.position; const s = this.size; const x = p.x + s.x / 2; const y = p.y + s.y / 2; result.set(x, y); } /** * * @return {number} */ computeArea() { return this.size.x * this.size.y; } /** * * @param {Array.<number>|Float32Array|Float64Array|Uint8Array} target * @param {number} [targetOffset=0] */ toArray(target, targetOffset = 0) { target[targetOffset] = this.position.x; target[targetOffset + 1] = this.position.y; target[targetOffset + 2] = this.size.x; target[targetOffset + 3] = this.size.y; } toJSON() { return { position: this.position.toJSON(), size: this.size.toJSON() }; } fromJSON(json) { this.position.fromJSON(json.position); this.size.fromJSON(json.size); } } /** * @readonly * @type {boolean} */ Rectangle.prototype.isRectangle = true; export default Rectangle;