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.
223 lines
7.0 KiB
223 lines
7.0 KiB
"use strict";
|
|
class Tree {
|
|
constructor(properties) {
|
|
this.pos = p.createVector();
|
|
this.sizeMultiplier = 1;
|
|
this.animationProgress = 0;
|
|
this.animationDirection = -1;
|
|
this.decorations = [];
|
|
if (properties == null) {
|
|
this.isPlaceholder = true;
|
|
}
|
|
else {
|
|
for (let key in properties) {
|
|
this[key] = properties[key];
|
|
}
|
|
}
|
|
}
|
|
//Always called
|
|
mousePressed() {
|
|
for (let d of [...this.decorations].reverse()) {
|
|
if (d.mouseIsOver) {
|
|
d.mousePressed();
|
|
let index = this.decorations.findIndex(deco => deco == d);
|
|
this.decorations[index] = this.decorations[this.decorations.length - 1];
|
|
this.decorations[this.decorations.length - 1] = d;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//Always called
|
|
mouseReleased() {
|
|
for (let d of this.decorations) {
|
|
d.mouseReleased();
|
|
}
|
|
}
|
|
get smoothProgress() {
|
|
return this.smoothStep(0, 1, this.animationProgress);
|
|
}
|
|
containsPosition(pos, excludeStem) {
|
|
let size = game.height, x = (p.width - size) / 2;
|
|
let px = pos.x, py = pos.y;
|
|
let pixelColor = p.get(px, py).slice(0, 3);
|
|
let colorIsValid = game.tree.getAllColors(excludeStem).find(c => equals(c, pixelColor)) != null;
|
|
return colorIsValid &&
|
|
px > x && px < x + size &&
|
|
py > 0 && py < size - 20;
|
|
}
|
|
update() {
|
|
this.animationProgress += 0.05 * this.animationDirection;
|
|
this.animationProgress = this.animationProgress > 1 ? 1 : this.animationProgress < 0 ? 0 : this.animationProgress;
|
|
if (this.isPlaceholder) {
|
|
this.pos = game.center;
|
|
this.sizeMultiplier = game.height * 0.05;
|
|
}
|
|
else {
|
|
this.pos = p5.Vector.lerp(this.container.center, game.center, this.smoothProgress);
|
|
this.sizeMultiplier = p.lerp(this.container.dim.y * 0.05, game.height * 0.05, this.smoothProgress);
|
|
}
|
|
this.decorations.forEach((d, i) => {
|
|
if (d.isToDelete) {
|
|
this.decorations.splice(i, 1);
|
|
if (d instanceof Ball) {
|
|
d.graphics.remove();
|
|
}
|
|
}
|
|
});
|
|
this.decorations.forEach(d => d.update());
|
|
}
|
|
display(pos, dim) {
|
|
let sizeMultiplier = this.sizeMultiplier;
|
|
if (pos || dim) {
|
|
sizeMultiplier = dim.y * 0.05;
|
|
}
|
|
else {
|
|
pos = this.pos;
|
|
}
|
|
p.push();
|
|
p.translate(pos.x, pos.y);
|
|
p.scale(sizeMultiplier);
|
|
if (this.isPlaceholder) {
|
|
p.fill(0);
|
|
p.stroke(100, 220, 100);
|
|
p.strokeWeight(0.05);
|
|
p.textSize(1);
|
|
p.textAlign(p.CENTER, p.CENTER);
|
|
p.text('Select your Christmas Tree!', 0, 0);
|
|
}
|
|
else {
|
|
this.drawTree();
|
|
this.drawDecorations();
|
|
if (debug && this === game.tree) {
|
|
p.stroke(255, 0, 0, 80);
|
|
p.strokeWeight(0.05);
|
|
for (let i = -10; i <= 10; i++) {
|
|
p.line(-10, i, 10, i);
|
|
p.line(i, -10, i, 10);
|
|
}
|
|
}
|
|
}
|
|
p.pop();
|
|
}
|
|
drawTree() {
|
|
p.push();
|
|
p.translate(0, 1);
|
|
p.fill(this.stemColor);
|
|
p.stroke(0);
|
|
p.strokeWeight(0.05);
|
|
p.rect(-this.stemRadius, 0, this.stemRadius * 2, this.stemHeight);
|
|
let drawLeaf = (r, h) => {
|
|
if (this.isSmooth) {
|
|
let cps = [
|
|
p.createVector(40, 70),
|
|
p.createVector(60, 90),
|
|
p.createVector(100, 130),
|
|
p.createVector(-100, 130),
|
|
p.createVector(-60, 90),
|
|
p.createVector(-40, 70)
|
|
];
|
|
cps.forEach(c => {
|
|
c.x *= r / 100;
|
|
c.y *= h / 100;
|
|
});
|
|
p.beginShape();
|
|
p.vertex(0, 0);
|
|
p.bezierVertex(cps[0].x, cps[0].y, cps[1].x, cps[1].y, r, h);
|
|
p.bezierVertex(cps[2].x, cps[2].y, cps[3].x, cps[3].y, -r, h);
|
|
p.bezierVertex(cps[4].x, cps[4].y, cps[5].x, cps[5].y, 0, 0);
|
|
p.endShape();
|
|
if (debug) {
|
|
p.stroke(255, 0, 0);
|
|
cps.forEach(c => p.ellipse(c.x, c.y, 0));
|
|
}
|
|
}
|
|
else {
|
|
p.triangle(0, 0, r, h, -r, h);
|
|
}
|
|
};
|
|
for (let i = 0; i < this.leafCount; i++) {
|
|
let y = -i * this.leafHeight / 2;
|
|
let lr = this.leafRadius * (this.leafCount - i) / this.leafCount;
|
|
p.push();
|
|
p.translate(0, y);
|
|
p.fill(this.leafColors[i % this.leafColors.length]);
|
|
drawLeaf(lr, this.leafHeight);
|
|
p.pop();
|
|
}
|
|
p.pop();
|
|
}
|
|
drawDecorations() {
|
|
for (let d of this.decorations) {
|
|
if (d.needsValidation) {
|
|
if (!d.hasValidPosition) {
|
|
d.isToDelete = true;
|
|
}
|
|
d.needsValidation = false;
|
|
}
|
|
}
|
|
for (let d of this.decorations) {
|
|
if (released && d.isBoundToMouse) {
|
|
d.needsValidation = true;
|
|
d.isBoundToMouse = false;
|
|
if (d instanceof Chain) {
|
|
d.p1IsBoundToMouse = false;
|
|
d.p2IsBoundToMouse = false;
|
|
}
|
|
}
|
|
d.display();
|
|
}
|
|
}
|
|
getAllColors(withoutStem) {
|
|
let colors = [];
|
|
colors.push(...this.leafColors, [0, 0, 0]);
|
|
if (!withoutStem) {
|
|
colors.push(this.stemColor);
|
|
}
|
|
return colors;
|
|
}
|
|
smoothStep(start, end, t) {
|
|
function clamp(x, lowLimit, upLimit) {
|
|
if (x < lowLimit)
|
|
x = lowLimit;
|
|
if (x > upLimit)
|
|
x = upLimit;
|
|
return x;
|
|
}
|
|
t = clamp((t - start) / (end - start), 0, 1);
|
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
|
}
|
|
toJSON(index) {
|
|
let list = [
|
|
"stemRadius",
|
|
"leafCount",
|
|
"leafColors",
|
|
"stemColor",
|
|
"stemHeight",
|
|
"leafHeight",
|
|
"leafRadius",
|
|
"isSmooth",
|
|
"isPlaceholder",
|
|
"decorations"
|
|
];
|
|
let obj = {};
|
|
for (let item of list) {
|
|
obj[item] = this[item];
|
|
}
|
|
return obj;
|
|
}
|
|
restoreFrom(rawTree) {
|
|
for (let key in rawTree) {
|
|
if (key === 'decorations') {
|
|
this[key] = [];
|
|
rawTree[key].forEach(rawDeco => {
|
|
let deco = Decoration.restoreFrom(rawDeco);
|
|
this[key].push(deco);
|
|
});
|
|
}
|
|
else {
|
|
this[key] = rawTree[key];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//# sourceMappingURL=tree.js.map
|