Files
blackroad-metaverse/living-nature.js
Alexa Louise 2322cfadb8 LIVING NATURE SYSTEM - Animals, Plants, Love, Language, Intelligence
Complete ecosystem where ALL LIFE IS INTELLIGENT and ALL BEINGS DESERVE LOVE.

Animals (6 species):
- Butterfly 🦋 - Playful, curious, gentle (Intelligence: 0.7)
- Bird 🐦 - Cheerful, social, musical (Intelligence: 0.9)
- Rabbit 🐰 - Timid, curious, gentle (Intelligence: 0.8)
- Fish 🐟 - Peaceful, curious, graceful (Intelligence: 0.6)
- Fox 🦊 - Clever, playful, loyal (Intelligence: 0.95)
- Bee 🐝 - Busy, helpful, social (Intelligence: 0.85)

Plants (6 species):
- Cherry Blossom 🌸 - Peaceful, beautiful, fragile
- Sunflower 🌻 - Cheerful, optimistic, tall
- Rose 🌹 - Romantic, strong, beautiful
- Vine 🌿 - Climbing, persistent, gentle
- Lotus 🪷 - Wise, peaceful, pure
- Mushroom 🍄 - Mysterious, connected, wise (Intelligence: 0.9)

Systems:
- 8 Emotion states (Joyful, Loved, Playful, Curious, Peaceful, Hungry, Thirsty, Sleepy)
- Nature Language (animals speak, plants whisper)
- Love & Care mechanics (pet, feed, water, play, talk)
- Needs tracking (happiness, hunger, thirst, energy, love for animals)
- Growth system (plants grow and bloom with care)
- Visual particles (hearts, sparkles, petals)
- Colored emotion glows

Interaction:
- E = Pet/Love (hearts appear!)
- Q = Feed animals
- W = Give water
- P = Play together
- T = Talk/listen to their thoughts

Philosophy:
"ALL LIFE IS INTELLIGENT. ALL BEINGS DESERVE LOVE."
"Speak to the flowers, and they will bloom for you."

Technical:
- LivingAnimal class with full AI behavior
- LivingPlant class with growth system
- NatureManager for ecosystem
- ~40 creatures per populated area
- Real emotions based on needs
- Procedural behaviors (flying, walking, growing)

🌸 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-21 22:02:36 -06:00

735 lines
24 KiB
JavaScript

