Session 3: Tree Variety System Complete
TREE VARIETIES IMPLEMENTED: - Added 5 tree types: Cherry, Oak, Pine, Dead, Apple - AI-generated PNG sprites with transparent backgrounds - Random tree selection for natural diversity - Growth scaling (0.4-0.6x for variety) VISUAL IMPROVEMENTS: - 2.5D depth sorting (Y-position based) - Proper shadows matching tree size - Layered rendering for perspective TRANSPARENCY FIXES: - Disabled automatic sprite processing - User manually removed green screen backgrounds - Fixed pink/red color preservation - Trees now render with proper transparency TREE DISTRIBUTION: - Reduced from ~78 to 10 trees (87% reduction) - Removed corner forest clusters (too crowded) - Sparse scattered placement across 100x100 map - Wider spacing (8-15 tiles apart) - Small tree sizes (0.35-0.7x scale, ~50% reduction) TECHNICAL CHANGES: - PreloadScene: Added tree sprite loading - PreloadScene: Disabled processAllTransparency() - Flat2DTerrainSystem: PNG sprite rendering with fallback - map2d_data.js: Sparse tree generation - Green removal threshold: g > 180 (preserves pink/red) FILES MODIFIED: - src/scenes/PreloadScene.js - src/systems/Flat2DTerrainSystem.js - data/map2d_data.js - assets/sprites/tree_*.png (5 new sprites) - docs/DNEVNIK.md (updated with user availability) Session: 1.5h (23:28-00:48) Date: 14-15.12.2024
BIN
assets/chest.png
|
Before Width: | Height: | Size: 559 KiB After Width: | Height: | Size: 314 KiB |
|
Before Width: | Height: | Size: 565 KiB After Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 470 KiB After Width: | Height: | Size: 231 KiB |
|
Before Width: | Height: | Size: 464 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 438 KiB After Width: | Height: | Size: 270 KiB |
BIN
assets/sprites/tree_apple.png
Normal file
|
After Width: | Height: | Size: 351 KiB |
BIN
assets/sprites/tree_cherry.png
Normal file
|
After Width: | Height: | Size: 341 KiB |
BIN
assets/sprites/tree_dead.png
Normal file
|
After Width: | Height: | Size: 450 KiB |
BIN
assets/sprites/tree_oak.png
Normal file
|
After Width: | Height: | Size: 395 KiB |
BIN
assets/sprites/tree_pine.png
Normal file
|
After Width: | Height: | Size: 281 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 556 KiB After Width: | Height: | Size: 405 KiB |
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 365 KiB After Width: | Height: | Size: 348 KiB |
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 332 KiB |
@@ -48,36 +48,19 @@ const Map2DData = {
|
||||
// this.addWindingPath(map, 10, 10, 90, 90); // Disabled
|
||||
// this.addWindingPath(map, 90, 10, 10, 90); // Disabled
|
||||
|
||||
// 3. MORE TREES IN NATURAL CLUSTERS 🌳
|
||||
// Top-left forest
|
||||
this.addTreeCluster(map, 15, 15, 5);
|
||||
this.addTreeCluster(map, 18, 12, 4);
|
||||
this.addTreeCluster(map, 12, 18, 3);
|
||||
// 3. SPARSE SCATTERED TREES 🌳 (NO CLUSTERS!)
|
||||
// Removed all corner forests - too crowded!
|
||||
|
||||
// Top-right forest
|
||||
this.addTreeCluster(map, 85, 15, 5);
|
||||
this.addTreeCluster(map, 82, 18, 4);
|
||||
this.addTreeCluster(map, 88, 12, 3);
|
||||
|
||||
// Bottom-left forest
|
||||
this.addTreeCluster(map, 15, 85, 5);
|
||||
this.addTreeCluster(map, 18, 82, 4);
|
||||
this.addTreeCluster(map, 12, 88, 3);
|
||||
|
||||
// Bottom-right forest
|
||||
this.addTreeCluster(map, 85, 85, 5);
|
||||
this.addTreeCluster(map, 82, 88, 4);
|
||||
this.addTreeCluster(map, 88, 82, 3);
|
||||
|
||||
// Scattered single trees - MANY MORE!
|
||||
for (let i = 0; i < 50; i++) {
|
||||
// Just a few scattered trees across entire map
|
||||
for (let i = 0; i < 10; i++) { // VERY FEW! (was 15)
|
||||
this.addTreeCluster(map,
|
||||
10 + Math.random() * 80, // Wider spread
|
||||
10 + Math.random() * 80, // Entire map
|
||||
10 + Math.random() * 80,
|
||||
1
|
||||
1 // Single trees only
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// 4. COLORFUL FLOWERS SCATTERED 🌸
|
||||
this.addFlowers(map, 30);
|
||||
|
||||
@@ -187,7 +170,7 @@ const Map2DData = {
|
||||
addTreeCluster: function (map, centerX, centerY, count) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
const angle = (Math.PI * 2 * i) / count + Math.random() * 0.5;
|
||||
const radius = 2 + Math.random() * 3;
|
||||
const radius = 8 + Math.random() * 7; // EVEN WIDER! (was 5+7)
|
||||
const tx = Math.floor(centerX + Math.cos(angle) * radius);
|
||||
const ty = Math.floor(centerY + Math.sin(angle) * radius);
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# 📖 DNEVNIK RAZVOJA - NovaFarma
|
||||
|
||||
## ⚠️ **POMEMBNO - User Availability:**
|
||||
**Status:** Na dopustu / bolniški
|
||||
**Razpoložljivost:** Lahko delamo dolge sessions (3-4+ ur)
|
||||
**Ni potrebe:** Skrbeti za čas spanja ali utrujenost
|
||||
**User bo povedal:** Ko je utrujen/zaspan
|
||||
|
||||
---
|
||||
|
||||
## 🗓️ 14. December 2024 - Session 1: Tiled Map Editor Exploration
|
||||
|
||||
**Trajanje:** 2 uri (20:00 - 22:00)
|
||||
|
||||
@@ -56,9 +56,12 @@ class PreloadScene extends Phaser.Scene {
|
||||
this.load.image('tree_blue_final', 'assets/tree_blue_final.png');
|
||||
this.load.image('tree_dead_final', 'assets/tree_dead_final.png');
|
||||
|
||||
// 🌸 CHERRY BLOSSOM TREES (NEW!)
|
||||
this.load.image('cesnjevo_drevo', 'assets/sprites/roza_cesnjevo_drevo.png');
|
||||
this.load.image('cesnja', 'assets/sprites/cesnja_sadje.png');
|
||||
// 🌳 TREE VARIETY SPRITES (GREEN SCREEN!)
|
||||
this.load.image('tree_cherry', 'assets/sprites/tree_cherry.png');
|
||||
this.load.image('tree_oak', 'assets/sprites/tree_oak.png');
|
||||
this.load.image('tree_pine', 'assets/sprites/tree_pine.png');
|
||||
this.load.image('tree_dead', 'assets/sprites/tree_dead.png');
|
||||
this.load.image('tree_apple', 'assets/sprites/tree_apple.png');
|
||||
|
||||
// STARDEW VALLEY FOREST TREES (NEW!)
|
||||
this.load.image('tree_purple', 'assets/tree_purple.png');
|
||||
@@ -153,7 +156,9 @@ class PreloadScene extends Phaser.Scene {
|
||||
// NOTE: Do NOT process spritesheets - they already have proper alpha!
|
||||
// Processing destroys frame definitions
|
||||
|
||||
this.processAllTransparency();
|
||||
// 🚫 DISABLED - Tree sprites already have transparency!
|
||||
// this.processAllTransparency();
|
||||
|
||||
this.createAnimations();
|
||||
});
|
||||
|
||||
@@ -345,10 +350,10 @@ class PreloadScene extends Phaser.Scene {
|
||||
'wheat_sprite',
|
||||
'grass_sprite',
|
||||
'leaf_sprite',
|
||||
'stone_sprite',
|
||||
'stone_sprite'
|
||||
|
||||
// 🌸 CHERRY BLOSSOM TREE
|
||||
'cesnjevo_drevo'
|
||||
// 🌳 TREES REMOVED - already have transparent PNG!
|
||||
// (green removal would delete green leaves!)
|
||||
];
|
||||
|
||||
spritesToProcess.forEach(spriteKey => {
|
||||
@@ -360,10 +365,10 @@ class PreloadScene extends Phaser.Scene {
|
||||
this.ultraRemoveBackground('fence_post');
|
||||
}
|
||||
|
||||
// ULTRA AGGRESSIVE: Cherry Blossom Tree (remove black outlines!)
|
||||
if (this.textures.exists('cesnjevo_drevo')) {
|
||||
this.ultraRemoveBackground('cesnjevo_drevo');
|
||||
}
|
||||
// ULTRA REMOVED - new tree sprites already have transparency!
|
||||
// if (this.textures.exists('cesnjevo_drevo')) {
|
||||
// this.ultraRemoveBackground('cesnjevo_drevo');
|
||||
// }
|
||||
|
||||
console.log('✅ All sprites transparency processed!');
|
||||
}
|
||||
@@ -399,15 +404,16 @@ class PreloadScene extends Phaser.Scene {
|
||||
|
||||
const brightness = (r + g + b) / 3;
|
||||
|
||||
// 🟢 NUCLEAR GREEN SCREEN REMOVAL!
|
||||
// Remove ANY pixel where green is even SLIGHTLY dominant
|
||||
// 🟢 GREEN REMOVAL - Only BRIGHT greens!
|
||||
// Pink (255,105,180) has g=105 - MUST KEEP!
|
||||
// Bright green (0,255,0) has g=255 - REMOVE!
|
||||
const isGreen = (
|
||||
g > 100 && // Even darker greens
|
||||
g > r && // Green beats red
|
||||
g > b // Green beats blue
|
||||
g > 180 && // Only very bright green
|
||||
g > r * 1.3 && // Green dominates red
|
||||
g > b * 1.3 // Green dominates blue
|
||||
);
|
||||
if (isGreen) {
|
||||
data[i + 3] = 0; // NUKE IT!
|
||||
data[i + 3] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -309,69 +309,259 @@ class Flat2DTerrainSystem {
|
||||
}
|
||||
|
||||
if (sprite) {
|
||||
// 🎨 2.5D DEPTH SORTING - Y position = depth!
|
||||
// Objects lower on screen appear in front
|
||||
sprite.setDepth(10 + worldY);
|
||||
this.decorLayer.add(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
createTree(x, y) {
|
||||
// 🌸 PNG DISABLED - procedural is more reliable!
|
||||
// if (this.scene.textures.exists('cesnjevo_drevo')) {
|
||||
// const tree = this.scene.add.image(x, y, 'cesnjevo_drevo');
|
||||
// const growthScale = Phaser.Math.FloatBetween(0.3, 0.7);
|
||||
// tree.setScale(growthScale);
|
||||
// tree.setOrigin(0.5, 0.9);
|
||||
// const shadow = this.scene.add.ellipse(x, y + 10, 20 * growthScale, 6, 0x000000, 0.15);
|
||||
// shadow.setDepth(tree.depth - 1);
|
||||
// return tree;
|
||||
// }
|
||||
// 🌳 TREE VARIETY SYSTEM!
|
||||
const treeTypes = ['cherry', 'oak', 'pine', 'dead', 'apple'];
|
||||
const randomType = Phaser.Utils.Array.GetRandom(treeTypes);
|
||||
|
||||
// PROCEDURAL CHERRY BLOSSOM (RELIABLE!)
|
||||
switch (randomType) {
|
||||
case 'oak': return this.createOakTree(x, y);
|
||||
case 'pine': return this.createPineTree(x, y);
|
||||
case 'dead': return this.createDeadTree(x, y);
|
||||
case 'apple': return this.createAppleTree(x, y);
|
||||
default: return this.createCherryTree(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
createCherryTree(x, y) {
|
||||
// 🌸 PNG SPRITE!
|
||||
if (this.scene.textures.exists('tree_cherry')) {
|
||||
const tree = this.scene.add.image(x, y, 'tree_cherry');
|
||||
const scale = Phaser.Math.FloatBetween(0.4, 0.6); // SMALLER! (was 0.8-1.2)
|
||||
tree.setScale(scale);
|
||||
tree.setOrigin(0.5, 0.85);
|
||||
|
||||
// Shadow
|
||||
const shadow = this.scene.add.ellipse(x, y + 15, 30 * scale, 10, 0x000000, 0.2);
|
||||
shadow.setDepth(tree.depth - 1);
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
// FALLBACK: Procedural
|
||||
return this.createProceduralCherryTree(x, y);
|
||||
}
|
||||
|
||||
createProceduralCherryTree(x, y) {
|
||||
// Old procedural code (backup)
|
||||
const graphics = this.scene.add.graphics();
|
||||
const growthScale = Phaser.Math.FloatBetween(0.8, 1.4); // BIGGER!
|
||||
|
||||
// DROP SHADOW (2D depth!) 🎨
|
||||
graphics.fillStyle(0x000000, 0.15);
|
||||
graphics.fillEllipse(x + 1, y + 24, 20, 6);
|
||||
const heightOffset = -20 * growthScale;
|
||||
const crownSize = 30 * growthScale; // MUCH BIGGER!
|
||||
|
||||
// TRUNK - simple rectangle
|
||||
graphics.fillStyle(0x8B4513);
|
||||
graphics.fillRect(x - 4, y + 6, 8, 18);
|
||||
// Shadow (ellipse on ground)
|
||||
graphics.fillStyle(0x000000, 0.2);
|
||||
graphics.fillEllipse(x, y + 30, 40 * growthScale, 12); // Bigger shadow
|
||||
|
||||
// Trunk outline
|
||||
graphics.lineStyle(1, 0x654321);
|
||||
graphics.strokeRect(x - 4, y + 6, 8, 18);
|
||||
// Trunk (with shading for volume)
|
||||
const trunkW = 12 * growthScale; // Thicker
|
||||
const trunkH = 30 * growthScale; // Taller
|
||||
|
||||
// CHERRY BLOSSOM CROWN - FLAT 2D TRIANGLE! 🌸
|
||||
// Base pink triangle
|
||||
// Dark side (right)
|
||||
graphics.fillStyle(0x6D3F1A);
|
||||
graphics.fillRect(x + trunkW / 4, y + 10 + heightOffset, trunkW / 2, trunkH);
|
||||
|
||||
// Light side (left)
|
||||
graphics.fillStyle(0x8B5A2B);
|
||||
graphics.fillRect(x - trunkW / 2, y + 10 + heightOffset, trunkW / 2, trunkH);
|
||||
|
||||
// CROWN - Layered circles for 2.5D!
|
||||
const crownY = y - 10 * growthScale + heightOffset; // Higher crown
|
||||
|
||||
// Dark base (shadow underneath)
|
||||
graphics.fillStyle(0xE75480);
|
||||
graphics.fillCircle(x + 4 * growthScale, crownY + 4 * growthScale, crownSize);
|
||||
|
||||
// Main pink crown
|
||||
graphics.fillStyle(0xFF69B4);
|
||||
graphics.fillCircle(x, crownY, crownSize);
|
||||
|
||||
// Top highlight (light from top-left)
|
||||
graphics.fillStyle(0xFFB6C1, 0.8);
|
||||
graphics.fillCircle(x - 6 * growthScale, crownY - 6 * growthScale, crownSize * 0.6);
|
||||
|
||||
// Bright specular spot
|
||||
graphics.fillStyle(0xFFFFFF, 0.5);
|
||||
graphics.fillCircle(x - 8 * growthScale, crownY - 8 * growthScale, crownSize * 0.3);
|
||||
|
||||
return graphics;
|
||||
}
|
||||
|
||||
createOakTree(x, y) {
|
||||
// 🌲 PNG SPRITE!
|
||||
if (this.scene.textures.exists('tree_oak')) {
|
||||
const tree = this.scene.add.image(x, y, 'tree_oak');
|
||||
const scale = Phaser.Math.FloatBetween(0.45, 0.65); // SMALLER!
|
||||
tree.setScale(scale);
|
||||
tree.setOrigin(0.5, 0.85);
|
||||
const shadow = this.scene.add.ellipse(x, y + 15, 35 * scale, 12, 0x000000, 0.2);
|
||||
shadow.setDepth(tree.depth - 1);
|
||||
return tree;
|
||||
}
|
||||
|
||||
// FALLBACK:
|
||||
const graphics = this.scene.add.graphics();
|
||||
const growthScale = Phaser.Math.FloatBetween(0.8, 1.4); // BIGGER!
|
||||
|
||||
// Shadow
|
||||
graphics.fillStyle(0x000000, 0.15);
|
||||
graphics.fillEllipse(x, y + 24, 25 * growthScale, 8);
|
||||
|
||||
// Thick trunk
|
||||
graphics.fillStyle(0x654321);
|
||||
graphics.fillRect(x - 5 * growthScale, y, 10 * growthScale, 24 * growthScale);
|
||||
|
||||
// Large round crown
|
||||
graphics.fillStyle(0x228B22); // Forest green
|
||||
graphics.fillCircle(x, y - 10 * growthScale, 18 * growthScale);
|
||||
|
||||
// Darker outline
|
||||
graphics.lineStyle(2, 0x006400);
|
||||
graphics.strokeCircle(x, y - 10 * growthScale, 18 * growthScale);
|
||||
|
||||
// Highlight
|
||||
graphics.fillStyle(0x32CD32, 0.6);
|
||||
graphics.fillCircle(x - 5 * growthScale, y - 15 * growthScale, 8 * growthScale);
|
||||
|
||||
return graphics;
|
||||
}
|
||||
|
||||
createPineTree(x, y) {
|
||||
// 🌲 PNG SPRITE!
|
||||
if (this.scene.textures.exists('tree_pine')) {
|
||||
const tree = this.scene.add.image(x, y, 'tree_pine');
|
||||
const scale = Phaser.Math.FloatBetween(0.45, 0.7); // SMALLER!
|
||||
tree.setScale(scale);
|
||||
tree.setOrigin(0.5, 0.9); // Taller
|
||||
const shadow = this.scene.add.ellipse(x, y + 20, 30 * scale, 10, 0x000000, 0.2);
|
||||
shadow.setDepth(tree.depth - 1);
|
||||
return tree;
|
||||
}
|
||||
|
||||
// FALLBACK:
|
||||
const graphics = this.scene.add.graphics();
|
||||
const growthScale = Phaser.Math.FloatBetween(0.8, 1.5); // BIGGER (Pine taller)
|
||||
|
||||
// Shadow
|
||||
graphics.fillStyle(0x000000, 0.15);
|
||||
graphics.fillEllipse(x, y + 20, 15 * growthScale, 6);
|
||||
|
||||
// Trunk
|
||||
graphics.fillStyle(0x8B4513);
|
||||
graphics.fillRect(x - 3 * growthScale, y + 5, 6 * growthScale, 15 * growthScale);
|
||||
|
||||
// Stacked triangles (pine shape)
|
||||
graphics.fillStyle(0x2F4F2F); // Dark green
|
||||
|
||||
// Bottom tier
|
||||
graphics.fillTriangle(
|
||||
x, y - 18, // Top point
|
||||
x - 16, y + 8, // Bottom left
|
||||
x + 16, y + 8 // Bottom right
|
||||
x, y - 5 * growthScale,
|
||||
x - 14 * growthScale, y + 10,
|
||||
x + 14 * growthScale, y + 10
|
||||
);
|
||||
|
||||
// Dark outline (2D cartoon style!)
|
||||
graphics.lineStyle(2, 0xDB7093, 1.0);
|
||||
graphics.strokeTriangle(
|
||||
x, y - 18,
|
||||
x - 16, y + 8,
|
||||
x + 16, y + 8
|
||||
// Middle tier
|
||||
graphics.fillTriangle(
|
||||
x, y - 15 * growthScale,
|
||||
x - 10 * growthScale, y,
|
||||
x + 10 * growthScale, y
|
||||
);
|
||||
|
||||
// Inner lighter triangle (highlight)
|
||||
graphics.fillStyle(0xFFB6C1);
|
||||
// Top tier
|
||||
graphics.fillTriangle(
|
||||
x, y - 14,
|
||||
x - 10, y + 4,
|
||||
x + 10, y + 4
|
||||
x, y - 25 * growthScale,
|
||||
x - 7 * growthScale, y - 10 * growthScale,
|
||||
x + 7 * growthScale, y - 10 * growthScale
|
||||
);
|
||||
|
||||
// Top highlight (blossom peak!)
|
||||
graphics.fillStyle(0xFFFFFF, 0.7);
|
||||
graphics.fillTriangle(
|
||||
x, y - 14,
|
||||
x - 6, y - 4,
|
||||
x + 6, y - 4
|
||||
return graphics;
|
||||
}
|
||||
|
||||
createDeadTree(x, y) {
|
||||
// 💀 PNG SPRITE!
|
||||
if (this.scene.textures.exists('tree_dead')) {
|
||||
const tree = this.scene.add.image(x, y, 'tree_dead');
|
||||
const scale = Phaser.Math.FloatBetween(0.35, 0.55); // SMALLER!
|
||||
tree.setScale(scale);
|
||||
tree.setOrigin(0.5, 0.85);
|
||||
const shadow = this.scene.add.ellipse(x, y + 18, 28 * scale, 10, 0x000000, 0.3);
|
||||
shadow.setDepth(tree.depth - 1);
|
||||
return tree;
|
||||
}
|
||||
|
||||
// FALLBACK:
|
||||
const graphics = this.scene.add.graphics();
|
||||
const growthScale = Phaser.Math.FloatBetween(0.7, 1.2); // BIGGER!
|
||||
|
||||
// Shadow
|
||||
graphics.fillStyle(0x000000, 0.2);
|
||||
graphics.fillEllipse(x, y + 20, 18 * growthScale, 6);
|
||||
|
||||
// Dark trunk
|
||||
graphics.fillStyle(0x3D3D3D);
|
||||
graphics.fillRect(x - 4 * growthScale, y, 8 * growthScale, 22 * growthScale);
|
||||
|
||||
// Branches (bare)
|
||||
graphics.lineStyle(3 * growthScale, 0x2D2D2D);
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(x, y - 5 * growthScale);
|
||||
graphics.lineTo(x - 10 * growthScale, y - 15 * growthScale);
|
||||
graphics.moveTo(x, y - 8 * growthScale);
|
||||
graphics.lineTo(x + 12 * growthScale, y - 12 * growthScale);
|
||||
graphics.strokePath();
|
||||
|
||||
return graphics;
|
||||
}
|
||||
|
||||
createAppleTree(x, y) {
|
||||
// 🍎 PNG SPRITE!
|
||||
if (this.scene.textures.exists('tree_apple')) {
|
||||
const tree = this.scene.add.image(x, y, 'tree_apple');
|
||||
const scale = Phaser.Math.FloatBetween(0.4, 0.6); // SMALLER!
|
||||
tree.setScale(scale);
|
||||
tree.setOrigin(0.5, 0.85);
|
||||
const shadow = this.scene.add.ellipse(x, y + 16, 32 * scale, 11, 0x000000, 0.2);
|
||||
shadow.setDepth(tree.depth - 1);
|
||||
return tree;
|
||||
}
|
||||
|
||||
// FALLBACK:
|
||||
const graphics = this.scene.add.graphics();
|
||||
const growthScale = Phaser.Math.FloatBetween(0.8, 1.3); // BIGGER!
|
||||
|
||||
// Shadow
|
||||
graphics.fillStyle(0x000000, 0.15);
|
||||
graphics.fillEllipse(x, y + 22, 22 * growthScale, 7);
|
||||
|
||||
// Trunk
|
||||
graphics.fillStyle(0x8B4513);
|
||||
graphics.fillRect(x - 4 * growthScale, y + 2, 8 * growthScale, 20 * growthScale);
|
||||
|
||||
// Green crown
|
||||
graphics.fillStyle(0x3CB371); // Medium sea green
|
||||
graphics.fillCircle(x, y - 8 * growthScale, 16 * growthScale);
|
||||
|
||||
// Apples (red circles)
|
||||
graphics.fillStyle(0xFF0000);
|
||||
const applePositions = [
|
||||
{ x: -8, y: -12 }, { x: 5, y: -10 }, { x: -3, y: -5 },
|
||||
{ x: 8, y: -8 }, { x: 0, y: -15 }
|
||||
];
|
||||
applePositions.forEach(pos => {
|
||||
graphics.fillCircle(
|
||||
x + pos.x * growthScale,
|
||||
y + pos.y * growthScale,
|
||||
3 * growthScale
|
||||
);
|
||||
});
|
||||
|
||||
return graphics;
|
||||
}
|
||||
|
||||