gamekit-utils
Version:
Minimal, fast and useful utilities for randomness, array manipulation and math — built for games, UI logic and generative design.
125 lines (116 loc) • 3.35 kB
JavaScript
/**
* Returns a random element from an array.
* Throws an error if the array is empty.
*
* @example
* random([1, 2, 3]); // → 2
*/
const random = (arr) => {
if (!Array.isArray(arr)) {
throw new TypeError("Expected an array");
}
if (arr.length === 0) {
throw new RangeError("Cannot select a random element from an empty array");
}
const index = Math.floor(Math.random() * arr.length);
return arr[index];
};
/**
* Returns a new array with the same elements in random order (Fisher–Yates).
*
* Note: Only the array structure is copied. Objects inside are not cloned.
*
* @example
* shuffle([1, 2, 3]); // → [2, 3, 1]
*/
const shuffle = (arr) => {
const result = [...arr]; // shallow copy
for (let i = result.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[result[i], result[j]] = [result[j], result[i]];
}
return result;
};
/**
* Picks `n` unique random elements from the array.
*
* @throws if n > arr.length
*/
function pickN(arr, n) {
if (!Array.isArray(arr)) {
throw new TypeError("Expected an array");
}
if (n > arr.length) {
throw new RangeError("Cannot pick more elements than array contains");
}
return shuffle(arr).slice(0, n);
}
/**
* Returns true with the given percentage chance (0–100).
*
* @example
* chance(25) // ~25% chance to return true
*/
function chance(percent) {
if (typeof percent !== "number" || isNaN(percent)) {
throw new TypeError("Chance percent must be a valid number");
}
if (percent < 0 || percent > 100) {
throw new RangeError("Chance percent must be between 0 and 100");
}
return Math.random() < percent / 100;
}
/**
* Clamps a number between min and max bounds.
*
* @example
* clamp(5, 1, 10) // → 5
* clamp(-2, 0, 10) // → 0
* clamp(12, 0, 10) // → 10
*/
function clamp(val, min, max) {
if (min > max) {
throw new RangeError("clamp: min cannot be greater than max");
}
return Math.min(Math.max(val, min), max);
}
/**
* Linearly interpolate between two values.
* @param a The start value.
* @param b The end value.
* @param t The interpolation factor, clamped between 0 and 1.
* @returns The interpolated value.
*/
function lerp(a, b, t) {
return a + (b - a) * t;
}
/**
* Normalizes a value t from the range [a, b] to [0, 1].
*
* @param a The start of the range.
* @param b The end of the range.
* @param t The value to normalize.
* @returns The normalized value in [0, 1].
*
* @example
* normalize(10, 20, 15) // → 0.5
* normalize(0, 100, 25) // → 0.25
*/
function normalize(a, b, t) {
if (a === b)
throw new RangeError('normalize: a and b cannot be equal');
return (t - a) / (b - a);
}
/**
* Creates a 2D array.
* @param rows The number of rows.
* @param cols The number of columns.
* @param value The initial value or a function to generate values.
* @returns A 2D array filled with the specified value.
*/
function create2D(rows, cols, value) {
const isFn = typeof value === "function";
return Array.from({ length: rows }, (_, r) => Array.from({ length: cols }, (_, c) => isFn ? value(r, c) : value));
}
export { chance, clamp, create2D, lerp, normalize, pickN, random, shuffle };
//# sourceMappingURL=index.js.map