Klima 3D V2: Session-Abschluss — Strandleben komplett + Berichte
- Strandleben: 22 Stellen (vorher 12), fünf Typen statt drei: Figur, Sonnenschirm, Handtuch, Liegestuhl (neu), Hund (neu). Positionen über gleichmäßiges Winkel-Raster mit Jitter, damit die Elemente rundum verteilt sitzen statt zufällig zusammen zu klumpen. - makeBeachChair: angeschrägte Rückenlehne + Sitz + vier Beine in wechselnder Stoff-Farbe. - makeBeachDog: Körper + Kopf + Schnauze + Schwanz + vier Beinchen + Ohren in zufälliger Fell-Farbe. - _status.md: auf finalen V2-Stand überschrieben - _inbox/zentrale/2026-04-19-2130-klima-3d-v2-abschluss.md: Bericht an Atlas mit vollständiger Feature-Liste - _inbox/zentrale/2026-04-19-2135-klima-3d-v2-lehrplan-nachtrag.md: Nachtrag an Lehrplan (Modul-Detailseite um 2D/3D-Launcher erweitern) - _inbox/glossar/2026-04-19-2130-klima-3d-v2-info-topics.md: Info an Glossar (17 view-lokale INFO_TOPICS, keine DB-Änderung nötig) 3D V2 ist einsatzbereit — Thomas schließt heute ab, strukturierter Browser-Regression-Test folgt in späterer Session. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+82
-11
@@ -4230,27 +4230,98 @@ function makeBeachTowel() {
|
||||
towel.position.y = 0.002; g.add(towel);
|
||||
return g;
|
||||
}
|
||||
|
||||
// Liegestuhl: angeschrägte Rückenlehne + Sitzfläche + zwei Beine
|
||||
function makeBeachChair() {
|
||||
const g = new THREE.Group();
|
||||
const colors = [0xe04040, 0x3070c0, 0xe0a040, 0x40a06a, 0xb040c0];
|
||||
const fabricMat = new THREE.MeshStandardMaterial({
|
||||
color: colors[Math.floor(Math.random() * colors.length)], roughness: 1
|
||||
});
|
||||
const frameMat = new THREE.MeshStandardMaterial({ color: 0x6a4a28, roughness: 1 });
|
||||
// Sitzfläche
|
||||
const seat = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.01, 0.08), fabricMat);
|
||||
seat.position.set(0, 0.06, 0); g.add(seat);
|
||||
// Rückenlehne (schräg)
|
||||
const back = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.13, 0.01), fabricMat);
|
||||
back.rotation.x = 0.4;
|
||||
back.position.set(0, 0.11, -0.05); g.add(back);
|
||||
// Beine
|
||||
for (const sx of [-0.05, 0.05]) {
|
||||
for (const sz of [-0.03, 0.03]) {
|
||||
const leg = new THREE.Mesh(new THREE.CylinderGeometry(0.005, 0.005, 0.06, 4), frameMat);
|
||||
leg.position.set(sx, 0.03, sz); g.add(leg);
|
||||
}
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
// Kleiner Strand-Hund: dicker Körper + Kopf + Schwanz + vier Beinchen
|
||||
function makeBeachDog() {
|
||||
const g = new THREE.Group();
|
||||
const furColors = [0xd8a870, 0x6a4a28, 0xe0e0e0, 0x2a2a2a, 0xa07040];
|
||||
const mat = new THREE.MeshStandardMaterial({
|
||||
color: furColors[Math.floor(Math.random() * furColors.length)], roughness: 1
|
||||
});
|
||||
// Körper (horizontaler Zylinder)
|
||||
const body = new THREE.Mesh(new THREE.CylinderGeometry(0.035, 0.035, 0.12, 8), mat);
|
||||
body.rotation.z = Math.PI / 2;
|
||||
body.position.y = 0.05; g.add(body);
|
||||
// Kopf
|
||||
const head = new THREE.Mesh(new THREE.SphereGeometry(0.035, 6, 5), mat);
|
||||
head.position.set(0.07, 0.07, 0); g.add(head);
|
||||
// Schnauze (leicht dunkler)
|
||||
const snout = new THREE.Mesh(
|
||||
new THREE.BoxGeometry(0.035, 0.025, 0.025),
|
||||
new THREE.MeshStandardMaterial({ color: 0x2a2018, roughness: 1 })
|
||||
);
|
||||
snout.position.set(0.10, 0.06, 0); g.add(snout);
|
||||
// Schwanz
|
||||
const tail = new THREE.Mesh(new THREE.CylinderGeometry(0.007, 0.012, 0.05, 5), mat);
|
||||
tail.rotation.z = -Math.PI / 3;
|
||||
tail.position.set(-0.08, 0.07, 0); g.add(tail);
|
||||
// Vier Beine
|
||||
for (const bx of [0.045, -0.045]) {
|
||||
for (const bz of [0.025, -0.025]) {
|
||||
const leg = new THREE.Mesh(new THREE.CylinderGeometry(0.008, 0.008, 0.04, 5), mat);
|
||||
leg.position.set(bx, 0.02, bz); g.add(leg);
|
||||
}
|
||||
}
|
||||
// Ohren (zwei kleine Dreiecke)
|
||||
for (const ey of [-0.02, 0.02]) {
|
||||
const ear = new THREE.Mesh(new THREE.ConeGeometry(0.012, 0.025, 4), mat);
|
||||
ear.position.set(0.06, 0.10, ey); g.add(ear);
|
||||
}
|
||||
return g;
|
||||
}
|
||||
function buildBeachLife() {
|
||||
while (beachLifeGroup.children.length) beachLifeGroup.remove(beachLifeGroup.children[0]);
|
||||
// 12 Stellen am Küstenband, zufällig auf Figuren/Schirme/Handtücher verteilt
|
||||
for (let i = 0; i < 12; i++) {
|
||||
// 22 Stellen rund um die Küste, gleichmäßig verteilt — Figuren,
|
||||
// Schirme, Handtücher, Liegestühle und Hunde in wechselnder Mischung.
|
||||
for (let i = 0; i < 22; i++) {
|
||||
let x = 0, z = 0, y = 0;
|
||||
for (let tries = 0; tries < 20; tries++) {
|
||||
const a = Math.random() * Math.PI * 2;
|
||||
const rScale = 0.82 + Math.random() * 0.08;
|
||||
for (let tries = 0; tries < 24; tries++) {
|
||||
// Winkel aus gleichmäßigem Raster (mit Jitter), damit nicht alle
|
||||
// Elemente zufällig an derselben Seite der Insel hocken.
|
||||
const angleBase = (i / 22) * Math.PI * 2;
|
||||
const a = angleBase + (Math.random() - 0.5) * 0.5;
|
||||
const rScale = 0.80 + Math.random() * 0.10;
|
||||
x = Math.cos(a) * ISLAND_HALF_WIDTH * rScale;
|
||||
z = Math.sin(a) * ISLAND_HALF_LENGTH * rScale;
|
||||
y = terrainHeight(x, z);
|
||||
if (y >= 0.2 && y <= 0.55) break;
|
||||
if (y >= 0.18 && y <= 0.58) break;
|
||||
}
|
||||
if (y < 0.2) continue;
|
||||
if (y < 0.18) continue;
|
||||
const roll = Math.random();
|
||||
const piece = roll < 0.45 ? makeBeachFigure()
|
||||
: roll < 0.80 ? makeBeachUmbrella()
|
||||
: makeBeachTowel();
|
||||
let piece;
|
||||
if (roll < 0.28) piece = makeBeachFigure();
|
||||
else if (roll < 0.50) piece = makeBeachUmbrella();
|
||||
else if (roll < 0.68) piece = makeBeachTowel();
|
||||
else if (roll < 0.86) piece = makeBeachChair();
|
||||
else piece = makeBeachDog();
|
||||
piece.position.set(x, y, z);
|
||||
piece.rotation.y = Math.random() * Math.PI * 2;
|
||||
piece.scale.setScalar(0.55 + Math.random() * 0.35); // winzig
|
||||
piece.scale.setScalar(0.55 + Math.random() * 0.40); // winzig
|
||||
beachLifeGroup.add(piece);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user