blue.js/libs/bluepixle.js

333 lines
11 KiB
JavaScript

// bluepixle.js
// This library is to help make using canvas tags easier
// requires bluemath.js
class shape {
constructor(type,coordinates,dimentions,rotation,fColor,bColor,bStyle,extraObject) {
this.type = "string" == typeof type ? (["rect","elipse","image"].includes(type) ? type : "rect") : "rect";
this.coordinates = coordinates instanceof vector ? coordinates : new vector([0,0]);
this.dimentions = dimentions instanceof vector ? dimentions : new vector([1,1]);
this.rotation = rotation instanceof vector ? rotation : new vector([0,1]);
this.fColor = "string" == typeof fColor ? fColor : undefined;
this.bColor = "string" == typeof bColor ? bColor : undefined;
this.bStyle = "number" == typeof bStyle ? bStyle : undefined;
this.extraObject = "object" == typeof extraObject ? extraObject : {};
if ("image" == this.type) {
this.imageData =
this.extraObject.imageData instanceof ImageData ?
this.extraObject.imageData :
new ImageData(
new Uint8ClampedArray([
255,0,0,255,
0,0,0,0,
255,0,0,255,
0,0,0,0,
255,0,0,255,
0,0,0,0,
255,0,0,255,
0,0,0,0,
255,0,0,255
]),3,3);
this.image = createImageBitmap(this.imageData);
}
}
render(ctx,position,rotation) {
// Save current defaults
var local = {};
local.fillStyle = "string" == typeof ctx.fillStyle ? ctx.fillStyle : undefined;
local.strokeStyle = "string" == ctx.strokeStyle ? ctx.strokeStyle : undefined;
local.lineWidth = "number" == ctx.lineWidth ? ctx.lineWidth : undefined;
local.imageSmoothingEnabled = ctx.imageSmoothingEnabled;
// calculate origin and rotation
var origin = this.coordinates.add(position instanceof vector ? position : new vector([0,0]));
var origRot = this.rotation.getRadAngle() + (rotation instanceof vector ? rotation : new vector([0,1])).getRadAngle();
var center = origin.add(this.dimentions.mag(0.5));
// Rotate
ctx.translate(center.d[0],center.d[1]);
ctx.rotate(origRot);
ctx.translate(-center.d[0],-center.d[1]);
// Draw
ctx.fillStyle = this.fcolor;
ctx.strokeStyle = this.bColor;
ctx.lineWidth = this.bStyle;
if("rect" == this.type) {
ctx.fillRect(origin.d[0],origin.d[1],this.dimentions.d[0],this.dimentions.d[1]);
ctx.strokeRect(origin.d[0],origin.d[1],this.dimentions.d[0],this.dimentions.d[1]);
} else if ("elipse" == this.type) {
ctx.beginPath();
ctx.ellipse(center.d[0],center.d[1],dimentions.d[0]/2,dimentions.d[1]/2,0,0,360);
ctx.stroke();
ctx.fill();
} else if ("image" == this.type) {
this.image.then(function (image) {
ctx.imageSmoothingEnabled = false;
ctx.drawImage(image,origin.d[0],origin.d[0],this.dimentions.d[0],this.dimentions.d[1]);
});
}
// restore context defaults
ctx.setTransform(1,0,0,1,0,0);
ctx.fillStyle = local.fillStyle;
ctx.strokeStyle = local.strokeStyle;
ctx.lineWidth = local.lineWidth;
ctx.imageSmoothingEnabled = local.imageSmoothingEnabled;
}
grow (amp) {
this.dimentions = this.dimentions.amp(amp);
}
}
class container {
constructor(coordinates,dimentions,rotation) {
this.coordinates = coordinates instanceof vector ? coordinates : new vector([0,0]);
this.size = dimentions instanceof vector ? dimentions : new vector([1,1]);
this.rotation = rotation instanceof vector ? rotation : new vector([0,1]);
this.movementVector = new vector([0,0]);
this.shapes = [];
this.containers = [];
}
addShape(myShape) {
if (myShape instanceof shape) {
this.shapes.push(myShape);
} else {
throw new TypeError("addShape Method must be given a shape object");
}
}
addContainer(myContainer) {
if (myContainer instanceof container) {
this.containers.push(container);
} else {
throw new TypeError("addContainer Method must be given a container object");
}
}
move(delta) {
delta = !isNaN(delta) ? delta : 0;
this.coordinates = this.coordinates.add(this.movementVector.mag(delta));
}
renderContainer(ctx,position,rotation) {
position = position instanceof vector ? position : new vector([0,0]);
rotation = rotation instanceof vector ? rotation : new vector([0,1]);
var refPos = this.coordinates.add(position);
var refRot = this.rotation.add(rotation);
if (this.shapes.length) {
this.shapes.forEach(shape => shape.render(ctx,refPos,refRot));
}
if (this.containers.length) {
this.containers.forEach(container => container.renderContainer(ctx,refPos,refRot));
}
}
grow(amp) {
amp = !isNaN(amp) ? amp : 1;
this.position.mag(amp);
if (this.shapes.length) {
this.shapes.forEach(shape => shape.grow(amp));
}
if (this.containers.length) {
this.containers.forEach( container => container.grow(amp));
}
}
bounce(surface) {
this.movementVector = this.movementVector.reflect(surface);
}
overlap(otherContainer, callbackFunction) {
///////////////////////////////// work starts here
this.
}
}
function collide(objectA,objectB,callBackFunction) {
var ASpeed = Math.abs(objectA.speed);
var BSpeed = Math.abs(objectB.speed);
var simAX = ASpeed <= BSpeed ? objectA.x : objectB.x;
var simAY = ASpeed <= BSpeed ? objectA.y : objectB.y;
var simBX = ASpeed <= BSpeed ? objectB.x : objectA.x;
var simBY = ASpeed <= BSpeed ? objectB.y : objectA.y;
var simADir = ASpeed <= BSpeed ? objectA.direction : objectB.direction;
var simBDir = ASpeed <= BSpeed ? objectB.direction : objectA.direction;
var simASpeed = ASpeed <= BSpeed ? objectA.speed : objectB.speed;
var simBSpeed = ASpeed <= BSpeed ? objectB.speed : objectA.speed;
var simAheight = ASpeed <= BSpeed ? objectA.sizeX : objectB.sizeX;
var simBheight = ASpeed <= BSpeed ? objectB.sizeX : objectA.sizeX;
var simAwidth = ASpeed <= BSpeed ? objectA.sizeY : objectB.sizeY;
var simBwidth = ASpeed <= BSpeed ? objectB.sizeY : objectA.sizeY;
var thetaA = deg2rad(simADir);
var deltaAX = Math.cos(thetaA)*simASpeed;
var deltaAY = Math.sin(thetaA)*simASpeed;
var thetaB = deg2rad(simBDir);
var deltaBX = Math.cos(thetaB)*simBSpeed;
var deltaBY = Math.sin(thetaB)*simBSpeed;
var fastest = Math.max(Math.abs(objectA.speed),Math.abs(objectB.speed));
for (var t = 0; t <= fastest; t++) {
var tFraction = t/(fastest+1);
var Atop = simAY+(tFraction * deltaAY);
var Abottom = simAY+(tFraction * deltaAY)+simAheight;
var Aleft = simAX+(tFraction * deltaAX);
var Aright = simAX+(tFraction * deltaAX)+simAwidth;
var Btop = simBY+(tFraction * deltaBY);
var Bbottom = simBY+(tFraction * deltaBY)+simBheight;
var Bleft = simBX+(tFraction * deltaBX);
var Bright = simBX+(tFraction * deltaBX)+simBwidth;
if (
pointInside(Aleft,Atop,Btop,Bright,Bbottom,Bleft) |
pointInside(Aright,Atop,Btop,Bright,Bbottom,Bleft) |
pointInside(Aleft,Abottom,Btop,Bright,Bbottom,Bleft) |
pointInside(Aright,Abottom,Btop,Bright,Bbottom,Bleft) |
pointInside(Bleft,Btop,Atop,Aright,Abottom,Aleft) |
pointInside(Bright,Btop,Atop,Aright,Abottom,Aleft) |
pointInside(Bleft,Bbottom,Atop,Aright,Abottom,Aleft) |
pointInside(Bright,Bbottom,Atop,Aright,Abottom,Aleft)
){
return callBackFunction(objectA,objectB,t);
}
}
return false;
}
function chase (source,target,max,minDis,acc) {
acc /= 100;
var sourceCenterX = source.x + (source.sizeX/2);
var sourceCenterY = source.y + (source.sizeY/2);
var targetCenterX = target.x + (target.sizeX/2);
var targetCenterY = target.y + (target.sizeY/2);
var deltaX = targetCenterX - sourceCenterX;
var deltaY = targetCenterY - sourceCenterY;
var theta = Math.atan2(deltaY,deltaX);
var dis = Math.sqrt(Math.pow(Math.abs(deltaX),2)+Math.pow(Math.abs(deltaY),2));
var dir = theta;
if (dis > minDis) {
dis = dis <= max ? dis : max;
source.direction = rad2deg(dir);
source.speed = (dis-minDis)*acc;
source.move(source.direction,source.speed);
}
}
function drawPixel (ctx, x, y, r, g, b, a) {
// Always validate your input
if (false == ctx instanceof CanvasRenderingContext2D) {
return new TypeError("ctx must be a 2D rendering context for canvas.");
}
x = x <= ctx.canvas.width ? x : ctx.canvas.width;
y = y <= ctx.canvas.height ? y : ctx.canvas.height;
r = r <= 255 ? r : 255;
r = r >= 0 ? r : 0;
g = g <= 255 ? g : 255;
g = g >= 0 ? g : 0;
b = b <= 255 ? b : 255;
b = b >= 0 ? b : 0;
a = a <= 255 ? a : 255;
a = a >= 0 ? a : 0;
// Do the thing
ctx.putImageData(new ImageData(new Uint8ClampedArray([r,g,b,a]),1,1),x,y);
}
class frameBuffer {
constructor(ctx, height, width) {
this.ctx = ctx;
this.height = height;
this.width = width;
this.containerArray = [];
}
addContainer(containerObject) { //might change this to auto create containers.
if (containerObject instanceof container) {
var index = this.containerArray.push(containerObject);
return this.containerArray[ index - 1];
} else {
throw new TypeError("addContainer Method must be given a container object");
}
}
pushFrame() {
var ctx = this.ctx;
ctx.clearRect(0,0,this.width,this.height);
this.containerArray.forEach(
function (container) { container.renderContainer(ctx,0,0); });
}
}
class starfield {
constructor (buffer,boundWidth,boundHeight,centerX,centerY,starCount,starLife,starSpeed) {
//Validate things
this.centerX = centerX;
this.centerY = centerY;
this.starLife = starLife;
this.starSpeed = starSpeed;
//Math the things
this.topBound = centerY - (boundHeight/2);
this.bottomBound = centerY + (boundHeight/2);
this.leftBound = centerX - (boundWidth/2);
this.rightBound = centerX + (boundWidth/2);
this.stars = [];
this.container = buffer.addContainer(
new container(this.centerX,this.centerY,0,0,0));
this.container.nestContainer();
for (var count = 1; count <= starCount; count++) {
var star = this.container.addShape(
new shape(
"rect",
((Math.random()*boundWidth)-(boundWidth/2)),
((Math.random()*boundHeight)-(boundHeight/2)),
1,1,
"#ffffff",
"#ffffff",
1));
this.stars.push({
"container":star,
"life":this.starLife,
"speed":this.starSpeed});
}
}
forward() {
var me = this;
this.stars.forEach(function (star) {
if (
(star.life > 0) &
(star.container.shape.x > me.leftBound - me.centerX) &
(star.container.shape.x < me.rightBound - me.centerX) &
(star.container.shape.y > me.topBound - me.centerY) &
(star.container.shape.y < me.bottomBound - me.centerY)) {
var xOffset = star.container.shape.x;
var yOffset = star.container.shape.y;
star.life--;
var c = 255*((me.starLife-star.life)/me.starLife)*4;
star.container.grow(5/me.starLife);
star.container.shape.fColor = "rgb("+c+","+c+","+c+")";
star.container.shape.bColor = "rgb("+c+","+c+","+c+")";
star.speed+=me.starSpeed;
star.container.shape.x +=
star.speed*((xOffset/me.centerX)*0.5);
star.container.shape.y +=
star.speed*((yOffset/me.centerY)*0.5);
} else {
star.container.x = 0;
star.container.y = 0;
star.life = me.starLife;
star.speed = me.starSpeed;
star.container.shape.sizeX = 1;
star.container.shape.sizeY = 1;
star.container.shape.fColor = "rgb(0,0,0)";
star.container.shape.bColor = "rgb(0,0,0)";
star.container.shape.x =
(Math.random()*(me.rightBound-me.leftBound))
-(me.centerX);
star.container.shape.y =
(Math.random()*(me.bottomBound-me.topBound))
-(me.centerY);
}
});
}
}