Files
novafarma/old_logic/src_backup_1768938138/utils/TextureGenerator.js
2026-01-21 01:08:21 +01:00

1505 lines
50 KiB
JavaScript

// Texture Generator
// Proceduralno generiranje tekstur in sprite-ov
class TextureGenerator {
// Generiraj player sprite (32x32px pixel art)
static createPlayerSprite(scene, key = 'player') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Body
ctx.fillStyle = '#A0522D'; // Sienna skin
ctx.fillRect(10, 8, 12, 12); // Head
ctx.fillStyle = '#2F4F4F'; // DarkSlateGray shirt
ctx.fillRect(8, 20, 16, 12);
// Eyes
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(12, 12, 2, 2);
ctx.fillRect(18, 12, 2, 2);
ctx.fillStyle = '#000000';
ctx.fillRect(13, 12, 1, 1);
ctx.fillRect(19, 12, 1, 1);
// Hair
ctx.fillStyle = '#000000';
ctx.fillRect(10, 6, 12, 4);
ctx.fillRect(8, 8, 2, 6);
ctx.fillRect(22, 8, 2, 6);
canvas.refresh();
}
// Generiraj walking animacijo
static createPlayerWalkSprite(scene, key = 'player_walk') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 128, 32);
const ctx = canvas.getContext();
// Simple placeholders for 4 frames
for (let i = 0; i < 4; i++) {
ctx.fillStyle = '#2F4F4F';
ctx.fillRect(i * 32 + 8, 6, 16, 26);
}
canvas.refresh();
}
// Generiraj NPC sprite
static createNPCSprite(scene, key = 'npc', type = 'zombie') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Elite Zombie: Red body, glowing pink eyes
if (type === 'elite_zombie') {
ctx.fillStyle = '#8B0000'; // DarkRed
ctx.fillRect(8, 6, 16, 26);
// Glowing Eyes
ctx.fillStyle = '#FF1493'; // Deep Pink (glow)
ctx.fillRect(10, 10, 4, 4);
ctx.fillRect(20, 10, 4, 4);
} else {
ctx.fillStyle = (type === 'zombie') ? '#556B2F' : '#DEB887';
ctx.fillRect(8, 6, 16, 26);
// Eyes (Red for zombie)
ctx.fillStyle = (type === 'zombie') ? '#FF0000' : '#000000';
ctx.fillRect(10, 10, 4, 4);
ctx.fillRect(20, 10, 4, 4);
}
canvas.refresh();
}
static createMerchantSprite(scene, key = 'merchant_texture') {
if (scene.textures.exists(key)) return;
console.log('🧙‍♂️ Creating Merchant Sprite Texture...');
try {
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Body (BRIGHT GOLD robe - zelo viden!)
ctx.fillStyle = '#FFD700'; // Gold
ctx.fillRect(8, 6, 16, 26);
// Head
ctx.fillStyle = '#FFE4C4'; // Bisque skin
ctx.fillRect(10, 4, 12, 12);
// Hat (Red Merchants Hat)
ctx.fillStyle = '#8B0000'; // DarkRed
ctx.fillRect(8, 2, 16, 4);
ctx.fillRect(10, 0, 12, 2); // Hat Top
// Backpack (Brown - visible on sides)
ctx.fillStyle = '#8B4513';
ctx.fillRect(4, 10, 4, 14); // Left side pack
ctx.fillRect(24, 10, 4, 14); // Right side pack
// Straps
ctx.fillStyle = '#A0522D';
ctx.fillRect(8, 10, 16, 2);
// Eyes
ctx.fillStyle = '#000000';
ctx.fillRect(13, 8, 2, 2);
ctx.fillRect(17, 8, 2, 2);
// Beard (White)
ctx.fillStyle = '#F5F5F5';
ctx.fillRect(10, 12, 12, 4);
ctx.fillRect(12, 16, 8, 2);
canvas.refresh();
console.log('✅ Merchant Sprite Created!');
}
catch (error) {
console.error('❌ ERROR creating merchant sprite:', error);
}
}
static createCloudSprite(scene, key = 'cloud') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 64, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 64, 32);
ctx.fillStyle = 'rgba(255,255,255,0.6)';
ctx.beginPath(); ctx.arc(20, 20, 15, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(35, 15, 18, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(50, 20, 12, 0, Math.PI * 2); ctx.fill();
canvas.refresh();
}
static createCropSprite(scene, key, stage = 4) {
if (scene.textures.exists(key)) scene.textures.remove(key); // FORCE REFRESH to see updates
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Improved Wheat Visuals
const startY = 32;
// 1. Stems (Green -> Yellowish)
ctx.fillStyle = (stage < 3) ? '#32CD32' : '#DAA520';
const h = stage * 6;
// Draw distinct stalks
ctx.fillRect(10, startY - h, 2, h); // Left stalk
ctx.fillRect(16, startY - h, 2, h); // Center stalk
ctx.fillRect(22, startY - h, 2, h); // Right stalk
// 2. Heads (Wheat ears) - Stage 3 & 4
if (stage >= 3) {
ctx.fillStyle = '#FFD700'; // Gold
// Left head
ctx.beginPath(); ctx.ellipse(11, startY - h, 3, 5, -0.2, 0, Math.PI * 2); ctx.fill();
// Center head
ctx.beginPath(); ctx.ellipse(17, startY - h - 2, 3, 6, 0, 0, Math.PI * 2); ctx.fill();
// Right head
ctx.beginPath(); ctx.ellipse(23, startY - h, 3, 5, 0.2, 0, Math.PI * 2); ctx.fill();
}
// 3. Withered
if (stage === 5) {
ctx.fillStyle = '#8B4513';
ctx.fillRect(10, 24, 14, 8); // Dead pile
}
canvas.refresh();
}
static createStructureSprite(scene, key, type) {
if (scene.textures.exists(key)) return;
const width = (type === 'house' || type === 'ruin') ? 64 : 32;
const height = (type === 'house' || type === 'ruin') ? 64 : 32;
const canvas = scene.textures.createCanvas(key, width, height);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, width, height);
if (type === 'ruin') {
// Isometric Ruin / Rocks for user
ctx.fillStyle = '#696969'; // DimGray
// Big Rock 1
ctx.beginPath(); ctx.arc(20, 50, 14, 0, Math.PI * 2); ctx.fill();
// Big Rock 2
ctx.beginPath(); ctx.arc(45, 55, 12, 0, Math.PI * 2); ctx.fill();
// Details
ctx.fillStyle = '#555555';
ctx.beginPath(); ctx.arc(25, 45, 6, 0, Math.PI * 2); ctx.fill();
} else if (type === 'house' || type === 'house_lv2') {
// --- ISOMETRIC HOUSE ---
const isLv2 = (type === 'house_lv2');
// Walls
const wallColor = isLv2 ? '#A0522D' : '#8B4513'; // Lv2 is lighter/refined
ctx.fillStyle = wallColor;
ctx.fillRect(10, 24, 44, 32);
// Roof (Triangle/Pyramid-ish)
const roofColor = isLv2 ? '#8B0000' : '#4682B4'; // Lv2 Red Roof, Lv1 Blue
ctx.fillStyle = roofColor;
ctx.beginPath();
ctx.moveTo(32, 2); // Top
ctx.lineTo(8, 24); // Left
ctx.lineTo(56, 24); // Right
ctx.fill();
// Door
ctx.fillStyle = '#5C4033'; // Dark Wood
ctx.fillRect(26, 40, 12, 16);
// Windows
ctx.fillStyle = '#87CEEB'; // SkyBlue
ctx.fillRect(14, 34, 8, 8); // Window 1
ctx.fillRect(42, 34, 8, 8); // Window 2
// Lv2 Extras: Chimney or extra floor indicator
if (isLv2) {
ctx.fillStyle = '#555';
ctx.fillRect(40, 10, 6, 12); // Chimney
// Second floor window
ctx.fillStyle = '#87CEEB';
ctx.beginPath(); ctx.arc(32, 16, 4, 0, Math.PI * 2); ctx.fill();
}
} else if (name === 'stable') {
// Stable
ctx.fillStyle = '#8B4513'; // Wood
ctx.fillRect(0, 16, 32, 16);
ctx.fillStyle = '#A0522D'; // Roof
ctx.beginPath();
ctx.moveTo(0, 16); ctx.lineTo(16, 0); ctx.lineTo(32, 16);
ctx.fill();
// Door
ctx.fillStyle = '#000';
ctx.fillRect(10, 20, 12, 12);
} else {
// Generic box for others
ctx.fillStyle = '#8B4513';
ctx.fillRect(0, 0, width, height);
}
canvas.refresh();
}
// ========== 3D VOLUMETRIC GENERATORS (RESTORED) ==========
// Generiraj 3D volumetric tree (Minecraft-style)
static createTreeSprite(scene, key = 'tree') {
if (scene.textures.exists(key)) return;
const size = 64;
const height = 96; // Taller for 3D effect
const canvas = scene.textures.createCanvas(key, size, height);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, size, height);
// Helper to draw isometric-ish cube face
const drawCube = (x, y, w, h, d, colorTop, colorSide, colorFront) => {
// Front face
ctx.fillStyle = colorFront;
ctx.fillRect(x, y + d, w, h);
// Top face (fake perspective)
ctx.fillStyle = colorTop;
ctx.beginPath();
ctx.moveTo(x, y + d);
ctx.lineTo(x + d, y);
ctx.lineTo(x + w + d, y);
ctx.lineTo(x + w, y + d);
ctx.closePath();
ctx.fill();
// Side face
ctx.fillStyle = colorSide;
ctx.beginPath();
ctx.moveTo(x + w, y + d);
ctx.lineTo(x + w + d, y);
ctx.lineTo(x + w + d, y + h);
ctx.lineTo(x + w, y + h + d);
ctx.closePath();
ctx.fill();
};
// Trunk
const trunkColor = '#8B4513';
const trunkTop = '#A0522D';
const trunkDark = '#663300';
drawCube(24, 60, 16, 24, 8, trunkTop, trunkDark, trunkColor);
// Leaves chunks (Minecraft style)
const leafColor = '#228B22'; // ForestGreen
const leafTop = '#32CD32'; // LimeGreen
const leafDark = '#006400'; // DarkGreen
// Bottom layer
drawCube(12, 30, 40, 20, 10, leafTop, leafDark, leafColor);
// Top layer
drawCube(20, 10, 24, 20, 8, leafTop, leafDark, leafColor);
canvas.refresh();
}
// Generiraj 3D volumetric Rock (Gray Cubes)
static createRockSprite(scene, key = 'rock') {
if (scene.textures.exists(key)) return;
const size = 48;
const canvas = scene.textures.createCanvas(key, size, size);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, size, size);
// Simple Voxel Draw
const drawVoxel = (x, y, c) => {
ctx.fillStyle = c;
ctx.fillRect(x, y, 10, 10);
ctx.fillStyle = '#444444'; // Side
ctx.fillRect(x + 10, y, 4, 10);
ctx.fillStyle = '#333333'; // Bottom
ctx.fillRect(x, y + 10, 10, 4);
};
const gray = '#808080';
drawVoxel(10, 25, gray);
drawVoxel(20, 20, gray);
drawVoxel(15, 15, gray);
canvas.refresh();
}
// Generiraj 3D flower (simple volumetric)
static createFlowerSprite(scene, key = 'flower') {
if (scene.textures.exists(key)) return;
const size = 32;
const canvas = scene.textures.createCanvas(key, size, size);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, size, size);
ctx.fillStyle = '#228B22'; // Stem
ctx.fillRect(15, 10, 2, 10);
ctx.fillStyle = '#FF69B4'; // Flower
ctx.fillRect(12, 8, 8, 8);
canvas.refresh();
}
static createBushSprite(scene, key = 'bush') {
if (scene.textures.exists(key)) return;
const size = 32;
const canvas = scene.textures.createCanvas(key, size, size);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, size, size);
ctx.fillStyle = '#228B22';
ctx.beginPath(); ctx.arc(16, 16, 12, 0, Math.PI * 2); ctx.fill();
ctx.fillStyle = 'red'; // Berries
ctx.beginPath(); ctx.arc(12, 12, 2, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(20, 18, 2, 0, Math.PI * 2); ctx.fill();
canvas.refresh();
}
static createGravestoneSprite(scene, key = 'gravestone') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 48, 64);
const ctx = canvas.getContext();
// Clear with transparency
ctx.clearRect(0, 0, 48, 64);
// Stone base (darker gray)
ctx.fillStyle = '#4A4A4A';
ctx.fillRect(14, 52, 20, 8); // Base platform
// Main gravestone body (gray stone)
ctx.fillStyle = '#707070';
ctx.fillRect(16, 24, 16, 28); // Tall rectangle
// Rounded top
ctx.beginPath();
ctx.arc(24, 24, 8, Math.PI, 0, false);
ctx.fill();
// Moss/weathering effect (dark green patches)
ctx.fillStyle = '#2D5016';
ctx.fillRect(17, 30, 3, 4);
ctx.fillRect(28, 35, 2, 3);
ctx.fillRect(19, 45, 4, 3);
// Cracks (dark lines)
ctx.fillStyle = '#3A3A3A';
ctx.fillRect(20, 28, 1, 10); // Vertical crack
ctx.fillRect(27, 32, 1, 8);
// Cross/RIP symbol (lighter gray)
ctx.fillStyle = '#909090';
// Vertical bar
ctx.fillRect(23, 32, 2, 8);
// Horizontal bar
ctx.fillRect(21, 34, 6, 2);
// Shadow (semi-transparent black)
ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
ctx.ellipse(24, 60, 10, 3, 0, 0, Math.PI * 2);
ctx.fill();
canvas.refresh();
}
static createFenceSprite(scene, key = 'fence_full') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 48, 48);
const ctx = canvas.getContext();
// Clear with transparency
ctx.clearRect(0, 0, 48, 48);
// Wood color (brown)
const woodDark = '#6B4423';
const woodLight = '#8B5A3C';
// Vertical posts (3 posts)
for (let i = 0; i < 3; i++) {
const x = 8 + i * 16;
// Main post
ctx.fillStyle = woodLight;
ctx.fillRect(x, 8, 6, 32);
// Dark side (shading)
ctx.fillStyle = woodDark;
ctx.fillRect(x + 5, 8, 1, 32);
// Top point (fence picket style)
ctx.fillStyle = woodLight;
ctx.beginPath();
ctx.moveTo(x, 8);
ctx.lineTo(x + 3, 4);
ctx.lineTo(x + 6, 8);
ctx.fill();
}
// Horizontal planks (2 planks)
ctx.fillStyle = woodLight;
ctx.fillRect(4, 16, 40, 4); // Top plank
ctx.fillRect(4, 28, 40, 4); // Bottom plank
// Plank shading
ctx.fillStyle = woodDark;
ctx.fillRect(4, 19, 40, 1); // Top plank shadow
ctx.fillRect(4, 31, 40, 1); // Bottom plank shadow
// Wood grain (subtle lines)
ctx.fillStyle = 'rgba(107, 68, 35, 0.3)';
for (let i = 0; i < 3; i++) {
const x = 8 + i * 16;
ctx.fillRect(x + 1, 10, 1, 25);
ctx.fillRect(x + 3, 12, 1, 20);
}
canvas.refresh();
}
static createChestSprite(scene, key = 'chest') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Chest body (brown)
ctx.fillStyle = '#8B4513'; // SaddleBrown
ctx.fillRect(6, 12, 20, 16);
// Lock (gold)
ctx.fillStyle = '#FFD700';
ctx.fillRect(14, 18, 4, 6);
// Lid
ctx.fillStyle = '#A0522D';
ctx.fillRect(6, 8, 20, 4);
canvas.refresh();
}
static createSpawnerSprite(scene, key = 'spawner') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Dark portal/spawner
ctx.fillStyle = '#2F4F4F'; // DarkSlateGray
ctx.fillRect(8, 8, 16, 16);
// Red glow
ctx.fillStyle = '#8B0000';
ctx.fillRect(10, 10, 12, 12);
// Center black hole
ctx.fillStyle = '#000000';
ctx.beginPath();
ctx.arc(16, 16, 4, 0, Math.PI * 2);
ctx.fill();
canvas.refresh();
}
static createSignpostSprite(scene, key = 'signpost', text = '→') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Wooden post (brown)
ctx.fillStyle = '#8B4513';
ctx.fillRect(14, 8, 4, 24);
// Sign board
ctx.fillStyle = '#D2691E';
ctx.fillRect(6, 10, 20, 12);
// Border
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.strokeRect(6, 10, 20, 12);
// Text
ctx.fillStyle = '#000';
ctx.font = 'bold 14px Courier';
ctx.textAlign = 'center';
ctx.fillText(text, 16, 19);
canvas.refresh();
}
static createToolSprites(scene) {
// --- 3D VOXEL TOOLS ---
const refresh = (key) => {
if (scene.textures.exists(key)) scene.textures.remove(key);
const c = scene.textures.createCanvas(key, 32, 32);
const ctx = c.getContext();
ctx.clearRect(0, 0, 32, 32);
return { c, ctx };
};
// Helper: Draw 3D Pixel/Block
const drawBlock = (ctx, x, y, color) => {
ctx.fillStyle = color;
ctx.fillRect(x, y, 2, 2); // Front
ctx.fillStyle = 'rgba(0,0,0,0.3)'; // Side shadow
ctx.fillRect(x + 2, y, 1, 2);
ctx.fillRect(x, y + 2, 3, 1);
};
// 1. AXE (3D)
{
const { c, ctx } = refresh('item_axe');
// Handle
for (let i = 0; i < 8; i++) drawBlock(ctx, 12 + i, 20 - i * 2, '#8B4513');
// Head
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 4; y++) {
drawBlock(ctx, 18 + x * 2, 6 + y * 2, '#708090'); // Gray Metal
}
}
drawBlock(ctx, 24, 8, '#C0C0C0'); // Edge
drawBlock(ctx, 24, 10, '#C0C0C0');
c.refresh();
}
// 2. PICKAXE (3D)
{
const { c, ctx } = refresh('item_pickaxe');
// Handle
for (let i = 0; i < 8; i++) drawBlock(ctx, 14, 8 + i * 2, '#8B4513');
// Head (Arc)
drawBlock(ctx, 6, 10, '#696969');
drawBlock(ctx, 8, 8, '#696969');
drawBlock(ctx, 10, 6, '#696969');
drawBlock(ctx, 12, 6, '#696969');
drawBlock(ctx, 14, 6, '#696969'); // Center
drawBlock(ctx, 16, 6, '#696969');
drawBlock(ctx, 18, 6, '#696969');
drawBlock(ctx, 20, 8, '#696969');
drawBlock(ctx, 22, 10, '#696969');
c.refresh();
}
// 3. HOE (3D)
{
const { c, ctx } = refresh('item_hoe');
// Handle
for (let i = 0; i < 9; i++) drawBlock(ctx, 14 + i, 4 + i * 2, '#8B4513');
// Head
drawBlock(ctx, 12, 4, '#778899');
drawBlock(ctx, 14, 4, '#778899');
drawBlock(ctx, 16, 6, '#778899');
drawBlock(ctx, 16, 8, '#778899'); // Blade
c.refresh();
}
// 4. SWORD (3D)
{
const { c, ctx } = refresh('item_sword');
// Handle
drawBlock(ctx, 14, 24, '#8B4513');
drawBlock(ctx, 14, 26, '#8B4513');
// Guard
drawBlock(ctx, 10, 22, '#FFD700');
drawBlock(ctx, 12, 22, '#FFD700');
drawBlock(ctx, 14, 22, '#FFD700');
drawBlock(ctx, 16, 22, '#FFD700');
drawBlock(ctx, 18, 22, '#FFD700');
// Blade
for (let i = 0; i < 8; i++) drawBlock(ctx, 14, 6 + i * 2, '#C0C0C0');
c.refresh();
}
// 5. WATERING CAN (3D)
{
const { c, ctx } = refresh('item_watering_can');
// Body 3x3 blocks
for (let x = 0; x < 4; x++)
for (let y = 0; y < 3; y++)
drawBlock(ctx, 10 + x * 2, 14 + y * 2, '#A9A9A9');
// Spout
drawBlock(ctx, 18, 12, '#A9A9A9');
drawBlock(ctx, 20, 10, '#A9A9A9');
// Handle
drawBlock(ctx, 8, 12, '#696969');
drawBlock(ctx, 8, 10, '#696969');
drawBlock(ctx, 10, 8, '#696969');
c.refresh();
}
// 6. BUCKET (Empty)
{
const { c, ctx } = refresh('item_bucket');
// Body
drawBlock(ctx, 12, 14, '#C0C0C0');
drawBlock(ctx, 14, 14, '#C0C0C0');
drawBlock(ctx, 16, 14, '#C0C0C0');
drawBlock(ctx, 11, 12, '#C0C0C0');
drawBlock(ctx, 17, 12, '#C0C0C0');
drawBlock(ctx, 10, 10, '#C0C0C0');
drawBlock(ctx, 18, 10, '#C0C0C0');
// Handle
ctx.fillStyle = '#696969';
ctx.fillRect(10, 6, 12, 2);
c.refresh();
}
// 7. BUCKET_MILK
{
const { c, ctx } = refresh('item_bucket_milk');
// Body (Same as bucket)
drawBlock(ctx, 12, 14, '#C0C0C0');
drawBlock(ctx, 14, 14, '#C0C0C0');
drawBlock(ctx, 16, 14, '#C0C0C0');
drawBlock(ctx, 11, 12, '#C0C0C0');
drawBlock(ctx, 17, 12, '#C0C0C0');
// Milk Content
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(12, 10, 8, 4);
c.refresh();
}
// 8. BUCKET_MILK_GLOWING
{
const { c, ctx } = refresh('item_bucket_milk_glowing');
// Body
drawBlock(ctx, 12, 14, '#C0C0C0');
drawBlock(ctx, 14, 14, '#C0C0C0');
drawBlock(ctx, 16, 14, '#C0C0C0');
drawBlock(ctx, 11, 12, '#C0C0C0');
drawBlock(ctx, 17, 12, '#C0C0C0');
// Glowing Milk Content
ctx.fillStyle = '#00FF00';
ctx.fillRect(12, 10, 8, 4);
c.refresh();
}
}
static createItemSprites(scene) {
// Placeholder item generation
const items = [
{ name: 'wood', color: '#8B4513' }, // Rjava
{ name: 'stone', color: '#808080' }, // Siva
{ name: 'seeds', color: '#90EE90' }, // Svetlo zelena
{ name: 'wheat', color: '#FFD700' }, // Zlata
{ name: 'corn', color: '#FFD700' }, // Zlata (Corn)
{ name: 'seeds_corn', color: '#B22222' },// FireBrick seeds
{ name: 'item_bone', color: '#F5F5DC' }, // Beige
{ name: 'item_scrap', color: '#B87333' }, // Copper/Bronze (kovinski kos)
{ name: 'item_chip', color: '#00CED1' }, // DarkTurquoise (elektronski chip)
{ name: 'artefact_old', color: '#8B4513' }, // Ancient Pot (Brown)
{ name: 'milk', color: '#FFFFFF' }, // White
{ name: 'glowing_milk', color: '#00FF00' }, // Green
{ name: 'animal_feed', color: '#F4A460' }, // Sandy Brown (Feed)
{ name: 'cannabis', color: '#228B22' }, // Green
{ name: 'cannabis_seeds', color: '#55ff55' }, // Lighter Green
{ name: 'hemp_fiber', color: '#DEB887' }, // Tan/Beige
{ name: 'hemp_clothing', color: '#2E8B57' } // SeaGreen
];
items.forEach(item => {
const it = typeof item === 'string' ? item : item.name;
const color = typeof item === 'string' ? 'gold' : item.color;
const k = (it.startsWith('item_')) ? it : 'item_' + it;
if (scene.textures.exists(k)) scene.textures.remove(k); // FORCE REFRESH
const c = scene.textures.createCanvas(k, 32, 32);
const x = c.getContext();
x.clearRect(0, 0, 32, 32);
// SPECIAL ICONS
if (it === 'corn') {
// Corn Cob
x.fillStyle = '#228B22'; // Husk
x.beginPath(); x.ellipse(16, 16, 6, 12, 0, 0, Math.PI * 2); x.fill();
x.fillStyle = '#FFD700'; // Kernels
x.beginPath(); x.ellipse(16, 16, 3, 8, 0, 0, Math.PI * 2); x.fill();
}
else if (it === 'wheat') {
// Wheat Sheaf
x.strokeStyle = '#FFD700';
x.lineWidth = 2;
x.beginPath();
x.moveTo(12, 28); x.lineTo(20, 4); // Stalk 1
x.moveTo(16, 28); x.lineTo(16, 4); // Stalk 2
x.moveTo(20, 28); x.lineTo(12, 4); // Stalk 3
x.stroke();
// Tie
x.fillStyle = '#DAA520';
x.fillRect(13, 22, 6, 3);
}
else if (it === 'cannabis') {
// Cannabis Leaf (Stylized)
x.fillStyle = '#228B22';
// Center leaf
x.beginPath(); x.ellipse(16, 12, 3, 10, 0, 0, Math.PI * 2); x.fill();
// Side leaves
x.beginPath(); x.ellipse(10, 16, 3, 8, -Math.PI / 4, 0, Math.PI * 2); x.fill();
x.beginPath(); x.ellipse(22, 16, 3, 8, Math.PI / 4, 0, Math.PI * 2); x.fill();
x.beginPath(); x.ellipse(10, 24, 3, 6, -Math.PI / 2.5, 0, Math.PI * 2); x.fill();
x.beginPath(); x.ellipse(22, 24, 3, 6, Math.PI / 2.5, 0, Math.PI * 2); x.fill();
}
else if (it.includes('seeds')) {
// Seed Bag
x.fillStyle = '#DEB887'; // Burlywood bag
x.beginPath();
x.moveTo(10, 8); x.lineTo(22, 8); // Top
x.lineTo(26, 26); x.lineTo(6, 26); // Bottom
x.fill();
// Label/Dots
x.fillStyle = color;
x.beginPath(); x.arc(16, 18, 4, 0, Math.PI * 2); x.fill();
}
else if (it === 'cannabis_buds') {
// Stylized "bud" (forest green clusters)
x.fillStyle = '#228B22';
for (let i = 0; i < 5; i++) {
const ang = (i / 5) * Math.PI * 2;
x.beginPath();
x.arc(16 + Math.cos(ang) * 6, 16 + Math.sin(ang) * 6, 5, 0, Math.PI * 2);
x.fill();
}
x.fillStyle = '#8FBC8F'; // Frosted look
x.beginPath(); x.arc(16, 16, 4, 0, Math.PI * 2); x.fill();
}
else if (it === 'hemp_fiber') {
// Bundle of fibers (tan/straw color)
x.strokeStyle = '#DEB887';
x.lineWidth = 2;
for (let i = 0; i < 5; i++) {
x.beginPath();
x.moveTo(10 + i * 3, 24);
x.quadraticCurveTo(16, 16, 10 + (4 - i) * 3, 8);
x.stroke();
}
// Tie
x.fillStyle = '#8B4513';
x.fillRect(10, 15, 12, 2);
}
else if (it === 'hemp_clothing') {
// Simple T-shirt shape
x.fillStyle = '#2E8B57'; // SeaGreen
x.fillRect(8, 10, 16, 18); // Body
x.fillRect(4, 10, 6, 8); // Left sleeve
x.fillRect(22, 10, 6, 8); // Right sleeve
// Collar
x.fillStyle = '#000';
x.beginPath(); x.arc(16, 10, 4, 0, Math.PI); x.fill();
}
else {
// Default Circle
x.fillStyle = color;
x.beginPath(); x.arc(16, 16, 10, 0, Math.PI * 2); x.fill();
}
c.refresh();
});
}
static createSaplingSprite(scene, key = 'tree_sapling') {
if (scene.textures.exists(key)) return;
const size = 32;
const canvas = scene.textures.createCanvas(key, size, size);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, size, size);
// Majhno steblo
ctx.fillStyle = '#8B4513';
ctx.fillRect(14, 20, 4, 12);
// Parnosti listov
ctx.fillStyle = '#32CD32';
ctx.beginPath(); ctx.arc(12, 18, 4, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(20, 18, 4, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(16, 12, 5, 0, Math.PI * 2); ctx.fill();
canvas.refresh();
}
static createCornSprites(scene) {
for (let i = 1; i <= 4; i++) {
const key = `corn_stage_${i}`;
if (scene.textures.exists(key)) continue;
// Corn is taller
const canvas = scene.textures.createCanvas(key, 32, 64);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 64);
const startY = 64;
// Stalk
ctx.fillStyle = '#556B2F'; // DarkOliveGreen
const height = 10 + (i * 10);
ctx.fillRect(14, startY - height, 4, height);
// Leaves
ctx.fillStyle = '#32CD32'; // LimeGreen
if (i >= 2) {
ctx.beginPath(); ctx.ellipse(10, startY - height + 10, 8, 3, 0.5, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.ellipse(22, startY - height + 15, 8, 3, -0.5, 0, Math.PI * 2); ctx.fill();
}
// Cobs (Only stage 4)
if (i === 4) {
ctx.fillStyle = '#FFD700'; // Gold
ctx.fillRect(12, startY - height + 20, 4, 8);
ctx.fillRect(18, startY - height + 25, 4, 8);
}
canvas.refresh();
}
}
// Helper to generate ALL textures at once
generateAll() {
TextureGenerator.createPlayerSprite(this.scene);
TextureGenerator.createPlayerWalkSprite(this.scene);
TextureGenerator.createNPCSprite(this.scene, 'npc', 'zombie');
TextureGenerator.createMerchantSprite(this.scene, 'merchant_texture');
TextureGenerator.createFlowerSprite(this.scene);
TextureGenerator.createBushSprite(this.scene);
TextureGenerator.createSaplingSprite(this.scene, 'tree_sapling');
TextureGenerator.createTreeSprite(this.scene);
TextureGenerator.createRockSprite(this.scene);
TextureGenerator.createCloudSprite(this.scene);
// Crops
TextureGenerator.createCropSprite(this.scene, 'crop_stage_1', 1);
TextureGenerator.createCropSprite(this.scene, 'crop_stage_2', 2);
TextureGenerator.createCropSprite(this.scene, 'crop_stage_3', 3);
TextureGenerator.createCropSprite(this.scene, 'crop_stage_4', 4);
TextureGenerator.createCornSprites(this.scene); // Added Corn
TextureGenerator.createGravestoneSprite(this.scene);
TextureGenerator.createFenceSprite(this.scene); // Procedural fence with transparency
TextureGenerator.createToolSprites(this.scene);
TextureGenerator.createItemSprites(this.scene);
TextureGenerator.createScooterSprite(this.scene, 'scooter', false);
TextureGenerator.createBoatSprite(this.scene, 'boat');
TextureGenerator.createScooterSprite(this.scene, 'scooter_broken', true);
TextureGenerator.createAnimatedWaterSprite(this.scene);
TextureGenerator.createPathStoneSprite(this.scene, 'path_stone');
TextureGenerator.createSmallRockSprite(this.scene, 'small_rock_1');
TextureGenerator.createSmallRockSprite(this.scene, 'small_rock_2');
TextureGenerator.createFlowerVariant(this.scene, 'flower_red', '#FF4444');
TextureGenerator.createFlowerVariant(this.scene, 'flower_yellow', '#FFFF44');
TextureGenerator.createFlowerVariant(this.scene, 'flower_blue', '#4444FF');
TextureGenerator.createMushroomSprite(this.scene, 'mushroom_red', '#FF4444', '#FFFFFF');
TextureGenerator.createMushroomSprite(this.scene, 'mushroom_brown', '#8B4513', '#FFE4C4');
TextureGenerator.createFallenLogSprite(this.scene, 'fallen_log');
TextureGenerator.createPuddleSprite(this.scene, 'puddle');
TextureGenerator.createFurnaceSprite(this.scene, 'furnace');
TextureGenerator.createMintSprite(this.scene, 'mint');
TextureGenerator.createOwlSprite(this.scene, 'owl');
TextureGenerator.createBatSprite(this.scene, 'bat');
// Structures (Fix checkered pattern bug)
TextureGenerator.createChestSprite(this.scene, 'chest');
TextureGenerator.createSpawnerSprite(this.scene, 'spawner');
TextureGenerator.createStructureSprite(this.scene, 'ruin', 'ruin');
TextureGenerator.createStructureSprite(this.scene, 'arena', 'ruin');
TextureGenerator.createSignpostSprite(this.scene, 'signpost_city', '→');
TextureGenerator.createSignpostSprite(this.scene, 'signpost_farm', '←');
TextureGenerator.createSignpostSprite(this.scene, 'signpost_both', '⇅');
// Mutants
TextureGenerator.createTrollSprite(this.scene, 'troll');
TextureGenerator.createElfSprite(this.scene, 'elf');
// Animals
TextureGenerator.createCowSprite(this.scene, 'cow', false);
TextureGenerator.createCowSprite(this.scene, 'cow_mutant', true);
TextureGenerator.createChickenSprite(this.scene, 'chicken', false);
TextureGenerator.createChickenSprite(this.scene, 'chicken_mutant', true);
// Villager
TextureGenerator.createVillagerSprite(this.scene, 'villager');
}
static createOwlSprite(scene, key = 'owl') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Body
ctx.fillStyle = '#8B4513'; // SaddleBrown
ctx.fillRect(8, 8, 16, 20);
// Eyes
ctx.fillStyle = '#FFD700'; // Gold eyes
ctx.beginPath(); ctx.arc(12, 12, 3, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(20, 12, 3, 0, Math.PI * 2); ctx.fill();
// Pupils
ctx.fillStyle = '#000';
ctx.beginPath(); ctx.arc(12, 12, 1, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(20, 12, 1, 0, Math.PI * 2); ctx.fill();
// Beak
ctx.fillStyle = '#FFA500'; // Orange
ctx.beginPath();
ctx.moveTo(16, 14); ctx.lineTo(14, 18); ctx.lineTo(18, 18);
ctx.fill();
// Wings (folded)
ctx.fillStyle = '#A0522D';
ctx.fillRect(6, 12, 4, 12);
ctx.fillRect(22, 12, 4, 12);
canvas.refresh();
}
static createBatSprite(scene, key = 'bat') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Body
ctx.fillStyle = '#222';
ctx.beginPath(); ctx.ellipse(16, 16, 4, 6, 0, 0, Math.PI * 2); ctx.fill();
// Wings
ctx.fillStyle = '#333';
// Left Wing
ctx.beginPath();
ctx.moveTo(12, 16); ctx.lineTo(2, 6); ctx.lineTo(4, 20);
ctx.closePath(); ctx.fill();
// Right Wing
ctx.beginPath();
ctx.moveTo(20, 16); ctx.lineTo(30, 6); ctx.lineTo(28, 20);
ctx.closePath(); ctx.fill();
// Eyes
ctx.fillStyle = '#f00';
ctx.fillRect(15, 14, 1, 1);
ctx.fillRect(17, 14, 1, 1);
canvas.refresh();
}
static createTrollSprite(scene, key) {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 48, 48); // Bigger
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 48, 48);
// Body (Big, Green)
ctx.fillStyle = '#228B22'; // ForestGreen
ctx.fillRect(10, 10, 28, 30);
// Head
ctx.fillStyle = '#105510';
ctx.fillRect(14, 4, 20, 16);
// Eyes (Red)
ctx.fillStyle = '#ff0000';
ctx.fillRect(18, 10, 4, 4);
ctx.fillRect(26, 10, 4, 4);
// Club
ctx.fillStyle = '#5c4033';
ctx.fillRect(36, 12, 8, 24);
canvas.refresh();
}
static createElfSprite(scene, key) {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 48);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 48);
// Body (Slim, Pale)
ctx.fillStyle = '#98FB98'; // PaleGreen (Mutated Elf)
ctx.fillRect(10, 16, 12, 24);
// Head
ctx.fillStyle = '#E0FFFF'; // LightCyan
ctx.fillRect(10, 4, 12, 12);
// Ears (Pointy)
ctx.fillStyle = '#E0FFFF';
ctx.beginPath(); ctx.moveTo(8, 8); ctx.lineTo(4, 4); ctx.lineTo(10, 12); ctx.fill();
ctx.beginPath(); ctx.moveTo(24, 8); ctx.lineTo(28, 4); ctx.lineTo(22, 12); ctx.fill();
// Eyes (Glowing)
ctx.fillStyle = '#00FFFF';
ctx.fillRect(12, 8, 2, 2);
ctx.fillRect(18, 8, 2, 2);
canvas.refresh();
}
static createCowSprite(scene, key, activeMutation) {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 48, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 48, 32);
// Body
ctx.fillStyle = activeMutation ? '#9ACD32' : '#FFFFFF'; // YellowGreen or White
ctx.fillRect(8, 10, 32, 16);
// Spots (if normal)
if (!activeMutation) {
ctx.fillStyle = '#000000';
ctx.fillRect(14, 12, 6, 6);
ctx.fillRect(28, 18, 8, 4);
} else {
// Glowing veins
ctx.fillStyle = '#00FF00';
ctx.fillRect(12, 14, 24, 2);
}
// Head
ctx.fillStyle = activeMutation ? '#9ACD32' : '#FFFFFF';
ctx.fillRect(0, 8, 12, 12);
// Legs
ctx.fillStyle = '#000000';
ctx.fillRect(10, 26, 4, 6);
ctx.fillRect(34, 26, 4, 6);
canvas.refresh();
}
static createBoatSprite(scene, key = 'boat') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 48, 24);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 48, 24);
// Hull (Wood)
ctx.fillStyle = '#8B4513';
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(48, 0);
ctx.lineTo(40, 24);
ctx.lineTo(8, 24);
ctx.closePath();
ctx.fill();
// Rim
ctx.strokeStyle = '#603010';
ctx.lineWidth = 2;
ctx.strokeRect(2, 2, 44, 20);
// Seat
ctx.fillStyle = '#603010';
ctx.fillRect(16, 8, 16, 4);
canvas.refresh();
}
static createChickenSprite(scene, key, activeMutation) {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 24, 24);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 24, 24);
// Body
ctx.fillStyle = activeMutation ? '#ADFF2F' : '#FFFFFF'; // GreenYellow or White
ctx.beginPath(); ctx.arc(12, 14, 8, 0, Math.PI * 2); ctx.fill();
// Head
ctx.beginPath(); ctx.arc(16, 8, 5, 0, Math.PI * 2); ctx.fill();
// Beak
ctx.fillStyle = '#ffaa00';
ctx.beginPath(); ctx.moveTo(20, 8); ctx.lineTo(24, 10); ctx.lineTo(20, 12); ctx.fill();
// Comb
ctx.fillStyle = '#ff0000';
ctx.fillRect(15, 3, 2, 3);
canvas.refresh();
}
static createPathStoneSprite(scene, key = 'path_stone') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Flat stone for paths
ctx.fillStyle = '#888888';
ctx.beginPath();
ctx.ellipse(16, 20, 12, 8, 0, 0, Math.PI * 2);
ctx.fill();
// Cracks/Details
ctx.strokeStyle = '#666666';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(10, 18);
ctx.lineTo(22, 18);
ctx.stroke();
canvas.refresh();
}
static createSmallRockSprite(scene, key) {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 24, 24);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 24, 24);
// Small rock pile
ctx.fillStyle = '#707070';
ctx.beginPath();
ctx.arc(12, 16, 6, 0, Math.PI * 2);
ctx.fill();
// Highlight
ctx.fillStyle = '#909090';
ctx.beginPath();
ctx.arc(10, 14, 3, 0, Math.PI * 2);
ctx.fill();
canvas.refresh();
}
static createFlowerVariant(scene, key, color) {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Stem
ctx.fillStyle = '#228B22';
ctx.fillRect(15, 16, 2, 10);
// Petals
ctx.fillStyle = color;
for (let i = 0; i < 5; i++) {
const angle = (i / 5) * Math.PI * 2;
const px = 16 + Math.cos(angle) * 4;
const py = 16 + Math.sin(angle) * 4;
ctx.beginPath();
ctx.arc(px, py, 3, 0, Math.PI * 2);
ctx.fill();
}
// Center
ctx.fillStyle = '#FFD700';
ctx.beginPath();
ctx.arc(16, 16, 2, 0, Math.PI * 2);
ctx.fill();
canvas.refresh();
}
static createMushroomSprite(scene, key, capColor, stemColor) {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 32);
// Stem
ctx.fillStyle = stemColor;
ctx.fillRect(13, 16, 6, 10);
// Cap (mushroom head)
ctx.fillStyle = capColor;
ctx.beginPath();
ctx.ellipse(16, 16, 10, 6, 0, 0, Math.PI * 2);
ctx.fill();
// Spots on cap (white dots)
ctx.fillStyle = '#FFFFFF';
for (let i = 0; i < 3; i++) {
const angle = (i / 3) * Math.PI * 2;
const px = 16 + Math.cos(angle) * 5;
const py = 16 + Math.sin(angle) * 3;
ctx.beginPath();
ctx.arc(px, py, 2, 0, Math.PI * 2);
ctx.fill();
}
canvas.refresh();
}
static createFallenLogSprite(scene, key = 'fallen_log') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 48, 32);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 48, 32);
// Log body (horizontal)
ctx.fillStyle = '#8B4513';
ctx.fillRect(4, 14, 40, 10);
// Bark texture
ctx.fillStyle = '#654321';
for (let i = 0; i < 5; i++) {
ctx.fillRect(6 + i * 8, 14, 2, 10);
}
// Log rings (ends)
ctx.fillStyle = '#D2691E';
ctx.beginPath();
ctx.arc(6, 19, 5, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = '#654321';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.arc(6, 19, 3, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.arc(6, 19, 1.5, 0, Math.PI * 2);
ctx.stroke();
// Small mushrooms growing on log
ctx.fillStyle = '#FF6347';
ctx.beginPath();
ctx.arc(20, 12, 3, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#FFE4C4';
ctx.fillRect(19, 13, 2, 3);
canvas.refresh();
}
static createPuddleSprite(scene, key = 'puddle') {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 32, 24);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 32, 24);
// Puddle shape (irregular oval)
ctx.fillStyle = 'rgba(70, 130, 180, 0.6)';
ctx.beginPath();
ctx.ellipse(16, 16, 12, 8, 0, 0, Math.PI * 2);
ctx.fill();
// Reflection highlights
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
ctx.beginPath();
ctx.ellipse(12, 14, 4, 2, 0, 0, Math.PI * 2);
ctx.fill();
// Darker edge
ctx.strokeStyle = 'rgba(30, 60, 90, 0.5)';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.ellipse(16, 16, 12, 8, 0, 0, Math.PI * 2);
ctx.stroke();
canvas.refresh();
}
static createScooterSprite(scene, key = 'scooter', isBroken = false) {
if (scene.textures.exists(key)) return;
const canvas = scene.textures.createCanvas(key, 48, 48);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, 48, 48);
const color = isBroken ? '#696969' : '#FF4500'; // Rusty Gray vs OrangeRed
const wheelColor = '#1a1a1a';
// Wheels
ctx.fillStyle = wheelColor;
ctx.beginPath(); ctx.arc(12, 38, 5, 0, Math.PI * 2); ctx.fill(); // Back
ctx.beginPath(); ctx.arc(38, 38, 5, 0, Math.PI * 2); ctx.fill(); // Front
// Spokes
ctx.fillStyle = '#555';
ctx.beginPath(); ctx.arc(12, 38, 2, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(38, 38, 2, 0, Math.PI * 2); ctx.fill();
// Base
ctx.fillStyle = color;
ctx.fillRect(12, 32, 26, 5); // Deck
// Angled Stem
ctx.beginPath();
ctx.moveTo(38, 34);
ctx.lineTo(34, 14);
ctx.lineTo(38, 14);
ctx.lineTo(42, 34);
ctx.closePath();
ctx.fill();
// Handlebars
ctx.strokeStyle = isBroken ? '#444' : '#C0C0C0';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(30, 14);
ctx.lineTo(42, 14);
ctx.stroke();
// Vertical post support
ctx.fillStyle = color;
ctx.fillRect(10, 30, 4, 4); // Rear wheel guard
if (isBroken) {
// Rust spots
ctx.fillStyle = '#8B4513';
ctx.fillRect(15, 33, 4, 2);
ctx.fillRect(35, 20, 2, 3);
}
canvas.refresh();
}
static createAnimatedWaterSprite(scene) {
// Create 4 separate textures for water animation frames
const frames = 4;
const frameWidth = 48;
const frameHeight = 60;
for (let f = 0; f < frames; f++) {
const key = `water_frame_${f}`;
if (scene.textures.exists(key)) continue;
const canvas = scene.textures.createCanvas(key, frameWidth, frameHeight);
const ctx = canvas.getContext();
ctx.clearRect(0, 0, frameWidth, frameHeight);
const P = 2;
const baseColor = 0x4444ff;
const shimmerOffset = Math.sin((f / frames) * Math.PI * 2) * 20;
const waterColor = Phaser.Display.Color.IntegerToColor(baseColor).lighten(shimmerOffset).color;
const xs = P;
const xe = 48 + P;
const midX = 24 + P;
const topY = P;
const midY = 12 + P;
const bottomY = 24 + P;
const depth = 20;
// Left Face
ctx.fillStyle = Phaser.Display.Color.IntegerToColor(waterColor).darken(30).rgba;
ctx.beginPath();
ctx.moveTo(midX, bottomY);
ctx.lineTo(midX, bottomY + depth);
ctx.lineTo(xs, midY + depth);
ctx.lineTo(xs, midY);
ctx.closePath();
ctx.fill();
// Right Face
ctx.fillStyle = Phaser.Display.Color.IntegerToColor(waterColor).darken(20).rgba;
ctx.beginPath();
ctx.moveTo(xe, midY);
ctx.lineTo(xe, midY + depth);
ctx.lineTo(midX, bottomY + depth);
ctx.lineTo(midX, bottomY);
ctx.closePath();
ctx.fill();
// Top Face
ctx.fillStyle = Phaser.Display.Color.IntegerToColor(waterColor).rgba;
ctx.beginPath();
ctx.moveTo(xs, midY);
ctx.lineTo(midX, topY);
ctx.lineTo(xe, midY);
ctx.lineTo(midX, bottomY);
ctx.closePath();
ctx.fill();
// Shimmer highlights
ctx.fillStyle = `rgba(255, 255, 255, ${0.1 + Math.abs(shimmerOffset) / 100})`;
for (let i = 0; i < 5; i++) {
const sx = xs + 8 + Math.random() * 28;
const sy = topY + 4 + Math.random() * 16;
ctx.fillRect(sx, sy, 3, 2);
}
// Wave lines
ctx.strokeStyle = `rgba(100, 100, 255, ${0.3 + (f / frames) * 0.2})`;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(xs + 10, midY + 8);
ctx.lineTo(xe - 10, midY - 2);
ctx.stroke();
canvas.refresh();
}
}
static createFurnaceSprite(scene, key = 'furnace') {
if (scene.textures.exists(key)) return;
const graphics = scene.make.graphics({ x: 0, y: 0, add: false });
// Furnace block (gray)
graphics.fillStyle(0x555555, 1);
graphics.fillRect(8, 14, 16, 18);
graphics.fillStyle(0x333333, 1);
graphics.fillRect(12, 22, 8, 6); // Hole
graphics.fillStyle(0xffaa00, 1);
graphics.fillRect(14, 24, 4, 3); // Embers
graphics.generateTexture(key, 32, 32);
}
static createMintSprite(scene, key = 'mint') {
if (scene.textures.exists(key)) return;
const graphics = scene.make.graphics({ x: 0, y: 0, add: false });
graphics.fillStyle(0x777799, 1); // Steel blue
graphics.fillRect(6, 12, 20, 20);
graphics.fillStyle(0xffd700, 1); // Gold coin icon
graphics.fillCircle(16, 18, 5);
graphics.generateTexture(key, 32, 32);
}
static createVillagerSprite(scene, key = 'villager') {
if (scene.textures.exists(key)) return;
const graphics = scene.make.graphics({ x: 0, y: 0, add: false });
// Farmer/Villager - simple human sprite
// Head (skin tone)
graphics.fillStyle(0xffdbac, 1);
graphics.fillCircle(16, 8, 4);
// Body (blue shirt)
graphics.fillStyle(0x4477bb, 1);
graphics.fillRect(12, 12, 8, 10);
// Arms
graphics.fillStyle(0xffdbac, 1);
graphics.fillRect(10, 14, 2, 6); // Left arm
graphics.fillRect(20, 14, 2, 6); // Right arm
// Pants (brown)
graphics.fillStyle(0x654321, 1);
graphics.fillRect(12, 22, 8, 8);
// Eyes
graphics.fillStyle(0x000000, 1);
graphics.fillRect(14, 7, 1, 1); // Left eye
graphics.fillRect(17, 7, 1, 1); // Right eye
graphics.generateTexture(key, 32, 32);
graphics.destroy();
}
constructor(scene) {
this.scene = scene;
}
}