Skip to content

Instantly share code, notes, and snippets.

@lovroselic
Created October 17, 2019 13:41
Show Gist options
  • Save lovroselic/d878fcc5a462c28238af503188614b86 to your computer and use it in GitHub Desktop.
Save lovroselic/d878fcc5a462c28238af503188614b86 to your computer and use it in GitHub Desktop.
Prototype LIB 2.06
console.clear();
var LIB = {
VERSION: 2.05
};
/*
Prototype and helpful functions library
as used by LS
version 2.06
changelog:
2.00: new main version, no backwards compatibility
2.01: array.removeRandomPool(N)
2.02: vector.mul default parameter set
2.03: Grid.distanceDiagonal
2.04: Vector.isDiagonal
2.05: Point.add()
2.06: round10()
*/
(function() {
function RND(start, end) {
return Math.floor(Math.random() * (++end - start) + start);
}
function coinFlip() {
let flip = RND(0, 1);
if (flip) return true;
return false;
}
function probable(x) {
let flip = RND(0, 99);
if (flip <= x) return true;
return false;
}
function round10(x) {
return Math.round(x / 10) * 10;
}
window.RND = RND;
window.coinFlip = coinFlip;
window.probable = probable;
window.round10 = round10;
})();
// Converts from degrees to radians.
Math.radians = function(degrees) {
return degrees * Math.PI / 180;
};
// Converts from radians to degrees.
Math.degrees = function(radians) {
return radians * 180 / Math.PI;
};
CanvasRenderingContext2D.prototype.pixelAt = function(x, y, size) {
size = size || 1; // default
this.fillRect(x, y, size, size);
};
CanvasRenderingContext2D.prototype.roundRect = function(
x,
y,
width,
height,
radius,
fill,
stroke
) {
var cornerRadius = {
upperLeft: 0,
upperRight: 0,
lowerLeft: 0,
lowerRight: 0
};
if (typeof stroke == "undefined") {
stroke = true;
}
if (typeof radius === "object") {
for (let side in radius) {
cornerRadius[side] = radius[side];
}
}
this.beginPath();
this.moveTo(x + cornerRadius.upperLeft, y);
this.lineTo(x + width - cornerRadius.upperRight, y);
this.quadraticCurveTo(x + width, y, x + width, y + cornerRadius.upperRight);
this.lineTo(x + width, y + height - cornerRadius.lowerRight);
this.quadraticCurveTo(
x + width,
y + height,
x + width - cornerRadius.lowerRight,
y + height
);
this.lineTo(x + cornerRadius.lowerLeft, y + height);
this.quadraticCurveTo(x, y + height, x, y + height - cornerRadius.lowerLeft);
this.lineTo(x, y + cornerRadius.upperLeft);
this.quadraticCurveTo(x, y, x + cornerRadius.upperLeft, y);
this.closePath();
if (stroke) {
this.stroke();
}
if (fill) {
this.fill();
}
};
/* collection of prototypes LS */
Array.prototype.clear = function() {
if (!this) return false;
this.splice(0, this.length);
};
Array.prototype.swap = function(x, y) {
let TMP = this[x];
this[x] = this[y];
this[y] = TMP;
return this;
};
Array.prototype.shuffle = function() {
var i = this.length,
j;
while (--i > 0) {
j = RND(0, i);
this.swap(i, j);
}
return this;
};
Array.prototype.sum = function() {
return this.reduce((a, b) => a + b, 0);
};
Array.prototype.average = function() {
return this.reduce((a, b) => a + b) / this.length;
};
Array.prototype.createPool = function(mx, N) {
if (!this) return false;
this.clear();
var tempArray = [];
for (var ix = 0; ix < mx; ix++) {
tempArray[ix] = ix;
}
var top;
for (var iy = 0; iy < N; iy++) {
top = tempArray.length;
var addx = RND(0, top - 1);
this[iy] = tempArray[addx];
tempArray.splice(addx, 1);
}
return this;
};
Array.prototype.compare = function(array) {
if (!array) return false;
var LN = this.length;
if (LN !== array.length) return false;
for (var x = 0; x < LN; x++) {
if (this[x] !== array[x]) return false;
}
return true;
};
Array.prototype.remove = function(value) {
var LN = this.length;
for (var x = 0; x < LN; x++) {
if (this[x] === value) {
this.splice(x, 1);
this.remove(value);
}
}
};
Array.prototype.chooseRandom = function() {
let LN = this.length;
let choose = RND(1, LN) - 1;
return this[choose];
};
Array.prototype.removeRandom = function() {
let LN = this.length;
let choose = RND(1, LN) - 1;
return this.splice(choose, 1)[0];
};
Array.prototype.removeRandomPool = function(N) {
let LN = this.length;
if (N >= LN) {
let temp = this.clone();
this.clear();
return temp;
}
if (N <= 0) return [];
let temp = [];
do {
temp.push(this.removeRandom());
N--;
} while (N > 0);
return temp;
};
Array.prototype.clone = function() {
return [].concat(this);
};
Array.prototype.sortByPropAsc = function(prop) {
this.sort(sort);
function sort(a, b) {
return a[prop] - b[prop];
}
};
Array.prototype.sortByPropDesc = function(prop) {
this.sort(sort);
function sort(a, b) {
return b[prop] - a[prop];
}
};
String.prototype.capitalize = function() {
return this.charAt(0).toUpperCase() + this.substr(1).toLowerCase();
};
String.prototype.trimSpace = function() {
let temp = this.split(" ");
temp.remove("");
return temp.join(" ");
};
String.prototype.changeChar = function(at, char) {
let LN = this.length - 1;
if (at > LN || at < 0) return -1;
const p1 = this.slice(0, at);
const p2 = this.slice(at + 1, ++LN);
return [p1, char, p2].join("");
};
class Grid {
constructor(x = 0, y = 0) {
this.x = parseInt(x, 10);
this.y = parseInt(y, 10);
}
static toClass(grid) {
return new Grid(grid.x, grid.y);
}
add(vector) {
return new Grid(this.x + vector.x, this.y + vector.y);
}
isInAt(dirArray) {
for (let q = 0; q < dirArray.length; q++) {
if (this.x === dirArray[q].x && this.y === dirArray[q].y) {
return q;
}
}
return -1;
}
direction(vector) {
var dx = (vector.x - this.x) / Math.abs(this.x - vector.x) || 0;
var dy = (vector.y - this.y) / Math.abs(this.y - vector.y) || 0;
return new Vector(dx, dy);
}
absDirection(vector) {
let dx = vector.x - this.x;
let dy = vector.y - this.y;
return new Vector(dx, dy);
}
same(vector) {
if (this.x === vector.x && this.y === vector.y) {
return true;
} else return false;
}
distance(vector) {
let distance = Math.abs(this.x - vector.x) + Math.abs(this.y - vector.y);
return distance;
}
distanceDiagonal(vector) {
let distance = (this.x - vector.x) ** 2 + (this.y - vector.y) ** 2;
distance = Math.floor(Math.sqrt(distance));
return distance;
}
directionSolutions(vector) {
let solutions = [];
let dir = this.direction(vector);
let absDir = this.absDirection(vector);
let split = dir.ortoSplit();
solutions.push(new Direction(split[0], Math.abs(absDir.x)));
solutions.push(new Direction(split[1], Math.abs(absDir.y)));
//SORT!!
if (solutions[0].len < solutions[1].len) solutions.swap(0, 1); //check
return solutions;
}
}
class Vector {
constructor(x = 0, y = 0) {
this.x = parseInt(x, 10);
this.y = parseInt(y, 10);
}
static toClass(vector) {
return new Vector(vector.x, vector.y);
}
isInAt(dirArray) {
for (let q = 0; q < dirArray.length; q++) {
if (this.x === dirArray[q].x && this.y === dirArray[q].y) {
return q;
}
}
return -1;
}
isInPointerArray(dirArray) {
for (let q = 0; q < dirArray.length; q++) {
if (this.x === dirArray[q].vector.x && this.y === dirArray[q].vector.y) {
return q;
}
}
return -1;
}
add(vector) {
return new Vector(this.x + vector.x, this.y + vector.y);
}
mul(vector, num = 1) {
return new Vector(this.x + num * vector.x, this.y + num * vector.y);
}
distance(vector) {
let distance = Math.abs(this.x - vector.x) + Math.abs(this.y - vector.y);
return distance;
}
mirror() {
let nx, ny;
if (this.x) {
nx = -this.x;
} else {
nx = 0;
}
if (this.y) {
ny = -this.y;
} else {
ny = 0;
}
return new Vector(nx, ny);
}
direction(vector) {
let dx = (vector.x - this.x) / Math.abs(this.x - vector.x) || 0;
let dy = (vector.y - this.y) / Math.abs(this.y - vector.y) || 0;
return new Vector(dx, dy);
}
absDirection(vector) {
let dx = vector.x - this.x;
let dy = vector.y - this.y;
return new Vector(dx, dy);
}
directionSolutions(vector) {
let solutions = [];
let dir = this.direction(vector);
let absDir = this.absDirection(vector);
let split = dir.ortoSplit();
solutions.push(new Direction(split[0], Math.abs(absDir.x)));
solutions.push(new Direction(split[1], Math.abs(absDir.y)));
//SORT!!
if (solutions[0].len < solutions[1].len) solutions.swap(0, 1); //check
return solutions;
}
ortoSplit() {
let split = [];
split.push(new Vector(this.x, 0));
split.push(new Vector(0, this.y));
return split;
}
cw() {
let directions = [UP, RIGHT, DOWN, LEFT];
let q;
for (q = 0; q < 4; q++) {
if (this.same(directions[q])) {
q++;
if (q > 3) q = 0;
return directions[q];
}
}
return null;
}
ccw() {
let directions = [UP, RIGHT, DOWN, LEFT];
let q;
for (q = 0; q < 4; q++) {
if (this.same(directions[q])) {
q--;
if (q < 0) q = 3;
return directions[q];
}
}
return null;
}
same(vector) {
if (this.x === vector.x && this.y === vector.y) {
return true;
} else return false;
}
isOrto() {
return this.x * this.y === 0;
}
isDiagonal(){
return Math.abs(this.x) === Math.abs(this.y);
}
isContra(vector) {
let X = this.x + vector.x;
let Y = this.y + vector.y;
return X === 0 && Y === 0;
}
getDirectionAxis() {
if (this.x !== 0) {
return "x";
} else if (this.y !== 0) {
return "y";
} else throw ("error getting direction axis from", this);
}
trimMirror(dirArray) {
let axis = this.getDirectionAxis();
let LN = dirArray.length;
for (let q = LN - 1; q >= 0; q--) {
if (dirArray[q][axis] === this[axis]) dirArray.splice(q, 1);
}
return dirArray;
}
}
class Direction {
constructor(vector, len, weight) {
//this.dir = vector;
this.dir = new Vector(vector.x, vector.y);
this.len = len || 1;
this.weight = weight || 0;
}
isInAt(dirArray) {
for (let q = 0; q < dirArray.length; q++) {
if (
this.dir.x === dirArray[q].dir.x &&
this.dir.y === dirArray[q].dir.y
) {
return q;
}
}
return -1;
}
}
class Point {
constructor(x = 0, y = 0) {
this.x = parseInt(x, 10);
this.y = parseInt(y, 10);
}
static toClass(point) {
return new Grid(point.x, point.y);
}
translate(vector, len = ENGINE.INI.GRIDPIX) {
return new Point(this.x + vector.x * len, this.y + vector.y * len);
}
toViewport() {
//change to offset
this.x = this.x - ENGINE.VIEWPORT.vx;
this.y = this.y - ENGINE.VIEWPORT.vy;
}
add(vector) {
return new Point(this.x + vector.x, this.y + vector.y);
}
}
class Pointer {
constructor(grid, vector) {
this.grid = Grid.toClass(grid);
this.vector = Vector.toClass(vector);
}
}
class Square {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
var UP = new Vector(0, -1);
var DOWN = new Vector(0, 1);
var LEFT = new Vector(-1, 0);
var RIGHT = new Vector(1, 0);
var float64ToInt64Binary = (function() {
//https://stackoverflow.com/questions/9939760/how-do-i-convert-an-integer-to-binary-in-javascript
var flt64 = new Float64Array(1);
var uint16 = new Uint16Array(flt64.buffer);
var MAX_SAFE = Math.pow(2, 53) - 1;
var MAX_INT32 = Math.pow(2, 31);
function uint16ToBinary() {
var bin64 = "";
for (var word = 0; word < 4; word++) {
bin64 = uint16[word].toString(2).padStart(16, 0) + bin64;
}
return bin64;
}
return function float64ToInt64Binary(number) {
if (Math.abs(number) > MAX_SAFE) {
throw new RangeError("Absolute value must be less than 2**53");
}
if (Math.abs(number) <= MAX_INT32) {
return (number >>> 0).toString(2).padStart(64, "0");
}
// little endian byte ordering
flt64[0] = number;
// subtract bias from exponent bits
var exponent = ((uint16[3] & 0x7ff0) >> 4) - 1023 + 1; //+1!!
// encode implicit leading bit of mantissa
uint16[3] |= 0x10;
// clear exponent and sign bit
uint16[3] &= 0x1f;
// only keep integer part of mantissa
var bin64 = uint16ToBinary().substr(11, Math.max(exponent, 0));
return bin64;
};
})();
/////////////////////////
console.log(`Prototype LIB ${LIB.VERSION} loaded!`);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment