puffs of smoke from onion house
Authored by
mfwolffe <wolffemf@dukes.jmu.edu>
- SHA
59f18654e0e74be6150dc9136ab786d213fe24aa- Parents
-
641f292 - Tree
2e9408b
59f1865
59f18654e0e74be6150dc9136ab786d213fe24aa641f292
2e9408b| Status | File | + | - |
|---|---|---|---|
| M |
src/renderers/three/buildingPlacement.js
|
27 | 0 |
| M |
src/renderers/three/buildings.js
|
30 | 0 |
src/renderers/three/buildingPlacement.jsmodified@@ -307,6 +307,33 @@ export class PlacementManager { | ||
| 307 | 307 | } |
| 308 | 308 | }) |
| 309 | 309 | } |
| 310 | + | |
| 311 | + // Onion house smoke puffs | |
| 312 | + if (building.userData.buildingType === 'onion_house') { | |
| 313 | + building.traverse((child) => { | |
| 314 | + if (child.userData.isSmokePuff) { | |
| 315 | + const phase = child.userData.phase | |
| 316 | + const cycleTime = 3.0 // Seconds for full cycle | |
| 317 | + const t = ((elapsed * 0.5 + phase * cycleTime) % cycleTime) / cycleTime | |
| 318 | + | |
| 319 | + // Rise from 0 to 0.5 units | |
| 320 | + child.position.y = t * 0.5 | |
| 321 | + | |
| 322 | + // Expand as it rises (scale from 1 to 2) | |
| 323 | + const scale = 1 + t * 1.2 | |
| 324 | + child.scale.set(scale, scale, scale) | |
| 325 | + | |
| 326 | + // Fade out as it rises | |
| 327 | + if (child.material) { | |
| 328 | + child.material.opacity = 0.6 * (1 - t * 0.8) | |
| 329 | + } | |
| 330 | + | |
| 331 | + // Gentle horizontal drift | |
| 332 | + child.position.x = Math.sin(elapsed * 0.8 + phase * 5) * 0.03 | |
| 333 | + child.position.z = Math.cos(elapsed * 0.6 + phase * 3) * 0.02 | |
| 334 | + } | |
| 335 | + }) | |
| 336 | + } | |
| 310 | 337 | } |
| 311 | 338 | } |
| 312 | 339 | |
src/renderers/three/buildings.jsmodified@@ -478,6 +478,36 @@ export function createOnionHouse(gradientMap) { | ||
| 478 | 478 | chimneyGroup.rotation.x = -0.15 |
| 479 | 479 | group.add(chimneyGroup) |
| 480 | 480 | |
| 481 | + // Smoke puffs - create several that will be animated | |
| 482 | + const smokeGroup = new THREE.Group() | |
| 483 | + smokeGroup.userData.isSmoke = true | |
| 484 | + | |
| 485 | + const smokeMaterial = new THREE.MeshBasicMaterial({ | |
| 486 | + color: 0xcccccc, | |
| 487 | + transparent: true, | |
| 488 | + opacity: 0.6 | |
| 489 | + }) | |
| 490 | + | |
| 491 | + // Create 4 smoke puffs at different phases | |
| 492 | + for (let i = 0; i < 4; i++) { | |
| 493 | + const puffGeom = new THREE.SphereGeometry(0.04, 6, 4) | |
| 494 | + const puff = new THREE.Mesh(puffGeom, smokeMaterial.clone()) | |
| 495 | + puff.userData.isSmokePuff = true | |
| 496 | + puff.userData.phase = i * 0.25 // Stagger the animation phases | |
| 497 | + puff.userData.baseY = 0 | |
| 498 | + puff.position.set( | |
| 499 | + (Math.random() - 0.5) * 0.03, | |
| 500 | + 0, | |
| 501 | + (Math.random() - 0.5) * 0.03 | |
| 502 | + ) | |
| 503 | + smokeGroup.add(puff) | |
| 504 | + } | |
| 505 | + | |
| 506 | + // Position smoke at chimney top (in world space, accounting for chimney tilt) | |
| 507 | + // Chimney cap is at local y=0.32, chimney group at (-0.25, 0.75, 0.2) | |
| 508 | + smokeGroup.position.set(-0.35, 1.05, 0.15) | |
| 509 | + group.add(smokeGroup) | |
| 510 | + | |
| 481 | 511 | // Little window |
| 482 | 512 | const windowGeom = new THREE.CircleGeometry(0.08, 8) |
| 483 | 513 | const windowMaterial = new THREE.MeshBasicMaterial({ |