2020-08-20 15:58:18 -06:00
|
|
|
// bluepixle.js
|
|
|
|
// This library is to help make using canvas tags easier
|
2022-02-08 12:37:06 -07:00
|
|
|
// requires bluemath.js
|
2020-08-20 15:58:18 -06:00
|
|
|
|
2022-02-08 17:10:24 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-08-20 15:58:18 -06:00
|
|
|
}
|
|
|
|
|
2022-02-08 17:10:24 -07:00
|
|
|
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
|
2022-02-10 08:51:20 -07:00
|
|
|
ctx.translate(center.d[0],center.d[1]);
|
|
|
|
ctx.rotate(-origRot);
|
|
|
|
ctx.translate(-center.d[0],-center.d[1]);
|
|
|
|
|
2022-02-08 17:10:24 -07:00
|
|
|
ctx.fillStyle = local.fillStyle;
|
|
|
|
ctx.strokeStyle = local.strokeStyle;
|
|
|
|
ctx.lineWidth = local.lineWidth;
|
|
|
|
ctx.imageSmoothingEnabled = local.imageSmoothingEnabled;
|
|
|
|
}
|
2020-08-20 15:58:18 -06:00
|
|
|
|
2022-02-08 17:10:24 -07:00
|
|
|
grow (amp) {
|
|
|
|
this.dimentions = this.dimentions.amp(amp);
|
2020-08-20 15:58:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-08 17:10:24 -07:00
|
|
|
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);
|
2022-02-10 08:51:20 -07:00
|
|
|
var refRot = rad2vec(this.rotation.getRadAngle() + (rotation instanceof vector ? rotation : new vector([0,1])).getRadAngle());
|
2022-02-10 09:01:11 -07:00
|
|
|
var center = refPos.add(this.size.mag(0.5));
|
2022-02-10 08:51:20 -07:00
|
|
|
ctx.translate(center.d[0],center.d[1]);
|
|
|
|
ctx.rotate(refRot.getRadAngle());
|
|
|
|
ctx.translate(-center.d[0],-center.d[1]);
|
2022-02-08 17:10:24 -07:00
|
|
|
if (this.shapes.length) {
|
|
|
|
this.shapes.forEach(shape => shape.render(ctx,refPos,refRot));
|
|
|
|
}
|
|
|
|
if (this.containers.length) {
|
2022-02-09 15:25:50 -07:00
|
|
|
this.containers.forEach(cont => cont.renderContainer(ctx,refPos,refRot));
|
2022-02-08 17:10:24 -07:00
|
|
|
}
|
2022-02-10 08:51:20 -07:00
|
|
|
ctx.translate(center.d[0],center.d[1]);
|
|
|
|
ctx.rotate(-origRot);
|
|
|
|
ctx.translate(-center.d[0],-center.d[1]);
|
2022-02-08 17:10:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2022-02-09 12:34:58 -07:00
|
|
|
var slowest = this.movementVector.getLength() <= otherContainer.movementVector.getLength() ? this : otherContainer;
|
|
|
|
var fastest = this.movementVector.getLength() <= otherContainer.movementVector.getLength() ? otherContainer : this;
|
|
|
|
|
|
|
|
var quickest = fastest.movementVector.getLength();
|
|
|
|
for (var t = 0; t <= quickest; t++) {
|
|
|
|
var tFraction = t/(quickest+1);
|
|
|
|
var Atop = slowest.coordinates.d[1]+(tFraction * slowest.movementVector.d[1]);
|
|
|
|
var Abottom = slowest.coordinates.d[1]+(tFraction * slowest.movementVector.d[1])+slowest.dimentions.d[0];
|
|
|
|
var Aleft = slowest.coordinates.d[0]+(tFraction * slowest.movementVector.d[0]);
|
|
|
|
var Aright = slowest.coordinates.d[0]+(tFraction * slowest.movementVector.d[0])+slowest.dimentions.d[1];
|
|
|
|
var Btop = fastest.coordinates.d[1]+(tFraction * fastest.movementVector.d[1]);
|
|
|
|
var Bbottom = fastest.coordinates.d[1]+(tFraction * fastest.movementVector.d[1])+fastest.dimentions.d[0];
|
|
|
|
var Bleft = fastest.coordinates.d[0]+(tFraction * fastest.movementVector.d[0]);
|
|
|
|
var Bright = fastest.coordinates.d[0]+(tFraction * fastest.movementVector.d[0])+fastest.dimentions.d[1];
|
|
|
|
|
|
|
|
var Abound = new bound([Aleft,Atop],[Aright,Abottom]);
|
|
|
|
var Bbound = new bound([Bleft,Btop],[Bright,Bbottom]);
|
|
|
|
if (
|
|
|
|
Bbound.inbounds([Aleft,Atop]) |
|
|
|
|
Bbound.inbounds([Aright,Atop]) |
|
|
|
|
Bbound.inbounds([Aleft,Abottom]) |
|
|
|
|
Bbound.inbounds([Aright,Abottom]) |
|
|
|
|
Abound.inbounds([Bleft,Btop]) |
|
|
|
|
Abound.inbounds([Bright,Btop]) |
|
|
|
|
Abound.inbounds([Bleft,Bbottom]) |
|
|
|
|
Abound.inbounds([Bright,Bbottom])
|
|
|
|
){
|
|
|
|
return callBackFunction(this,otherContainer,t);
|
|
|
|
}
|
2020-08-20 15:58:18 -06:00
|
|
|
}
|
2022-02-09 12:34:58 -07:00
|
|
|
return false;
|
2020-08-20 15:58:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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); });
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|