You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
678 lines
17 KiB
678 lines
17 KiB
let TOP = 1,
|
|
RIGHT = 2,
|
|
BOTTOM = 3,
|
|
LEFT = 4,
|
|
TOP_RIGHT = 5,
|
|
BOTTOM_RIGHT = 6,
|
|
BOTTOM_LEFT = 7,
|
|
TOP_LEFT = 8;
|
|
|
|
function collisionDetection(obj0, obj1){
|
|
|
|
let sp = strokePadding;
|
|
if (sp == null) sp = 0;
|
|
|
|
if (obj0.isEllipse && obj1.isRectangle){
|
|
|
|
//Ball
|
|
let b = obj0;
|
|
|
|
//Rectangle
|
|
let r = obj1;
|
|
|
|
for (let i = 0; i < TWO_PI; i += PI / 32){
|
|
|
|
/* Check every borderpoint of the ball beginning
|
|
at the top in clock direction up to top again */
|
|
|
|
// Ball Center X
|
|
let bcx = b.x;
|
|
|
|
// Ball Center Y
|
|
let bcy = b.y;
|
|
|
|
// Ball Border X
|
|
let bbx = b.x + sin(i) * b.r;
|
|
|
|
// Ball Border Y inverted because Y = 0 is the TOP of the screen
|
|
let bby = b.y - cos(i) * b.r;
|
|
|
|
// Rectangle Width
|
|
let rW = r.width + 2 * sp;
|
|
|
|
// Rectangle Height
|
|
let rH = r.height + 2 * sp;
|
|
|
|
// Rectangle Border X
|
|
let rX = r.x - sp;
|
|
|
|
// Rectangle Border Y
|
|
let rY = r.y - sp;
|
|
|
|
// Objects touch
|
|
if (bbx > rX && bbx < rX + rW
|
|
&& bby > rY && bby < rY + rH){
|
|
|
|
// STRAIGHT FACES //
|
|
|
|
//Top/Bottom touch
|
|
if (bcx > rX && bcx < rX + rW){
|
|
|
|
//Top touch
|
|
if (b.v.y > 0) return {isTouching: true, location: TOP};
|
|
|
|
//Bottom touch
|
|
if (b.v.y < 0) return {isTouching: true, location: BOTTOM};
|
|
}
|
|
|
|
//Left/Right touch
|
|
if (bcy > rY && bcy < rY + rH){
|
|
|
|
//Left touch
|
|
if (b.v.x > 0) return {isTouching: true, location: LEFT};
|
|
|
|
//Right touch
|
|
if (b.v.x < 0) return {isTouching: true, location: RIGHT};
|
|
|
|
}
|
|
|
|
// CORNERS //
|
|
|
|
// BOTTOM Left/Right
|
|
if (i > 0 && i <= PI / 2) return {isTouching: true, location: BOTTOM_LEFT};
|
|
|
|
//LEFT Bottom/Top
|
|
if (i > PI / 2 && i <= PI) return {isTouching: true, location: TOP_LEFT};
|
|
|
|
//TOP Left/Right
|
|
if (i > PI && i <= PI + PI / 2) return {isTouching: true, location: TOP_RIGHT};
|
|
|
|
//RIGHT Bottom/Top
|
|
if (i > PI + PI / 2 && i <= TWO_PI) return {isTouching: true, location: BOTTOM_RIGHT};
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (obj0.isEllipse && obj1.isEllipse){
|
|
|
|
//Ball 1
|
|
let b1 = obj0;
|
|
|
|
//Ball 2
|
|
let b2 = obj1;
|
|
|
|
//Balls are close to each other
|
|
if (b1.x + b1.r > b2.x - b2.r
|
|
&& b1.x - b1.r < b2.x + b2.r
|
|
&& b1.y + b1.r > b2.y - b2.r
|
|
&& b1.y - b1.r < b2.y + b2.r){
|
|
|
|
let distance = sqrt(pow(b1.x - b2.x, 2) + pow(b1.y - b2.y, 2));
|
|
|
|
if (distance < b1.r + b2.r) return {isTouching: true};
|
|
}
|
|
}
|
|
return {isTouching: false, location: 0};
|
|
}
|
|
|
|
function performCollision(obj0, obj1, collision){
|
|
if (obj0.isEllipse){
|
|
|
|
let ball = obj0;
|
|
|
|
//Ball collides with frameborder
|
|
if (obj1.isFrameborder){
|
|
switch (collision.location){
|
|
case BOTTOM:
|
|
ball.v.y *= -1;
|
|
break;
|
|
case LEFT:
|
|
case RIGHT:
|
|
ball.v.x *= -1;
|
|
break;
|
|
}
|
|
if (testMode && collision.location == TOP) ball.v.y *= -1;
|
|
ball.move();
|
|
}
|
|
|
|
//Ball collides with any brick
|
|
if (obj1.isBrick){
|
|
let cornerX, cornerY;
|
|
switch (collision.location){
|
|
case TOP:
|
|
case BOTTOM:
|
|
ball.v.y *= -1;
|
|
ball.move();
|
|
return;
|
|
case LEFT:
|
|
case RIGHT:
|
|
ball.v.x *= -1;
|
|
ball.move();
|
|
return;
|
|
case TOP_LEFT:
|
|
cornerX = obj1.x;
|
|
cornerY = obj1.y;
|
|
break;
|
|
case TOP_RIGHT:
|
|
cornerX = obj1.x + obj1.width;
|
|
cornerY = obj1.y;
|
|
break;
|
|
case BOTTOM_LEFT:
|
|
cornerX = obj1.x;
|
|
cornerY = obj1.y + obj1.height;
|
|
break;
|
|
case BOTTOM_RIGHT:
|
|
cornerX = obj1.x + obj1.width;
|
|
cornerY = obj1.y + obj1.height;
|
|
break;
|
|
}
|
|
|
|
let nx = ball.x - cornerX;
|
|
let ny = ball.y - cornerY;
|
|
let length = sqrt(nx * nx + ny * ny);
|
|
nx /= length;
|
|
ny /= length;
|
|
|
|
let projection = ball.v.x * nx + ball.v.y * ny;
|
|
ball.v.x = ball.v.x - 2 * projection * nx;
|
|
ball.v.y = ball.v.y - 2 * projection * ny;
|
|
|
|
ball.move();
|
|
|
|
}
|
|
|
|
//Ball collides with paddleboard
|
|
if (obj1.isPaddle){
|
|
let cornerX, cornerY;
|
|
switch (collision.location){
|
|
case TOP:
|
|
case TOP_LEFT:
|
|
case TOP_RIGHT:
|
|
ball.v.x = ball.calcVelocityX(obj1, ball.v.x);
|
|
ball.v.y = -ball.calcVelocityY();
|
|
ball.move();
|
|
return;
|
|
case LEFT:
|
|
case RIGHT:
|
|
ball.v.x *= -1;
|
|
ball.move();
|
|
return;
|
|
case BOTTOM_LEFT:
|
|
cornerX = obj1.x;
|
|
cornerY = obj1.y + obj1.height;
|
|
break;
|
|
case BOTTOM_RIGHT:
|
|
cornerX = obj1.x + obj1.width;
|
|
cornerY = obj1.y + obj1.height;
|
|
break;
|
|
}
|
|
let nx = ball.x - cornerX;
|
|
let ny = ball.y - cornerY;
|
|
let length = sqrt(nx * nx + ny * ny);
|
|
nx /= length;
|
|
ny /= length;
|
|
|
|
let projection = ball.v.x * nx + ball.v.y * ny;
|
|
ball.v.x = ball.v.x - 2 * projection * nx;
|
|
ball.v.y = ball.v.y - 2 * projection * ny;
|
|
|
|
ball.move();
|
|
}
|
|
|
|
//Ball collides with other ball
|
|
if (obj1.isEllipse){
|
|
|
|
//Ball 1
|
|
let b1 = obj0;
|
|
|
|
//Ball 2
|
|
let b2 = obj1;
|
|
|
|
//Set mass equal to radius of each ball
|
|
b1.mass = b1.r;
|
|
b2.mass = b2.r;
|
|
|
|
//Colliding angle of ball 1 to ball 2 using arc tan of both x and y differences
|
|
let collisionAngle = atan2((b2.y - b1.y), (b2.x - b1.x));
|
|
|
|
//Converting directions of velocity vector of balls into angles
|
|
let d1 = atan2(b1.v.y, b1.v.x);
|
|
let d2 = atan2(b2.v.y, b2.v.x);
|
|
|
|
//Ignoring mass effects new velocites are simply magnitude multiplied with value of angle differences
|
|
let newXspeed1 = b1.v.mag * cos(d1 - collisionAngle);
|
|
let newYspeed1 = b1.v.mag * sin(d1 - collisionAngle);
|
|
let newXspeed2 = b2.v.mag * cos(d2 - collisionAngle);
|
|
let newYspeed2 = b2.v.mag * sin(d2 - collisionAngle);
|
|
|
|
//According to the principle of linear momentum, kinetic energy stays the same after collision, so velocities are now related to masses
|
|
let finalXspeed1 = ((b1.mass - b2.mass) * newXspeed1 + b2.mass * 2 * newXspeed2) / (b1.mass + b2.mass);
|
|
let finalYspeed1 = newYspeed1;
|
|
let finalXspeed2 = (b1.mass * 2 * newXspeed1 + (b2.mass - b1.mass) * newXspeed2) / (b1.mass + b2.mass);
|
|
let finalYspeed2 = newYspeed2;
|
|
|
|
//Values of collisionAngle
|
|
let cosAngle = cos(collisionAngle);
|
|
let sinAngle = sin(collisionAngle);
|
|
|
|
//To also keep velocites relative to pure collisionAngle, subtract sin*x from cos*x and add sin*y to cos*y because coordSystem has y = 0 on the top
|
|
let u1x = cosAngle * finalXspeed1 - sinAngle * finalYspeed1;
|
|
let u1y = sinAngle * finalXspeed1 + cosAngle * finalYspeed1;
|
|
let u2x = cosAngle * finalXspeed2 - sinAngle * finalYspeed2;
|
|
let u2y = sinAngle * finalXspeed2 + cosAngle * finalYspeed2;
|
|
|
|
//Set new velocities to both balls
|
|
b1.v.x = u1x;
|
|
b1.v.y = u1y;
|
|
b2.v.x = u2x;
|
|
b2.v.y = u2y;
|
|
|
|
//Update magnitude
|
|
b1.v.mag = sqrt(pow(b1.v.x, 2) + pow(b1.v.y, 2));
|
|
b2.v.mag = sqrt(pow(b2.v.x, 2) + pow(b2.v.y, 2));
|
|
|
|
|
|
//Move balls one vx/vy forward to avoid double inverting collision detection
|
|
b1.x += b1.v.x;
|
|
b1.y += b1.v.y;
|
|
b2.x += b2.v.x;
|
|
b2.y += b2.v.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function toTimeString(time, hoursWanted){
|
|
|
|
time = floor(time / 10);
|
|
|
|
let hs = String(floor(time % 100));
|
|
let fs = String(floor((time / 100) % 60));
|
|
|
|
if (hoursWanted){
|
|
let min = String(floor(((time / 100) / 60) % 60));
|
|
let hr = String(floor(((time / 100) / 60) / 60));
|
|
|
|
if (hs.length < 2) hs = "0" + hs;
|
|
if (fs.length < 2) fs = "0" + fs;
|
|
if (min.length < 2) min = "0" + min;
|
|
if (hr.length < 2) hr = "0" + hr;
|
|
|
|
let timeString = hr + ":" + min + ":" + fs + ":" + hs;
|
|
} else {
|
|
let min = String(floor(((time / 100) / 60) % 60));
|
|
|
|
if (hs.length < 2) hs = "0" + hs;
|
|
if (fs.length < 2) fs = "0" + fs;
|
|
if (min.length < 2) min = "0" + min;
|
|
|
|
let timeString = min + ":" + fs + ":" + hs;
|
|
}
|
|
|
|
|
|
|
|
return timeString;
|
|
}
|
|
|
|
|
|
function setCookie(name, value, years){
|
|
let expires = "";
|
|
if (years){
|
|
let date = new Date();
|
|
date.setTime(date.getTime() + (years * 365 * 24 * 60 * 60 * 1000));
|
|
expires = "; expires=" + date.toUTCString();
|
|
}
|
|
document.cookie = name + "=" + value + expires + "; path=/";
|
|
}
|
|
|
|
function getCookie(name){
|
|
let nameEQ = name + "=";
|
|
let ca = document.cookie.split(';');
|
|
for (let i = 0; i < ca.length; i++){
|
|
let c = ca[i];
|
|
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
|
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function deleteCookies(){
|
|
for (let i = 0; i < arguments.length; i++) setCookie(arguments[i], "", -1);
|
|
}
|
|
|
|
function deleteAllCookies(){
|
|
let cookies = document.cookie.split(";");
|
|
for (let i = 0; i < cookies.length; i++) deleteCookies(cookies[i].split("=")[0]);
|
|
}
|
|
|
|
Array.prototype.shuffle = function(){
|
|
let currentIndex = this.length, temporaryValue, randomIndex;
|
|
while (0 != currentIndex){
|
|
randomIndex = floor(random() * currentIndex);
|
|
currentIndex -= 1;
|
|
temporaryValue = this[currentIndex];
|
|
this[currentIndex] = this[randomIndex];
|
|
this[randomIndex] = temporaryValue;
|
|
}
|
|
}
|
|
|
|
Array.prototype.clone = function(){
|
|
return this.slice(0);
|
|
};
|
|
|
|
//Divides big Array into big multidimensional Array
|
|
Array.prototype.partitiate = function(dimensions){
|
|
if (dimensions == 0) return this;
|
|
let parts = [];
|
|
while(this.length) parts.push(this.splice(0, round(pow(this.length, 1 / (1 + 1 / dimensions)))).partitiate(dimensions - 1));
|
|
return parts;
|
|
}
|
|
|
|
String.prototype.isValidHEX = function(){
|
|
return /(^#[0-9A-Fa-f]{6}$)|(^#[0-9A-Fa-f]{3}$)/i.test(this);
|
|
}
|
|
|
|
String.prototype.capitalize = function(){
|
|
return this.charAt(0).toUpperCase() + this.slice(1);
|
|
}
|
|
|
|
function debugInformation(){
|
|
let x = 0,
|
|
y = 0;
|
|
textSize(12);
|
|
textStyle(NORMAL);
|
|
stroke(255);
|
|
strokeWeight(1);
|
|
fill(255);
|
|
text("FPS : " + round(frameRate()), 10 + x, 10 + textAscent("FPS : ") + y);
|
|
text("MouseX : " + round(mouseX + x), 10 + x, 10 + textAscent("FPS : ") + 10 + textAscent("MouseX : ") + y);
|
|
text("MouseY : " + round(-mouseY - y), 10 + x, 10 + textAscent("FPS : ") + 10 + textAscent("MouseX : ") + 10 + textAscent("MouseY : ") + y);
|
|
}
|
|
|
|
|
|
|
|
function ColorPicker(editor) {
|
|
this.movingObject = "";
|
|
|
|
this.updateFromGraphical = function(){
|
|
this.h = (1 - $("#hue_picker").position().top / $("#hue").height()) * 360;
|
|
this.s = ($("#sb_picker").position().left + 8) / $("#saturation").width() * 100;
|
|
this.v = (1 - ($("#sb_picker").position().top + 8) / $("#value").height()) * 100;
|
|
|
|
this.r = HSVtoRGB(this.h, this.s, this.v).r;
|
|
this.g = HSVtoRGB(this.h, this.s, this.v).g;
|
|
this.b = HSVtoRGB(this.h, this.s, this.v).b;
|
|
|
|
this.hex = RGBtoHEX(this.r, this.g, this.b);
|
|
|
|
this.updateInterface();
|
|
}
|
|
|
|
this.updateFromHSV = function(){
|
|
this.h = $($("#color_picker_hsv input")[0]).val();
|
|
this.s = $($("#color_picker_hsv input")[1]).val();
|
|
this.v = $($("#color_picker_hsv input")[2]).val();
|
|
|
|
this.r = HSVtoRGB(this.h, this.s, this.v).r;
|
|
this.g = HSVtoRGB(this.h, this.s, this.v).g;
|
|
this.b = HSVtoRGB(this.h, this.s, this.v).b;
|
|
|
|
this.hex = RGBtoHEX(this.r, this.g, this.b);
|
|
|
|
this.updateFromHEX(null, true);
|
|
|
|
this.updateInterface();
|
|
}
|
|
|
|
this.updateFromRGB = function(){
|
|
this.r = $($("#color_picker_rgb input")[0]).val();
|
|
this.g = $($("#color_picker_rgb input")[1]).val();
|
|
this.b = $($("#color_picker_rgb input")[2]).val();
|
|
|
|
this.h = RGBtoHSV(this.r, this.g, this.b).h;
|
|
this.s = RGBtoHSV(this.r, this.g, this.b).s;
|
|
this.v = RGBtoHSV(this.r, this.g, this.b).v;
|
|
|
|
this.hex = RGBtoHEX(this.r, this.g, this.b);
|
|
|
|
this.updateFromHEX(null, true);
|
|
|
|
this.updateInterface();
|
|
}
|
|
|
|
this.updateFromHEX = function(input, otf){
|
|
if (!otf){ //Not on the fly
|
|
if ($(input).val().isValidHEX()) this.hex = $(input).val();
|
|
else {
|
|
alert("Error!");
|
|
return;
|
|
}
|
|
}
|
|
|
|
this.r = HEXtoRGB(this.hex).r;
|
|
this.g = HEXtoRGB(this.hex).g;
|
|
this.b = HEXtoRGB(this.hex).b;
|
|
|
|
this.h = RGBtoHSV(this.r, this.g, this.b).h;
|
|
this.s = RGBtoHSV(this.r, this.g, this.b).s;
|
|
this.v = RGBtoHSV(this.r, this.g, this.b).v;
|
|
|
|
this.updateInterface();
|
|
}
|
|
|
|
this.updateInterface = function(){
|
|
|
|
let r = $($("#color_picker_rgb input")[0]),
|
|
g = $($("#color_picker_rgb input")[1]),
|
|
b = $($("#color_picker_rgb input")[2]),
|
|
h = $($("#color_picker_hsv input")[0]),
|
|
s = $($("#color_picker_hsv input")[1]),
|
|
v = $($("#color_picker_hsv input")[2]),
|
|
hex = $("#color_picker_hex"),
|
|
bgColor;
|
|
|
|
r.val(round(this.r));
|
|
g.val(round(this.g));
|
|
b.val(round(this.b));
|
|
h.val(round(this.h));
|
|
s.val(round(this.s));
|
|
v.val(round(this.v));
|
|
bgColor = color(this.r, 0, 0);
|
|
r.css({
|
|
"background-color": bgColor.toString(),
|
|
"color": fontColor(bgColor)
|
|
});
|
|
bgColor = color(0, this.g, 0);
|
|
g.css({
|
|
"background-color": bgColor.toString(),
|
|
"color": fontColor(bgColor)
|
|
});
|
|
bgColor = color(0, 0, this.b);
|
|
b.css({
|
|
"background-color": bgColor.toString(),
|
|
"color": fontColor(bgColor)
|
|
});
|
|
colorMode(HSL);
|
|
bgColor = color(this.h, 100, 50);
|
|
h.css({
|
|
"background-color": bgColor.toString(),
|
|
"color": fontColor(bgColor)
|
|
});
|
|
bgColor = color(this.h, this.s, 100 - this.s / 2);
|
|
s.css({
|
|
"background-color": bgColor.toString(),
|
|
"color": fontColor(bgColor)
|
|
});
|
|
bgColor = color(this.h, 100, this.v / 2);
|
|
v.css({
|
|
"background-color": bgColor.toString(),
|
|
"color": fontColor(bgColor)
|
|
});
|
|
colorMode(RGB);
|
|
hex.val(this.hex);
|
|
hex.css({
|
|
"background-color": this.hex,
|
|
"color": fontColor(color(this.hex))
|
|
});
|
|
|
|
|
|
let sRGB = HSVtoRGB(this.h, 100, 100);
|
|
let saturationBackground = "linear-gradient(to right, #FFF 0%, rgb("
|
|
+ sRGB.r + ","
|
|
+ sRGB.g + ","
|
|
+ sRGB.b + ") 100%)";
|
|
$("#hue_picker").css("top", (1 - this.h / 360) * $("#hue").height());
|
|
$("#sb_picker").css({
|
|
"left": this.s / 100 * $("#saturation").width() - 8,
|
|
"top": (1 - this.v / 100) * $("#value").height() - 8
|
|
});
|
|
$("#saturation").css("background", saturationBackground);
|
|
|
|
}
|
|
|
|
this.mousePressed = function(){
|
|
let x = winMouseX - $("#saturation").offset().left;
|
|
let y = winMouseY - $("#value").offset().top;
|
|
if (x > 0 && x < $("#saturation").width() && y > 0 && y < $("#value").height()){
|
|
this.movingObject = "sb";
|
|
}
|
|
if (x > $("#saturation").width() + 6 && x < $("#saturation").width() + 6 + $("#hue").width() && y > 0 && y < $("#hue").height()){
|
|
this.movingObject = "hue";
|
|
}
|
|
this.mouseDragged();
|
|
}
|
|
|
|
this.mouseDragged = function(){
|
|
if (this.movingObject == "hue"){
|
|
let objH = $("#hue");
|
|
let picker = $("#hue_picker");
|
|
let h = winMouseY - objH.offset().top;
|
|
if (h > 0 && h < objH.height()){
|
|
picker.css("top", h - 1);
|
|
} else if (h > objH.height()){
|
|
picker.css("top", objH.height() - 1);
|
|
} else if (h < 0){
|
|
picker.css("top", -1);
|
|
}
|
|
}
|
|
|
|
if (this.movingObject == "sb"){
|
|
let objS = $("#saturation");
|
|
let objV = $("#value");
|
|
let picker = $("#sb_picker");
|
|
let s = winMouseX - objS.offset().left;
|
|
let v = winMouseY - objV.offset().top;
|
|
if (s > 0 && s < objS.width()){
|
|
picker.css("left", s - 8);
|
|
} else if (s < 0){
|
|
picker.css("left", -8);
|
|
} else if (s < objS.width()){
|
|
picker.css("left", objS.width() - 8);
|
|
}
|
|
if (v > 0 && v < objV.height()){
|
|
picker.css("top", v - 8);
|
|
} else if (v < 0){
|
|
picker.css("top", -8);
|
|
} else if (v > objV.height()){
|
|
picker.css("top", objV.height() - 8);
|
|
}
|
|
}
|
|
|
|
this.updateFromGraphical();
|
|
}
|
|
|
|
this.mouseReleased = function(){
|
|
this.movingObject = "";
|
|
}
|
|
|
|
this.getColor = function(){
|
|
return this.hex;
|
|
}
|
|
}
|
|
|
|
function fontColor(color){
|
|
//https://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
|
|
let o = (red(color) * 299 + green(color) * 587 + blue(color) * 114) / 1000;
|
|
return (o > 125) ? "#000" : "#CCC";
|
|
}
|
|
|
|
//www.stackoverflow.com -->
|
|
function RGBtoHEX(r, g, b) {
|
|
let rgb = b | (g << 8) | (r << 16);
|
|
return '#' + (0x1000000 + rgb).toString(16).slice(1);
|
|
}
|
|
|
|
function HEXtoRGB(hex) {
|
|
let shorthandRegex = /^#?([a-fA-F\d])([a-fA-F\d])([a-fA-F\d])$/i;
|
|
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
|
|
return r + r + g + g + b + b;
|
|
});
|
|
let result = /^#?([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})$/i.exec(hex);
|
|
return result ? {
|
|
r: parseInt(result[1], 16),
|
|
g: parseInt(result[2], 16),
|
|
b: parseInt(result[3], 16)
|
|
} : null;
|
|
}
|
|
|
|
function HSVtoRGB(h, s, v) {
|
|
let r, g, b, i, f, p, q, t;
|
|
if (arguments.length === 1) {
|
|
s = h.s, v = h.v, h = h.h;
|
|
}
|
|
h /= 360;
|
|
s /= 100;
|
|
v /= 100;
|
|
i = Math.floor(h * 6);
|
|
f = h * 6 - i;
|
|
p = v * (1 - s);
|
|
q = v * (1 - f * s);
|
|
t = v * (1 - (1 - f) * s);
|
|
switch (i % 6) {
|
|
case 0: r = v, g = t, b = p; break;
|
|
case 1: r = q, g = v, b = p; break;
|
|
case 2: r = p, g = v, b = t; break;
|
|
case 3: r = p, g = q, b = v; break;
|
|
case 4: r = t, g = p, b = v; break;
|
|
case 5: r = v, g = p, b = q; break;
|
|
}
|
|
return {
|
|
r: r * 255,
|
|
g: g * 255,
|
|
b: b * 255
|
|
};
|
|
}
|
|
|
|
function RGBtoHSV(r, g, b) {
|
|
if (arguments.length === 1) {
|
|
g = r.g, b = r.b, r = r.r;
|
|
}
|
|
let max = Math.max(r, g, b), min = Math.min(r, g, b),
|
|
d = max - min,
|
|
h,
|
|
s = (max === 0 ? 0 : d / max),
|
|
v = max / 255;
|
|
|
|
switch (max) {
|
|
case min: h = 0; break;
|
|
case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;
|
|
case g: h = (b - r) + d * 2; h /= 6 * d; break;
|
|
case b: h = (r - g) + d * 4; h /= 6 * d; break;
|
|
}
|
|
|
|
return {
|
|
h: h * 360,
|
|
s: s * 100,
|
|
v: v * 100
|
|
};
|
|
}
|
|
|
|
|
|
|
|
|
|
function ranBool(chance){
|
|
if (!chance) chance = 2;
|
|
return Math.floor(Math.random() * chance + 1) == chance ? true : false;
|
|
} |