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.

167 lines
5.0 KiB

2 years ago
import has = Reflect.has;
class Chain extends Decoration{
p1: p5.Vector = p.createVector(-0.65, 0)
p2: p5.Vector = p.createVector(0.65, 0)
p1IsBoundToMouse: boolean = false
p2IsBoundToMouse: boolean = false
placedOnce: boolean = false
points: {x: number, y: number}[] = []
lights: {x: number, y: number}[] = []
constructor(properties: object){
super(properties);
this.generate();
}
get properties(): object{
let obj = super.properties;
obj['p1'] = this.p1;
obj['p2'] = this.p2;
return obj;
}
generate(){
let d = p.dist(this.p1.x, this.p1.y, this.p2.x, this.p2.y);
let m = p.abs((this.p2.y - this.p1.y) / (this.p2.x - this.p1.x));
let a = -1 / d - m / 10;
let b = (this.p1.y - this.p2.y + a * p.pow(this.p2.x, 2) - a * p.pow(this.p1.x, 2)) /
(this.p1.x - this.p2.x);
if (this.p1.x - this.p2.x === 0)
b = 0;
let c = this.p1.y - a * p.pow(this.p1.x, 2) - b * this.p1.x;
let func = x => a * x * x + b * x + c;
let detail = 40;
let points = [];
for (let i = 0; i <= detail; i++){
let point = {x: 0, y: 0};
point.x = this.p1.x + (this.p2.x - this.p1.x) / detail * i;
point.y = func(point.x);
points.push(point);
}
let lightDist = 0.35;
let lastLight = {x: Infinity, y: Infinity};
let lights = []
detail = 300;
for (let i = 0; i <= detail; i++){
let point = {x: 0, y: 0, hasLight: false};
point.x = this.p1.x + (this.p2.x - this.p1.x) / detail * i;
point.y = func(point.x);
if (p.dist(point.x, point.y, lastLight.x, lastLight.y) >= lightDist){
lights.push(point);
lastLight = point;
}
}
this.points = points;
this.lights = lights;
}
display(pos?: p5.Vector, dim?: p5.Vector){
super.display(pos, dim);
p.strokeWeight(0.05);
p.stroke(0);
p.noFill();
p.beginShape();
for (let point of this.points)
p.vertex(point.x, point.y);
p.endShape();
p.strokeWeight(0.01);
let i = 0;
for (let point of this.lights){
let colorIndex = (i + p.int(p.frameCount / 30)) % this.colors.length;
p.fill(this.colors[colorIndex]);
p.ellipse(point.x, point.y, 0.2, 0.2);
i++;
}
p.pop();
}
get hasValidPosition(): boolean{
return game.tree.containsPosition(this.realPosByAnchor(this.p1), true)
&& game.tree.containsPosition(this.realPosByAnchor(this.p2), true);
}
realPosByAnchor(anchor): p5.Vector{
return p5.Vector.add(p5.Vector.mult(p5.Vector.add(this.pos, anchor), game.tree.sizeMultiplier), game.center);
}
realPointDistToAnchor(point, anchor){
let pos = this.realPosByAnchor(anchor);
return p.dist(pos.x, pos.y, point.x, point.y);
}
isMouseOverAnchor(anchor){
return this.realPointDistToAnchor(p.createVector(p.mouseX, p.mouseY), anchor) <= 0.5 * game.tree.sizeMultiplier;
}
get mouseIsOver(): boolean{
return this.isTaken && (this.isMouseOverAnchor(this.p1) || this.isMouseOverAnchor(this.p2));
}
//Mouse is over this
mousePressed() {
super.mousePressed();
if (this.isMouseOverAnchor(this.p1)){
this.p1IsBoundToMouse = true;
} else if (this.isMouseOverAnchor(this.p2)){
this.p2IsBoundToMouse = true;
}
}
updateFromPoint(point, other, x, y){
if (this.placedOnce){
let pointRelative = p.createVector(x - this.pos.x, y - this.pos.y);
point.set(pointRelative);
let pointReal = p5.Vector.add(this.pos, point);
let otherReal = p5.Vector.add(this.pos, other);
let newPos = p5.Vector.div(p5.Vector.add(pointReal, otherReal), 2);
point.set(p5.Vector.sub(pointReal, newPos));
other.set(p5.Vector.mult(point, -1));
this.pos.set(newPos);
} else {
this.pos.set(x - point.x, y - point.y);
}
}
update(){
let x = (p.mouseX - game.center.x) / game.tree.sizeMultiplier,
y = (p.mouseY - game.center.y) / game.tree.sizeMultiplier;
if (this.isBoundToMouse){
if (this.p1IsBoundToMouse){
this.updateFromPoint(this.p1, this.p2, x, y);
}
if (this.p2IsBoundToMouse){
this.updateFromPoint(this.p2, this.p1, x, y);
}
this.generate();
} else {
super.update();
}
if (this.isTaken && !this.isBoundToMouse){
this.placedOnce = true;
}
}
toJSON(index){
let list = [
"p1",
"p2"
]
let obj = super.toJSON(index);
for (let item of list){
obj[item] = this[item];
}
return obj;
}
}