From 4ccbdbc9fe95aac88cd446a4b0533ff73cb2a653 Mon Sep 17 00:00:00 2001 From: Till JS Date: Sun, 29 Mar 2026 15:14:32 +0200 Subject: [PATCH] fix(manavoxel): improve demo world with full ground coverage and better spawn - Fill entire area with grass (top-down needs ground everywhere, no AIR gaps) - Add cobblestone road with stone edges - Add dirt paths, sand area, market stalls, flower patches - 10 trees with trunk + leaf canopy scattered around - 3 distinct buildings: brick house, wood cabin, stone tower - Well with water in village center - Torches along road edges - Player spawns at center of road (200, 150) for better first impression - Camera default zoom reduced to 1.5x (was 2x) to show more of the village - Min zoom out to 0.3x for full overview - New seed ID (guest-world-002) to regenerate for existing users Co-Authored-By: Claude Opus 4.6 (1M context) --- .../apps/web/src/lib/data/guest-seed.ts | 149 +++++++++++++----- .../apps/web/src/lib/engine/camera.ts | 6 +- 2 files changed, 113 insertions(+), 42 deletions(-) diff --git a/apps/manavoxel/apps/web/src/lib/data/guest-seed.ts b/apps/manavoxel/apps/web/src/lib/data/guest-seed.ts index b513c198f..e96ceceeb 100644 --- a/apps/manavoxel/apps/web/src/lib/data/guest-seed.ts +++ b/apps/manavoxel/apps/web/src/lib/data/guest-seed.ts @@ -12,9 +12,9 @@ let cached: { worlds: LocalWorld[]; areas: LocalArea[]; items: LocalItem[] } | n export function generateGuestWorld() { if (cached) return cached; - const worldId = 'guest-world-001'; - const streetId = 'guest-street-001'; - const houseId = 'guest-house-001'; + const worldId = 'guest-world-002'; + const streetId = 'guest-street-002'; + const houseId = 'guest-house-002'; // ─── Street (50m × 30m at 10cm) ───────────────────────── @@ -25,47 +25,118 @@ export function generateGuestWorld() { for (let y = 0; y < streetH; y++) { for (let x = 0; x < streetW; x++) { - let mat = MATERIAL_AIR; + // Start with grass everywhere (top-down: everything needs a ground) + let mat = 3; // Grass - // Border - if (x === 0 || x === streetW - 1 || y === 0 || y === streetH - 1) mat = 1; - // Road - else if (y >= 130 && y <= 170) mat = 12; - // Grass patches - else if ((y > 170 || y < 130) && Math.random() < 0.25) mat = 3; - // House 1 (brick) - else if (x >= 40 && x <= 80 && y >= 40 && y <= 80) { - if (x === 40 || x === 80 || y === 40 || y === 80) mat = 8; - else if (y === 80 && x >= 56 && x <= 64) - mat = 0; // door - else if (y === 45 && (x === 50 || x === 55 || x === 65 || x === 70)) mat = 9; + // Stone border wall around the whole area + if (x <= 1 || x >= streetW - 2 || y <= 1 || y >= streetH - 2) { + mat = 1; // Stone wall } - // House 2 (wood) - else if (x >= 120 && x <= 180 && y >= 30 && y <= 90) { - if (x === 120 || x === 180 || y === 30 || y === 90) mat = 4; - else if (y === 90 && x >= 145 && x <= 155) mat = 0; - else if (y === 40 && (x === 135 || x === 150 || x === 165)) mat = 9; + // Cobblestone road (horizontal, center) + else if (y >= 120 && y <= 180) { + mat = 12; // Cobblestone + // Road edge markings + if (y === 120 || y === 180) mat = 1; } - // House 3 (stone) - else if (x >= 250 && x <= 310 && y >= 50 && y <= 100) { - if (x === 250 || x === 310 || y === 50 || y === 100) mat = 1; - else if (y === 100 && x >= 275 && x <= 285) mat = 0; + // Dirt path (vertical, connecting to road) + else if (x >= 148 && x <= 152 && y < 120) { + mat = 2; // Dirt } - // Well (center of village) - else if (Math.abs(x - 150) <= 4 && Math.abs(y - 150) <= 4) { - if (Math.abs(x - 150) === 4 || Math.abs(y - 150) === 4) mat = 12; - else mat = 7; // water + // Sand area (bottom right, like a beach/playground) + else if (x >= 350 && y >= 200 && x <= 450 && y <= 270) { + mat = 6; // Sand } - // Trees - else if (x === 350 && y >= 80 && y <= 95) mat = 4; - else if (Math.abs(x - 350) + Math.abs(y - 75) <= 7 && y < 82) mat = 13; - else if (x === 400 && y >= 100 && y <= 115) mat = 4; - else if (Math.abs(x - 400) + Math.abs(y - 95) <= 6 && y < 102) mat = 13; - // Torches - else if (y === 128 && x % 30 === 15) mat = 10; - else if (y === 172 && x % 30 === 15) mat = 10; - if (mat !== 0) streetView.setUint16((y * streetW + x) * 2, mat, true); + // ── Buildings (on top of ground) ── + + // House 1: Brick house (top-left area) + if (x >= 40 && x <= 90 && y >= 40 && y <= 90) { + if (x === 40 || x === 90 || y === 40 || y === 90) { + mat = 8; // Brick walls + } else { + mat = 5; // Plank floor inside + } + // Door (south wall) + if (y === 90 && x >= 60 && x <= 70) mat = 2; // Dirt (open door) + // Windows + if (y === 40 && (x === 55 || x === 75)) mat = 9; + } + + // House 2: Wood cabin (top-center) + if (x >= 130 && x <= 190 && y >= 35 && y <= 95) { + if (x === 130 || x === 190 || y === 35 || y === 95) { + mat = 4; // Wood walls + } else { + mat = 5; // Plank floor + } + if (y === 95 && x >= 155 && x <= 165) mat = 2; // Door + if (y === 35 && (x === 145 || x === 160 || x === 175)) mat = 9; // Windows + } + + // House 3: Stone tower (top-right) + if (x >= 260 && x <= 300 && y >= 50 && y <= 110) { + if (x === 260 || x === 300 || y === 50 || y === 110) { + mat = 1; // Stone walls + } else { + mat = 12; // Stone floor + } + if (y === 110 && x >= 275 && x <= 285) mat = 2; // Door + } + + // Well (center of village, on the road) + if (Math.abs(x - 250) <= 5 && Math.abs(y - 150) <= 5) { + if (Math.abs(x - 250) === 5 || Math.abs(y - 150) === 5) { + mat = 1; // Stone rim + } else { + mat = 7; // Water + } + } + + // Market stalls (south of road) + if (x >= 60 && x <= 80 && y >= 200 && y <= 215) { + if (y === 200) + mat = 4; // Wood counter + else if (y === 215 && (x === 60 || x === 80)) mat = 4; // Posts + } + if (x >= 120 && x <= 140 && y >= 200 && y <= 215) { + if (y === 200) mat = 4; + else if (y === 215 && (x === 120 || x === 140)) mat = 4; + } + + // ── Nature ── + + // Trees (scattered, on grass areas only) + const trees = [ + [30, 150], + [320, 80], + [380, 60], + [420, 140], + [350, 220], + [100, 250], + [200, 230], + [450, 90], + [20, 250], + [480, 200], + ]; + for (const [tx, ty] of trees) { + // Trunk + if (x === tx && y >= ty && y <= ty + 8) mat = 4; + // Leaves (diamond shape) + if (Math.abs(x - tx) + Math.abs(y - (ty - 3)) <= 6 && y < ty + 1 && y > ty - 8) { + mat = 13; + } + } + + // Flower patches + if (mat === 3 && (x + y * 7) % 47 === 0) { + mat = 10; // Yellow flowers (torch color = yellow) + } + + // Torches along the road + if (y === 119 && x % 25 === 12 && x > 5 && x < streetW - 5) mat = 10; + if (y === 181 && x % 25 === 12 && x > 5 && x < streetW - 5) mat = 10; + + streetView.setUint16((y * streetW + x) * 2, mat, true); } } @@ -167,7 +238,7 @@ export function generateGuestWorld() { targetFloor: 0, }, ]), - spawnX: 60, + spawnX: 200, spawnY: 150, spawnFloor: 0, createdAt: new Date().toISOString(), diff --git a/apps/manavoxel/apps/web/src/lib/engine/camera.ts b/apps/manavoxel/apps/web/src/lib/engine/camera.ts index 94d82a5de..e3ef85551 100644 --- a/apps/manavoxel/apps/web/src/lib/engine/camera.ts +++ b/apps/manavoxel/apps/web/src/lib/engine/camera.ts @@ -4,9 +4,9 @@ export class Camera { private _container: Container; private _x = 0; private _y = 0; - private _scale = 2; // 2x zoom by default (each 10cm pixel = 2 screen pixels) - private _minScale = 0.5; - private _maxScale = 8; + private _scale = 1.5; // Start zoomed out more to see the village + private _minScale = 0.3; + private _maxScale = 6; get x() { return this._x;