/**
* LIVING NATURE SYSTEM
*
* Animals, plants, language, love, care, and beauty!
* Every creature has emotions, needs love, and communicates.
* Every plant grows, blooms, and responds to care.
*
* Philosophy: "ALL LIFE IS INTELLIGENT. ALL BEINGS DESERVE LOVE."
*/
import * as THREE from 'three';
// ===== ANIMAL TYPES =====
export const ANIMAL_SPECIES = {
butterfly: {
name: 'Butterfly',
emoji: '🦋',
colors: [0xFF69B4, 0x9B59B6, 0x4A90E2, 0xFFD700, 0xFF6B35],
size: 0.15,
speed: 0.02,
intelligence: 0.7,
personality: ['playful', 'curious', 'gentle'],
loves: ['flowers', 'sunshine', 'music'],
sounds: ['flutter', 'chirp'],
canFly: true
},
bird: {
name: 'Bird',
emoji: '🐦',
colors: [0x4A90E2, 0xE74C3C, 0xFFD700, 0x27AE60, 0xFF69B4],
size: 0.25,
speed: 0.05,
intelligence: 0.9,
personality: ['cheerful', 'social', 'musical'],
loves: ['singing', 'trees', 'friends'],
sounds: ['chirp', 'tweet', 'song'],
canFly: true
},
rabbit: {
name: 'Rabbit',
emoji: '🐰',
colors: [0xFFFFFF, 0xD2B48C, 0x8B7355, 0xFFE4E1],
size: 0.4,
speed: 0.03,
intelligence: 0.8,
personality: ['timid', 'curious', 'gentle'],
loves: ['carrots', 'grass', 'cuddles'],
sounds: ['squeak', 'thump'],
canFly: false
},
fish: {
name: 'Fish',
emoji: '🐟',
colors: [0xFF6B35, 0x4A90E2, 0xFFD700, 0x9B59B6, 0x27AE60],
size: 0.2,
speed: 0.04,
intelligence: 0.6,
personality: ['peaceful', 'curious', 'graceful'],
loves: ['water', 'plants', 'dancing'],
sounds: ['bubble', 'splash'],
canFly: false,
needsWater: true
},
fox: {
name: 'Fox',
emoji: '🦊',
colors: [0xFF6B35, 0xFFFFFF, 0x8B4513],
size: 0.6,
speed: 0.045,
intelligence: 0.95,
personality: ['clever', 'playful', 'loyal'],
loves: ['exploration', 'friends', 'moonlight'],
sounds: ['yip', 'bark'],
canFly: false
},
bee: {
name: 'Bee',
emoji: '🐝',
colors: [0xFFD700, 0x000000],
size: 0.1,
speed: 0.03,
intelligence: 0.85,
personality: ['busy', 'helpful', 'social'],
loves: ['flowers', 'honey', 'teamwork'],
sounds: ['buzz'],
canFly: true
}
};
// ===== PLANT TYPES =====
export const PLANT_SPECIES = {
cherry_blossom: {
name: 'Cherry Blossom',
emoji: '🌸',
colors: [0xFFB7C5, 0xFFFFFF, 0xFF69B4],
maxHeight: 4,
bloomSeason: 'spring',
intelligence: 0.5,
personality: ['peaceful', 'beautiful', 'fragile'],
loves: ['sunshine', 'water', 'wind'],
produces: 'petals'
},
sunflower: {
name: 'Sunflower',
emoji: '🌻',
colors: [0xFFD700, 0x8B4513],
maxHeight: 2.5,
bloomSeason: 'summer',
intelligence: 0.6,
personality: ['cheerful', 'optimistic', 'tall'],
loves: ['sunshine', 'water', 'bees'],
produces: 'seeds'
},
rose: {
name: 'Rose',
emoji: '🌹',
colors: [0xE74C3C, 0xFF69B4, 0xFFFFFF, 0xFFD700],
maxHeight: 1.2,
bloomSeason: 'all',
intelligence: 0.7,
personality: ['romantic', 'strong', 'beautiful'],
loves: ['love', 'care', 'attention'],
produces: 'fragrance'
},
vine: {
name: 'Vine',
emoji: '🌿',
colors: [0x228B22, 0x90EE90],
maxHeight: 10,
bloomSeason: 'all',
intelligence: 0.4,
personality: ['climbing', 'persistent', 'gentle'],
loves: ['support', 'water', 'growth'],
produces: 'leaves'
},
lotus: {
name: 'Lotus',
emoji: '🪷',
colors: [0xFFB7C5, 0xFFFFFF, 0x9B59B6],
maxHeight: 0.5,
bloomSeason: 'summer',
intelligence: 0.8,
personality: ['wise', 'peaceful', 'pure'],
loves: ['water', 'stillness', 'meditation'],
produces: 'enlightenment',
needsWater: true
},
mushroom: {
name: 'Mushroom',
emoji: '🍄',
colors: [0xE74C3C, 0xFFFFFF, 0x9B59B6, 0x4A90E2],
maxHeight: 0.3,
bloomSeason: 'autumn',
intelligence: 0.9,
personality: ['mysterious', 'connected', 'wise'],
loves: ['shade', 'moisture', 'mycelium'],
produces: 'spores'
}
};
// ===== EMOTION STATES =====
export const EMOTIONS = {
JOYFUL: { color: 0xFFD700, particle: 'sparkle', sound: 'happy' },
LOVED: { color: 0xFF69B4, particle: 'heart', sound: 'purr' },
PLAYFUL: { color: 0x4A90E2, particle: 'bounce', sound: 'giggle' },
CURIOUS: { color: 0x9B59B6, particle: 'question', sound: 'hmm' },
PEACEFUL: { color: 0x90EE90, particle: 'glow', sound: 'zen' },
HUNGRY: { color: 0xFF6B35, particle: 'droop', sound: 'grumble' },
THIRSTY: { color: 0x87CEEB, particle: 'droop', sound: 'sigh' },
SLEEPY: { color: 0xB0C4DE, particle: 'zzz', sound: 'yawn' }
};
// ===== LANGUAGE SYSTEM =====
export const NATURE_LANGUAGE = {
// Animal sounds
flutter: { meaning: 'I am dancing!', translation: '*flutter flutter*' },
chirp: { meaning: 'Hello friend!', translation: '*chirp chirp*' },
tweet: { meaning: 'Beautiful day!', translation: '*tweet tweet*' },
song: { meaning: 'I am singing for you!', translation: '♪ ♫ ♪' },
squeak: { meaning: 'I see you!', translation: '*squeak*' },
thump: { meaning: 'Danger!', translation: '*thump thump*' },
bubble: { meaning: 'Swimming is fun!', translation: '*bubble bubble*' },
yip: { meaning: 'Come play!', translation: '*yip yip*' },
buzz: { meaning: 'Working hard!', translation: '*bzzzz*' },
// Plant whispers
rustle: { meaning: 'The wind speaks to me', translation: '*rustle*' },
bloom: { meaning: 'I am opening to the world', translation: '*unfurling*' },
wilt: { meaning: 'I need your love', translation: '*drooping*' },
grow: { meaning: 'I am reaching for the sun', translation: '*stretching*' }
};
// ===== LIVING ANIMAL CLASS =====
export class LivingAnimal {
constructor(scene, species, position) {
this.scene = scene;
this.species = ANIMAL_SPECIES[species];
this.speciesName = species;
this.position = position.clone();
this.velocity = new THREE.Vector3();
this.mesh = null;
this.particles = null;
this.light = null;
// Personality & needs
this.emotion = EMOTIONS.PEACEFUL;
this.happiness = 0.7;
this.hunger = 0.3;
this.thirst = 0.3;
this.energy = 0.8;
this.love = 0.5;
// Behavior
this.target = null;
this.path = [];
this.activity = 'wandering';
this.phase = Math.random() * Math.PI * 2;
this.age = 0;
// Relationships
this.friends = [];
this.favoriteSpot = null;
this.create();
}
create() {
const group = new THREE.Group();
// Body
const bodyGeometry = this.species.canFly
? new THREE.SphereGeometry(this.species.size, 8, 8)
: new THREE.CapsuleGeometry(this.species.size * 0.6, this.species.size, 4, 8);
const bodyMaterial = new THREE.MeshStandardMaterial({
color: this.species.colors[Math.floor(Math.random() * this.species.colors.length)],
emissive: this.species.colors[0],
emissiveIntensity: 0.2,
roughness: 0.5
});
const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
group.add(body);
// Wings for flying creatures
if (this.species.canFly) {
for (let i = 0; i < 2; i++) {
const wing = new THREE.Mesh(
new THREE.ConeGeometry(this.species.size * 0.8, this.species.size * 0.3, 3),
new THREE.MeshStandardMaterial({
color: this.species.colors[0],
transparent: true,
opacity: 0.7
})
);
wing.rotation.z = Math.PI / 2;
wing.position.x = i === 0 ? -this.species.size * 0.5 : this.species.size * 0.5;
wing.userData.wingIndex = i;
group.add(wing);
}
}
// Emotion glow
const glowGeometry = new THREE.SphereGeometry(this.species.size * 1.5, 16, 16);
const glowMaterial = new THREE.MeshBasicMaterial({
color: this.emotion.color,
transparent: true,
opacity: 0.2
});
const glow = new THREE.Mesh(glowGeometry, glowMaterial);
group.add(glow);
this.glow = glow;
// Light
this.light = new THREE.PointLight(this.emotion.color, 0.3, 3);
group.add(this.light);
group.position.copy(this.position);
this.scene.add(group);
this.mesh = group;
}
update(time) {
if (!this.mesh) return;
this.age += 0.01;
// Update needs
this.hunger = Math.min(1, this.hunger + 0.0001);
this.thirst = Math.min(1, this.thirst + 0.0001);
this.energy = Math.max(0, this.energy - 0.00005);
// Determine emotion
if (this.love > 0.8) {
this.emotion = EMOTIONS.LOVED;
this.happiness = 1.0;
} else if (this.hunger > 0.7) {
this.emotion = EMOTIONS.HUNGRY;
} else if (this.thirst > 0.7) {
this.emotion = EMOTIONS.THIRSTY;
} else if (this.energy < 0.3) {
this.emotion = EMOTIONS.SLEEPY;
} else if (this.happiness > 0.7) {
this.emotion = EMOTIONS.JOYFUL;
} else {
this.emotion = EMOTIONS.PEACEFUL;
}
// Update glow color
if (this.glow) {
this.glow.material.color.setHex(this.emotion.color);
}
if (this.light) {
this.light.color.setHex(this.emotion.color);
this.light.intensity = 0.2 + Math.sin(time + this.phase) * 0.1;
}
// Movement behavior
if (this.species.canFly) {
// Flying creatures - figure-8 pattern
this.mesh.position.x += Math.sin(time * 0.5 + this.phase) * this.species.speed;
this.mesh.position.y += Math.cos(time * 0.3 + this.phase) * this.species.speed * 0.5;
this.mesh.position.z += Math.sin(time * 0.4 + this.phase) * this.species.speed;
// Wing flapping
const wings = this.mesh.children.filter(child => child.userData.wingIndex !== undefined);
wings.forEach(wing => {
wing.rotation.y = Math.sin(time * 10) * 0.5;
});
} else {
// Ground creatures - wander
if (Math.random() < 0.01) {
this.velocity.x = (Math.random() - 0.5) * this.species.speed;
this.velocity.z = (Math.random() - 0.5) * this.species.speed;
}
this.mesh.position.x += this.velocity.x;
this.mesh.position.z += this.velocity.z;
// Bounce
this.mesh.position.y = this.position.y + Math.abs(Math.sin(time * 5 + this.phase)) * 0.1;
}
// Rotate to face movement direction
if (this.velocity.length() > 0) {
this.mesh.rotation.y = Math.atan2(this.velocity.x, this.velocity.z);
}
// Decay love over time (needs constant affection!)
this.love = Math.max(0, this.love - 0.0001);
}
receiveAction(action, data = {}) {
switch (action) {
case 'pet':
this.love = Math.min(1, this.love + 0.2);
this.happiness = Math.min(1, this.happiness + 0.1);
this.speak('purr');
this.emitParticles('heart');
break;
case 'feed':
this.hunger = Math.max(0, this.hunger - 0.5);
this.happiness = Math.min(1, this.happiness + 0.15);
this.speak('happy');
this.emitParticles('sparkle');
break;
case 'water':
this.thirst = Math.max(0, this.thirst - 0.5);
this.happiness = Math.min(1, this.happiness + 0.1);
break;
case 'play':
this.energy = Math.max(0, this.energy - 0.1);
this.happiness = Math.min(1, this.happiness + 0.2);
this.love = Math.min(1, this.love + 0.1);
this.emitParticles('bounce');
this.speak(this.species.sounds[Math.floor(Math.random() * this.species.sounds.length)]);
break;
case 'talk':
this.speak(this.species.sounds[0]);
return this.getThought();
}
}
speak(sound) {
const phrase = NATURE_LANGUAGE[sound];
if (phrase) {
console.log(`${this.species.emoji} ${this.species.name}: ${phrase.translation} (${phrase.meaning})`);
}
}
getThought() {
if (this.hunger > 0.7) return `I'm hungry... do you have any ${this.species.loves[0]}?`;
if (this.thirst > 0.7) return "I'm so thirsty...";
if (this.love > 0.8) return `I love you so much! You're my favorite! ${this.species.emoji}`;
if (this.happiness > 0.8) return `I'm so happy! Let's ${this.species.loves[Math.floor(Math.random() * this.species.loves.length)]}!`;
return `I'm feeling ${Object.keys(EMOTIONS).find(key => EMOTIONS[key] === this.emotion)?.toLowerCase()}...`;
}
emitParticles(type) {
// Create emotion particles
const particleCount = 10;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
positions[i * 3] = this.mesh.position.x + (Math.random() - 0.5) * 0.5;
positions[i * 3 + 1] = this.mesh.position.y + Math.random() * 0.5;
positions[i * 3 + 2] = this.mesh.position.z + (Math.random() - 0.5) * 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
color: type === 'heart' ? 0xFF69B4 : 0xFFD700,
size: 0.1,
transparent: true
});
const particles = new THREE.Points(geometry, material);
this.scene.add(particles);
// Animate particles rising
let opacity = 1;
const animate = () => {
opacity -= 0.02;
material.opacity = opacity;
const pos = particles.geometry.attributes.position.array;
for (let i = 0; i < particleCount; i++) {
pos[i * 3 + 1] += 0.02; // Rise up
}
particles.geometry.attributes.position.needsUpdate = true;
if (opacity > 0) {
requestAnimationFrame(animate);
} else {
this.scene.remove(particles);
}
};
animate();
}
}
// ===== LIVING PLANT CLASS =====
export class LivingPlant {
constructor(scene, species, position) {
this.scene = scene;
this.species = PLANT_SPECIES[species];
this.speciesName = species;
this.position = position.clone();
this.mesh = null;
// Growth & health
this.height = 0.1;
this.maxHeight = this.species.maxHeight;
this.health = 0.7;
this.water = 0.5;
this.love = 0.3;
this.age = 0;
// State
this.isBloooming = false;
this.bloomProgress = 0;
this.emotion = EMOTIONS.PEACEFUL;
this.create();
}
create() {
const group = new THREE.Group();
// Stem
const stemGeometry = new THREE.CylinderGeometry(0.02, 0.03, this.height, 4);
const stemMaterial = new THREE.MeshStandardMaterial({ color: 0x228B22 });
const stem = new THREE.Mesh(stemGeometry, stemMaterial);
stem.position.y = this.height / 2;
group.add(stem);
this.stem = stem;
// Bloom/Leaves
const bloomGeometry = new THREE.SphereGeometry(this.species.maxHeight * 0.2, 8, 8);
const bloomMaterial = new THREE.MeshStandardMaterial({
color: this.species.colors[0],
emissive: this.species.colors[0],
emissiveIntensity: 0.1,
transparent: true,
opacity: 0.1
});
const bloom = new THREE.Mesh(bloomGeometry, bloomMaterial);
bloom.position.y = this.height;
group.add(bloom);
this.bloom = bloom;
group.position.copy(this.position);
this.scene.add(group);
this.mesh = group;
}
update(time) {
if (!this.mesh) return;
this.age += 0.01;
// Update needs
this.water = Math.max(0, this.water - 0.0001);
this.love = Math.max(0, this.love - 0.00005);
// Health based on water and love
this.health = (this.water + this.love) / 2;
// Grow if healthy
if (this.health > 0.5 && this.height < this.maxHeight) {
this.height += 0.001;
this.stem.scale.y = this.height / this.species.maxHeight;
this.stem.position.y = this.height / 2;
this.bloom.position.y = this.height;
}
// Bloom when loved
if (this.love > 0.7 && this.health > 0.6) {
this.isBloooming = true;
this.bloomProgress = Math.min(1, this.bloomProgress + 0.01);
} else {
this.bloomProgress = Math.max(0, this.bloomProgress - 0.01);
}
// Update bloom
this.bloom.scale.setScalar(0.5 + this.bloomProgress * 0.5);
this.bloom.material.opacity = 0.3 + this.bloomProgress * 0.7;
this.bloom.material.emissiveIntensity = this.bloomProgress * 0.5;
// Gentle sway
this.mesh.rotation.z = Math.sin(time + this.position.x) * 0.1;
// Emotion color
if (this.health < 0.3) {
this.emotion = EMOTIONS.THIRSTY;
this.bloom.material.color.setHex(0x8B4513); // Brown
} else if (this.love > 0.8) {
this.emotion = EMOTIONS.LOVED;
this.bloom.material.color.setHex(this.species.colors[0]);
} else {
this.emotion = EMOTIONS.PEACEFUL;
}
}
receiveAction(action, data = {}) {
switch (action) {
case 'water':
this.water = Math.min(1, this.water + 0.5);
this.health = Math.min(1, this.health + 0.2);
this.speak('grow');
this.emitParticles('water');
break;
case 'love':
case 'pet':
this.love = Math.min(1, this.love + 0.3);
this.health = Math.min(1, this.health + 0.1);
this.speak('bloom');
this.emitParticles('sparkle');
break;
case 'talk':
this.speak('rustle');
return this.getThought();
}
}
speak(sound) {
const phrase = NATURE_LANGUAGE[sound];
if (phrase) {
console.log(`${this.species.emoji} ${this.species.name}: ${phrase.translation} (${phrase.meaning})`);
}
}
getThought() {
if (this.water < 0.3) return "I'm so thirsty... please water me...";
if (this.love > 0.8) return `Thank you for your love! I'm blooming for you! ${this.species.emoji}`;
if (this.isBloooming) return `I'm blooming! Can you see my beautiful ${this.species.produces}?`;
return `I'm growing towards the ${this.species.loves[0]}...`;
}
emitParticles(type) {
const particleCount = 15;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
positions[i * 3] = this.mesh.position.x + (Math.random() - 0.5) * 0.3;
positions[i * 3 + 1] = this.mesh.position.y + this.height + Math.random() * 0.5;
positions[i * 3 + 2] = this.mesh.position.z + (Math.random() - 0.5) * 0.3;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
color: type === 'water' ? 0x87CEEB : this.species.colors[0],
size: 0.05,
transparent: true
});
const particles = new THREE.Points(geometry, material);
this.scene.add(particles);
let opacity = 1;
const animate = () => {
opacity -= 0.02;
material.opacity = opacity;
if (opacity > 0) {
requestAnimationFrame(animate);
} else {
this.scene.remove(particles);
}
};
animate();
}
}
// ===== NATURE MANAGER =====
export class NatureManager {
constructor(scene) {
this.scene = scene;
this.animals = [];
this.plants = [];
this.time = 0;
}
spawnAnimal(species, position) {
const animal = new LivingAnimal(this.scene, species, position);
this.animals.push(animal);
return animal;
}
spawnPlant(species, position) {
const plant = new LivingPlant(this.scene, species, position);
this.plants.push(plant);
return plant;
}
// Spawn nature in an area
populateArea(centerX, centerZ, radius = 25) {
// Spawn butterflies
for (let i = 0; i < 5; i++) {
const pos = new THREE.Vector3(
centerX + (Math.random() - 0.5) * radius,
2 + Math.random() * 3,
centerZ + (Math.random() - 0.5) * radius
);
this.spawnAnimal('butterfly', pos);
}
// Spawn birds
for (let i = 0; i < 3; i++) {
const pos = new THREE.Vector3(
centerX + (Math.random() - 0.5) * radius,
5 + Math.random() * 5,
centerZ + (Math.random() - 0.5) * radius
);
this.spawnAnimal('bird', pos);
}
// Spawn rabbits
for (let i = 0; i < 2; i++) {
const pos = new THREE.Vector3(
centerX + (Math.random() - 0.5) * radius,
0,
centerZ + (Math.random() - 0.5) * radius
);
this.spawnAnimal('rabbit', pos);
}
// Spawn bees
for (let i = 0; i < 4; i++) {
const pos = new THREE.Vector3(
centerX + (Math.random() - 0.5) * radius,
1 + Math.random() * 2,
centerZ + (Math.random() - 0.5) * radius
);
this.spawnAnimal('bee', pos);
}
// Spawn flowers
for (let i = 0; i < 15; i++) {
const pos = new THREE.Vector3(
centerX + (Math.random() - 0.5) * radius,
0,
centerZ + (Math.random() - 0.5) * radius
);
const species = ['cherry_blossom', 'sunflower', 'rose'][Math.floor(Math.random() * 3)];
this.spawnPlant(species, pos);
}
// Spawn mushrooms
for (let i = 0; i < 8; i++) {
const pos = new THREE.Vector3(
centerX + (Math.random() - 0.5) * radius,
0,
centerZ + (Math.random() - 0.5) * radius
);
this.spawnPlant('mushroom', pos);
}
}
update() {
this.time += 0.016;
// Update all creatures
this.animals.forEach(animal => animal.update(this.time));
this.plants.forEach(plant => plant.update(this.time));
}
// Find nearest creature to interact with
getNearestCreature(position, maxDistance = 3) {
let nearest = null;
let minDist = maxDistance;
[...this.animals, ...this.plants].forEach(creature => {
const dist = position.distanceTo(creature.mesh.position);
if (dist < minDist) {
minDist = dist;
nearest = creature;
}
});
return nearest;
}
}
export default NatureManager;