class Decoration{ pos: p5.Vector = p.createVector() colors: number[][] radius: number sizeMultiplier: number container: Container isTaken: boolean = false isBoundToMouse: boolean = false; isToDelete: boolean = false; needsValidation: boolean = false; isSelected: boolean = false; type: string constructor(properties: object){ for (let key in properties){ if (properties.hasOwnProperty(key)){ if (Array.isArray(properties[key])){ this[key] = arrayCopy(properties[key]); } else { this[key] = properties[key]; } } } } get properties(): object{ let colors = []; for (let i = 0; i < this.colors.length; i++){ let color = []; for (let c of this.colors[i]){ color.push(c); } colors.push(color); } return { radius: this.radius, colors: colors, type: this.type }; } get mouseIsOver(): boolean{ if (this.isTaken){ let pos = this.realPos; return p.dist(pos.x, pos.y, p.mouseX, p.mouseY) <= this.radius * game.tree.sizeMultiplier; } return false; } get hasValidPosition(): boolean{ return game.tree.containsPosition(this.realPos, true); } get realPos(): p5.Vector{ return p5.Vector.add(p5.Vector.mult(this.pos, game.tree.sizeMultiplier), game.center); } static Create(properties: object): Decoration{ switch (properties['type']){ case 'ball': return new Ball(properties); case 'star': return new Star(properties); case 'chain': return new Chain(properties); } } display(pos?: p5.Vector, dim?: p5.Vector){ let sizeMultiplier = this.sizeMultiplier; if (pos || dim){ sizeMultiplier = dim.y * 0.6; } else { pos = this.pos; } p.push(); p.translate(pos); p.scale(sizeMultiplier); } brightness(value: number){ p.noStroke(); p.fill(0, 0, 0, value); p.ellipse(0, 0, this.radius * 2, this.radius * 2); } update(){ if (!this.isTaken){ this.pos = this.container.center; this.sizeMultiplier = this.container.dim.y * 0.6; } else { this.sizeMultiplier = 1; } if (this.isBoundToMouse){ let x = (p.mouseX - game.center.x) / game.tree.sizeMultiplier, y = (p.mouseY - game.center.y) / game.tree.sizeMultiplier; this.pos.set(x, y); } } //Assumes mouse is over this mousePressed(){ this.isBoundToMouse = true; } //Always called mouseReleased(){ } toJSON(index){ let list = [ "pos", "colors", "radius", "type" ] let obj = {}; for (let item of list){ obj[item] = this[item]; } return obj; } static restoreFrom(rawDeco: object){ let props = {}; for (let key in rawDeco){ if (['pos', 'p1', 'p2'].find(s => s === key) === undefined){ props[key] = rawDeco[key]; } } let deco = Decoration.Create(props); deco.isTaken = true; deco.pos.x = rawDeco['pos'].x; deco.pos.y = rawDeco['pos'].y; if (deco instanceof Chain){ deco.p1.set(rawDeco['p1'].x, rawDeco['p1'].y); deco.p2.set(rawDeco['p2'].x, rawDeco['p2'].y); deco.generate(); } return deco; } } function darker(c){ let newC = [] for (let v of c){ newC.push(p.constrain(v * 0.6, 0, 255)); } return newC; } function arrayCopy(a){ let newArr = []; for (let c of a){ let copy = c; if (Array.isArray(c)){ copy = arrayCopy(c); } newArr.push(copy); } return newArr; } function equals(a1, a2){ // if the other array is a falsy value, return if (!a1) return false; // compare lengths - can save a lot of time if (a2.length != a1.length) return false; for (let i = 0, l=a2.length; i < l; i++) { // Check if we have nested arrays if (a2[i] instanceof Array && a1[i] instanceof Array) { // recurse into the nested arrays if (!a2[i].equals(a1[i])) return false; } else if (a2[i] != a1[i]) { // Warning - two different object instances will never be equal: {x:20} != {x:20} return false; } } return true; }