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

2 years ago
"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