@litecanvas/utils
Version:
Utilities to help build litecanvas games
257 lines (253 loc) • 6.02 kB
JavaScript
(() => {
var __defProp = Object.defineProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
// src/_global.js
globalThis.utils = globalThis.utils || {};
globalThis.utils.global = (overrides = true) => {
for (const key in globalThis.utils) {
if ("global" === key) continue;
if (overrides || globalThis[key] === void 0) {
globalThis[key] = globalThis.utils[key];
}
}
};
// src/grid/index.js
var index_exports = {};
__export(index_exports, {
Grid: () => Grid,
TypedGrid: () => TypedGrid
});
var Grid = class _Grid {
/** @type {number} The grid width */
_w;
/** @type {number} The grid height */
_h;
/** @type {any[]} The grid cells */
_c;
/**
* @param {number} width The grid width
* @param {number} height The grid height
*/
constructor(width, height, values = []) {
this._w = Math.max(1, ~~width);
this._h = Math.max(1, ~~height);
this._c = values;
}
[Symbol.iterator]() {
let i = 0;
return {
next: () => {
return {
value: [this.indexToPointX(i), this.indexToPointY(i), this._c[i++]],
done: i > this._c.length
};
}
};
}
/**
* @returns {Grid} the cloned grid
*/
clone() {
return new _Grid(this._w, this._h, this._c);
}
/**
* Delete all cell values.
*/
clear() {
this.forEach((x, y) => this.set(x, y, void 0));
}
/**
* @returns {number}
* @readonly
*/
get width() {
return this._w;
}
/**
* @returns {number}
* @readonly
*/
get height() {
return this._h;
}
/**
* The the value of a grid's cell.
*
* @param {number} x
* @param {number} y
* @param {any} value
*/
set(x, y, value) {
this._c[this.pointToIndex(x, y)] = value;
}
/**
* Returns the value of a grid's cell.
*
* @param {number} x
* @param {number} y
* @returns {any}
*/
get(x, y) {
return this._c[this.pointToIndex(x, y)];
}
/**
* Returns true if the which cell has any value not equal to `null` or `undefined`.
*
* @param {number} x
* @param {number} y
* @returns {boolean}
*/
has(x, y) {
return this.get(x, y) != null;
}
/**
* Checks if a which point (x, y) is within the grid.
*
* @param {number} x
* @param {number} y
* @returns {boolean}
*/
check(x, y) {
return x >= 0 && x < this._w && y >= 0 && y < this._h;
}
/**
* Returns the total of cells.
*
* @returns {number}
*/
get length() {
return this._w * this._h;
}
/**
* Convert a grid point (X, Y) to a index.
*
* @param {number} x
* @param {number} y
* @returns {number} The index
*/
pointToIndex(x, y) {
return this.clampX(~~x) + this.clampY(~~y) * this._w;
}
/**
* Convert index to a grid point X.
*
* @param {number} index
* @returns {number}
*/
indexToPointX(index) {
return index % this._w;
}
/**
* Convert index to a grid point Y.
*
* @param {number} index
* @returns {number}
*/
indexToPointY(index) {
return Math.floor(index / this._w);
}
/**
* Loops over all grid cells.
*
* @callback GridForEachCallback
* @param {number} x
* @param {number} y
* @param {any} value
* @param {Grid} grid
* @returns {boolean?} returns `false` to stop/break the loop
*
* @param {GridForEachCallback} handler
* @param {boolean} [reverse=false]
*/
forEach(handler, reverse = false) {
let i = reverse ? this.length - 1 : 0, limit = reverse ? -1 : this.length, step = reverse ? -1 : 1;
while (i !== limit) {
const x = this.indexToPointX(i), y = this.indexToPointY(i), cellValue = this._c[i];
if (false === handler(x, y, cellValue, this)) break;
i += step;
}
}
/**
* @param {*} value
*/
fill(value) {
this.forEach((x, y) => {
this.set(x, y, value);
});
}
/**
* @param {number} y
* @returns {number}
*/
clampX(x) {
return _clamp(x, 0, this._w - 1);
}
/**
* @param {number} y
* @returns {number}
*/
clampY(y) {
return _clamp(y, 0, this._h - 1);
}
/**
* Returns the cell values in a single array.
*
* @returns {any[]}
*/
toArray() {
return this._c.slice();
}
/**
* @param {string} separator
* @param {boolean} format
* @returns {string}
*/
toString(separator = " ", format = true) {
if (!format) return this._c.join(separator);
const rows = [];
this.forEach((x, y, value) => {
rows[y] = rows[y] || "";
rows[y] += value + separator;
});
return rows.join("\n");
}
};
var TypedGrid = class _TypedGrid extends Grid {
/**
* @param {number} width The grid width
* @param {number} height The grid height
*/
constructor(width, height, TypedArray = Uint8Array) {
super(width, height, null);
this._c = new TypedArray(this._w * this._h);
}
/**
* @param {number} x
* @param {number} y
* @returns {boolean}
*/
has(x, y) {
return this.get(x, y) !== 0;
}
/**
* @returns {TypedGrid}
*/
clone() {
const copy = new _TypedGrid(this._w, this._h, this._c.constructor);
this.forEach((x, y, value) => {
copy.set(x, y, value);
});
return copy;
}
};
function _clamp(value, min, max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
// src/grid/_web.js
globalThis.utils = Object.assign(globalThis.utils || {}, index_exports);
})();