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
167 lines
5.0 KiB
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;
|
|
}
|
|
|
|
} |