@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
306 lines (260 loc) • 6.58 kB
JavaScript
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;