Skip to content

Instantly share code, notes, and snippets.

@owenroberts
Last active March 7, 2024 15:43
Show Gist options
  • Save owenroberts/8a7c2a19b8248f61ef94ab733eceb8fb to your computer and use it in GitHub Desktop.
Save owenroberts/8a7c2a19b8248f61ef94ab733eceb8fb to your computer and use it in GitHub Desktop.
Some helpers for various projects
/* some helpers */
Array.prototype.insert = function(index, item) {
this.splice(index, 0, item);
};
Number.prototype.clamp = function(min, max) {
return max > min ?
Math.min(Math.max(this, min), max) :
Math.min(Math.max(this, max), min);
};
// requestAnim shim layer by Paul Irish
// https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
if (typeof window !== 'undefined') {
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback, /* DOMElement */ element){
window.setTimeout(callback, 1000 / 60);
};
})();
}
const Cool = {};
Cool.map = function(value, low1, high1, low2, high2, clamp) {
let v = low2 + (high2 - low2) * (value - low1) / (high1 - low1) || 0;
return clamp ? v.clamp(low2, high2) : v;
};
Cool.padNumber = function(number, length) {
let my_string = '' + number;
while (my_string.length < length) {
my_string = '0' + my_string;
}
return my_string;
};
Cool.random = function(min, max) {
if (!max) {
if (typeof min === "number") {
return Math.random() * (min);
} else if (Array.isArray(min)) {
return min[Math.floor(Math.random() * min.length)];
} else if (typeof min == 'object') {
return min[Cool.random(Object.keys(min))];
}
} else {
return Math.random() * (max - min) + min;
}
};
Cool.randomInt = function(min, max) {
if (!max) max = min, min = 0;
return Math.round( Math.random() * (max - min) + min );
};
Cool.randInt = Cool.randomInt;
Cool.chance = function(n) {
return Cool.random(1) < n;
};
Cool.choice = function(choices) {
if (!Array.isArray(choices)) choices = [...arguments];
return choices[Math.floor(Math.random() * choices.length)];
};
Cool.shuffle = function(array) {
// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
};
// https://stackoverflow.com/a/36481059
Cool.randomNormalInverse = function() {
let u = 0, v = 0;
while (u === 0) u = Math.random(); //Converting [0,1) to (0,1)
while (v === 0) v = Math.random();
const r = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
let m = Cool.map(r, -3.5, 3.5, 0, 1); /* convert normal range to 0 - 1 */
return m > 0.5 ? m - 0.5 : m + 0.5; /* invert range */
};
/* converting color values
http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
https://gist.github.com/kig/2115205 // hslToHex
*/
Cool.componentToHex = function(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
};
Cool.HueToRgb = function(m1, m2, hue) {
var v;
if (hue < 0)
hue += 1;
else if (hue > 1)
hue -= 1;
if (6 * hue < 1)
v = m1 + (m2 - m1) * hue * 6;
else if (2 * hue < 1)
v = m2;
else if (3 * hue < 2)
v = m1 + (m2 - m1) * (2/3 - hue) * 6;
else
v = m1;
return 255 * v;
};
Cool.hslToHex = function(c) {
var hue=0, saturation=0, lightness=0;
var tmp = 0;
for (var i=0,j=0,k=0; i<c.length; i++) {
var ch = c.charCodeAt(i);
if (ch >= 48 && ch <= 57) {
tmp = tmp * 10 + (ch-48);
k = 1;
continue;
} else if (k === 1) {
switch(j) {
case 0: hue = (tmp % 360) / 360; break;
case 1:
saturation = (tmp > 100 ? 100 : tmp) / 100; break;
case 2:
lightness = (tmp > 100 ? 100 : tmp) / 100; break;
}
j++;
}
k = 0;
tmp = 0;
}
var h = (hue / (1/6));
var c = (1-Math.abs(2*lightness-1))*saturation;
var x = c * (1-Math.abs((h%2)-1));
switch (h | 0) {
case 0: r=c; g=x; b=0; break;
case 1: r=x; g=c; b=0; break;
case 2: r=0; g=c; b=x; break;
case 3: r=0; g=x; b=c; break;
case 4: r=x; g=0; b=c; break;
case 5: r=c; g=0; b=x; break;
}
var m = lightness - 0.5*c;
r+=m; g+=m; b+=m;
r=r*255|0; g=g*255|0; b=b*255|0;
var hex = '';
k = (r >> 4 & 0xf) + 48;
if (k > 57) k += 7;
hex += String.fromCharCode(k);
k = (r & 0xf) + 48;
if (k > 57) k += 7;
hex += String.fromCharCode(k);
k = (g >> 4 & 0xf) + 48;
if (k > 57) k += 7;
hex += String.fromCharCode(k);
k = (g & 0xf) + 48;
if (k > 57) k += 7;
hex += String.fromCharCode(k);
k = (b >> 4 & 0xf) + 48;
if (k > 57) k += 7;
hex += String.fromCharCode(k);
k = (b & 0xf) + 48;
if (k > 57) k += 7;
hex += String.fromCharCode(k);
return hex;
};
Cool.hexToRgb = function(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
};
Cool.rgbToHsl = function(rgb) {
rgb.r /= 255, rgb.g /= 255, rgb.b /= 255;
var max = Math.max(rgb.r, rgb.g, rgb.b), min = Math.min(rgb.r, rgb.g, rgb.b);
var h, s, l = (max + min) / 2;
if (max == min) { h = s = 0; }
else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max){
case rgb.r: h = (rgb.g - rgb.b) / d + (rgb.g < rgb.b ? 6 : 0); break;
case rgb.g: h = (rgb.b - rgb.r) / d + 2; break;
case rgb.b: h = (rgb.r - rgb.g) / d + 4; break;
}
h /= 6;
}
return [(h*360+0.5)|0, ((s*100+0.5)|0), ((l*100+0.5)|0)];
};
// http://wowmotty.blogspot.com/2009/06/convert-jquery-rgb-output-to-hex-color.html
Cool.rgb2hex = function(orig) {
var rgb = orig.replace(/\s/g,'').match(/^rgba?\((\d+),(\d+),(\d+)/i);
return (rgb && rgb.length === 4) ? "#" +
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : orig;
};
/* ascii key mapping */
Cool.keys = {
"9": "tab",
"13": "enter",
"27": "escape",
"32": "space",
"37": "left",
"38": "up",
"39": "right",
"40": "down",
"48": "0",
"49": "1",
"50": "2",
"51": "3",
"52": "4",
"53": "5",
"54": "6",
"55": "7",
"56": "8",
"57": "9",
"65": "a",
"66": "b",
"67": "c",
"68": "d",
"69": "e",
"70": "f",
"71": "g",
"72": "h",
"73": "i",
"74": "j",
"75": "k",
"76": "l",
"77": "m",
"78": "n",
"79": "o",
"80": "p",
"81": "q",
"82": "r",
"83": "s",
"84": "t",
"85": "u",
"86": "v",
"87": "w",
"88": "x",
"89": "y",
"90": "z",
"186": ";",
"187": "+",
"188": ",",
"190": ".",
"191": "/",
"192": "`",
"219": "[",
"220": "backslash",
"221": "]",
"222": "'",
};
/* vector stuff */
Cool.Vector = function(x,y) {
this.x = x || 0;
this.y = y || 0;
if (Array.isArray(this.x)) {
this.x = x[0];
this.y = x[1];
}
this.random = function(xMin, xMax, yMin, yMax) {
if (arguments.length == 1) {
this.x = Cool.random(-xMin, xMin);
this.y = Cool.random(-xMin, xMin);
} else if (arguments.length == 2) {
this.x = Cool.random(xMin, xMax);
this.y = Cool.random(xMin, xMax);
} else if (arguments.length == 4) {
this.x = Cool.random(xMin, xMax);
this.y = Cool.random(yMin, yMax);
} else {
console.error('You need 1, 2 or 4 arguments, dingus.');
}
return this;
};
this.zero = function() {
if ( Math.abs(this.x) > 0 || Math.abs(this.y) > 0 ) return false;
else return true;
};
this.add = function(v) {
this.x += v.x;
this.y += v.y;
return this;
};
this.subtract = function(v) {
this.x -= v.x;
this.y -= v.y;
return this;
};
this.multiply = function(n) {
if (typeof n === 'object') {
this.x *= n.x;
this.y *= n.y;
} else {
this.x *= n;
this.y *= n;
}
return this;
};
this.divide = function(n) {
if (typeof n == 'object') {
this.x /= n.x;
this.y /= n.y;
} else {
this.x /= n;
this.y /= n;
}
return this;
};
this.magnitude = function() {
return Math.sqrt(this.x*this.x + this.y*this.y);
};
this.normalize = function() {
var m = this.magnitude();
if (m != 0 && m != 1) this.divide(m);
return this;
};
this.copy = function() {
return new Cool.Vector(this.x, this.y);
};
this.distance = function(v) {
var d = new Cool.Vector(v.x, v.y);
d.subtract(this);
return d.magnitude();
};
this.round = function() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
return this;
};
this.getObj = function() {
return { x: this.x, y: this.y };
};
this.clone = function() {
return new Cool.Vector(this.x, this.y);
};
this.sameDirection = function(v) {
return Math.sign(this.x) == Math.sign(v.x) &&
Math.sign(this.y) == Math.sign(v.y);
};
this.toArray = function() {
return [this.x, this.y];
};
return this;
};
Cool.mobilecheck = function() {
var check = false;
(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
return check;
};
Cool.testPerformance = function() {
// https://stackoverflow.com/questions/19754792/measure-cpu-performance-via-js
var _speedconstant = 1.15600e-8; //if speed=(c*a)/t, then constant=(s*t)/a and time=(a*c)/s
var d = new Date();
var amount = 150000000;
var estprocessor = 1.7; //average processor speed, in GHZ
// console.log("JSBenchmark by Aaron Becker, running loop " + amount + " times. Estimated time (for " + estprocessor + "ghz processor) is " + (Math.round(((_speedconstant * amount) / estprocessor) * 100) / 100) + "s");
for (var i = amount; i > 0; i--) {}
var newd = new Date();
var accnewd = Number(String(newd.getSeconds()) + "." + String(newd.getMilliseconds()));
var accd = Number(String(d.getSeconds()) + "." + String(d.getMilliseconds()));
var di = accnewd - accd;
//console.log(accnewd,accd,di);
if (d.getMinutes() != newd.getMinutes()) {
di = (60 * (newd.getMinutes() - d.getMinutes())) + di
}
var spd = ((_speedconstant * amount) / di);
// console.log("Time: " + Math.round(di * 1000) / 1000 + "s, estimated speed: " + Math.round(spd * 1000) / 1000 + "GHZ");
return Math.round(di * 1000) / 1000;
};
// 8 bit bit mask auto tile order for 48 tiles
// https://unit.dev/posts/blobmaps/
Cool.tileMap = [
0, 4, 68, 64, 117, 71, 197, 93, 7, 199, 215, 193,
1, 5, 69, 65, 23, 223, 247, 209, 95, 255, 221, 241,
17, 21, 85, 81, 29, 127, 253, 113, 31, 119, 'x', 245,
16, 20, 84, 80, 219, 92, 116, 87, 28, 125, 124, 112,
];
if (typeof module !== 'undefined') {
module.exports.default = Cool; // does this work?
}
if (typeof window !== 'undefined') {
window.Cool = Cool;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment