@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
339 lines (287 loc) • 5.9 kB
JavaScript
import { assert } from "../assert.js";
import Signal from "../events/signal/Signal.js";
import { clamp } from "../math/clamp.js";
import { computeHashFloat } from "../primitives/numbers/computeHashFloat.js";
/**
* Wrapper around a scalar value, `Vector1` is used for consistence with {@link Vector2} and {@link Vector3}
*
* @author Alex Goldring
* @copyright Company Named Limited (c) 2025
*/
export class Vector1 extends Number {
/**
*
* @param {number} [x=0]
* @constructor
* @class
* @property {number} x
*/
constructor(x = 0) {
super();
assert.isNumber(x, 'x');
assert.notNaN(x, 'x');
this.x = x;
/**
*
* @type {Signal<number,number>}
*/
this.onChanged = new Signal();
}
/**
* Inherited from Number class
* @returns {number}
*/
valueOf() {
return this.x;
}
/**
*
* @returns {string}
*/
toString() {
return String(this.x);
}
/**
* Currently held value
* @returns {number}
*/
getValue() {
return this.x;
}
/**
* Useful for sorting
* @param {Vector1} other
* @returns {number}
*/
compareTo(other) {
return this.x - other.x;
}
/**
*
* @param {number} x
* @returns {Vector1}
*/
set(x) {
assert.isNumber(x, 'x');
assert.notNaN(x, 'x');
const oldValue = this.x;
if (oldValue !== x) {
this.x = x;
if (this.onChanged.hasHandlers()) {
this.onChanged.send2(x, oldValue);
}
}
return this;
}
/**
* Set value without triggering {@link #onChanged} signal
* @param {number} x
*/
setSilent(x) {
assert.isNumber(x, 'x');
assert.notNaN(x, 'x');
this.x = x;
}
/**
*
* @return {boolean}
*/
isZero() {
return this.x === 0;
}
/**
* Increase value by 1.
* `value++`
*/
increment() {
this._add(1);
}
/**
* Decrease value by 1.
* `value--`
*/
decrement() {
this._add(-1);
}
/**
*
* @param {Number} v
* @return {Vector1}
*/
_add(v) {
return this.set(this.x + v);
}
/**
*
* @param {Vector1|Vector2|Vector3|Vector4} other
*/
add(other) {
assert.isObject(other, "other");
return this._add(other.x);
}
/**
*
* @param {Number} v
* @return {Vector1}
*/
_sub(v) {
return this._add(-v);
}
/**
*
* @param {Vector1} other
* @returns {Vector1}
*/
sub(other) {
return this._sub(other.x);
}
/**
*
* @param {Vector1} other
* @returns {Vector1}
*/
multiply(other) {
return this.set(this.x * other.x);
}
/**
*
* @param {number} v
*/
multiplyScalar(v) {
this.set(this.x * v);
}
/**
*
* @param {number} low
* @param {number} high
* @returns {Vector1}
*/
clamp(low, high) {
return this.set(clamp(this.x, low, high));
}
/**
* Negate sign of the value, if value is 7, it will become -7 and vice versa
* Zero is unaffected
*/
negate() {
this.set(-this.x);
}
/**
*
* @param {Vector1|Vector2|Vector3|Vector4} other
*/
copy(other) {
this.set(other.x);
}
/**
*
* @returns {Vector1}
*/
clone() {
return new Vector1(this.x);
}
/**
*
* @param {Vector1} other
* @returns {boolean}
*/
equals(other) {
return this.x === other.x;
}
/**
* @returns {number}
*/
hash() {
return computeHashFloat(this.x);
}
/**
*
* @param {function(newValue:number, oldValue:number)} handler
*/
process(handler) {
handler(this.x, this.x);
this.onChanged.add(handler);
}
toJSON() {
return this.x;
}
fromJSON(val) {
this.set(val);
}
/**
*
* @param {number[]} array
* @param {number} offset
*/
readFromArray(array, offset = 0) {
this.set(array[offset]);
}
/**
*
* @param {number[]} array
* @param {number} offset
*/
writeToArray(array, offset = 0) {
array[offset] = this.x;
}
asArray() {
return [this.x];
}
/**
*
* @param {BinaryBuffer} buffer
*/
toBinaryBuffer(buffer) {
buffer.writeFloat64(this.x);
}
/**
*
* @param {BinaryBuffer} buffer
*/
fromBinaryBuffer(buffer) {
const x = buffer.readFloat64();
this.set(x);
}
/**
*
* @param {Vector1} a
* @param {Vector1} b
* @return {number}
*/
static compare(a, b) {
return a.x - b.x;
}
// pretending to be an array
get 0() {
return this.x;
}
set 0(v) {
this.x = v;
}
* [Symbol.iterator]() {
yield this.x;
}
}
/**
* @readonly
* @type {boolean}
*/
Vector1.prototype.isVector1 = true;
/**
* @readonly
* @type {string}
*/
Vector1.typeName = "Vector1";
/**
* Utility singleton
* @readonly
* @type {Vector1}
*/
Vector1.zero = Object.freeze(new Vector1(0));
/**
* Utility singleton
* @readonly
* @type {Vector1}
*/
Vector1.one = Object.freeze(new Vector1(1));
export default Vector1;