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; } }