On this page

  1. The Food Web
  2. Feeding & Reproduction
  3. Energy & Metabolism
  4. Plant Lifecycle
  5. Population Balance

The Food Web

PolyFish's ecosystem runs on a short loop: creatures seek the nearest food source, eat it, and that single act of eating triggers everything else - poop, reproduction, population growth. The food web fans out from there. Plants produce food particles. Fish eat the food. Dolphins hunt fish. Manatees eat plants directly. Waste from any creature can seed new plants, closing the loop.

Everything is driven by collisions. Food collides with a creature's mouth trigger, causing it to eat. Poop collides with the terrain, which then decides whether it should grow a plant, bounce, or do nothing. Because these outcomes depend on where things physically land, each session plays out differently - even though the overall story and macro-behavior remain the same.

This physics-driven approach means the ecosystem doesn't need scripted events or timers. Efficient spatial hashing keeps collision queries fast across 100+ creatures.

Feeding & Reproduction

Each creature carries a food counter that increments each time it consumes food within its mouth radius. When the counter reaches a reproduction threshold, the creature spawns offspring (up to 12) and resets the counter. A 10-second cooldown prevents spam.

Feeding is spatial. Every frame, a creature queries its grid cell and nearby cells for food particles. If any are within the mouth radius, the particle is destroyed and the food counter increments. Fish have a tight mouth radius of 0.15 units, requiring them to get right on top of food. Dolphins and manatees have a wider 0.5-unit radius, making feeding easier for the larger creatures.

// Query nearby cells for food particles
const cellHash = spatialHash(creature.x, creature.z, cellSize);
const nearbyFoods = grid.get(cellHash) || [];

for (let food of nearbyFoods) {
  const dist = creature.distanceTo(food);
  if (dist < mouthRadius) {
    this.consumeFood(food);
    creature.foodCounter++;
  }
}

// Reproduction threshold
if (creature.foodCounter >= repThreshold && now - creature.lastReproduce > cooldown) {
  for (let i = 0; i < 12; i++) {
    this.spawnOffspring(creature);
  }
  creature.foodCounter = 0;
  creature.lastReproduce = now;
}

Fish (Threshold: 4)

Eat food particles. Need 4 meals to reproduce. 10s cooldown. Mouth radius 0.15 units.

Dolphins (Threshold: 5)

Hunt fish as prey. Need 5 fish meals to reproduce. 10s cooldown. Mouth radius 0.5 units.

Manatees (Threshold: 7)

Eat plants directly. Need 7 meals to reproduce. 10s cooldown. Mouth radius 0.5 units.

Offspring Limit

Max 12 offspring per reproduction event across all species. Prevents population explosions.

Energy & Metabolism

Every creature starts with 60 energy points. Each second, energy drains at a constant rate (60 energy/min for fish, scaled for other species). When energy hits zero, the creature dies and sinks to the seafloor, becoming waste that seeds new plants.

Energy conservation is strict. Creatures don't gain energy from food, only reproduction. The energy drain is lifespan control. A fish with 60 starting energy that drains at 60/min lives exactly 60 seconds (plus or minus a random variance of ±30 seconds). Larger creatures like dolphins and manatees drain slower, living 120+ seconds.

// Energy drain per frame (delta = 1/60 second)
const drainRate = 60 / 60000; // 60 energy per minute
creature.energy -= drainRate * deltaTime;

// Death when energy <= 0
if (creature.energy <= 0) {
  this.killCreature(creature);
  // Waste seeds plants at creature position
  this.spawnPlant(creature.x, creature.z);
}
60
Starting energy
60–90s
Fish lifespan
120+s
Dolphin/manatee
0
Gain from food

Plant Lifecycle

Plants are both scenery and the ecosystem's energy source. They spawn from creature waste, germinate with a 40% base chance reduced by nearby plant density, grow over 16 seconds with an animation, produce food particles, and die after 37-62 seconds.

Seed germination uses a random roll: 40% base chance, but reduced by 25% for each nearby plant within a 1.33-unit radius. This creates natural clustering - dense forests self-regulate their growth. A spot with 3 neighboring plants has only a ~17% chance of germinating a new one.

Growth animation: Young plants (0–16s) display a scaling animation from 0 to 100%, plus a gentle sway. This gives the player visual feedback that the ecosystem is alive and growing.

Food production: Young plants (still growing) produce 1 food particle per second. Mature plants (past growth phase) produce 1 every 8 seconds, scaling back production to conserve particles. Each plant can hold at most 4 bites of food before it needs to be consumed.

// Seed germination with density check
let chance = 0.4; // 40% base
const nearbyPlants = this.countPlantsNearby(x, z, 1.33);
chance *= Math.pow(0.75, nearbyPlants); // 25% reduction per neighbor

if (Math.random() < chance) {
  this.spawnPlant(x, z);
}

// Food production scaled by growth phase
const isYoung = plant.age < 16;
const foodRate = isYoung ? 1 : 1 / 8;

if (plant.foodCounter >= foodRate * deltaTime) {
  this.spawnFood(plant.x, plant.z);
  plant.foodCounter = 0;
}
40%
Germination chance
16s
Growth duration
37–62s
Plant lifespan
1 or 1/8
Food/sec (young/mature)

Population Balance

The ecosystem starts with initial object pools for each species - 60 fish, 15 dolphins, and 10 manatees - to seed the world with life. But there are no hard caps. Populations can and do run away beyond those initial numbers. The system is intentionally designed this way.

Instead of artificial limits, the ecosystem relies on physics and hunger to self-regulate. When food runs out, creatures starve. When predators become too numerous, prey populations decline. Energy drain from movement and maintenance creates constant pressure. These organic forces - not a population monitor - naturally control population growth. During development, populations regularly blew past the initial object pools, exploding until the ecosystem collapsed under its own weight and then recovered.

This design creates more authentic emergent behavior. Rather than hitting an invisible ceiling, populations rise and fall based on real ecological pressures. It is messier, less stable, and far more interesting.

Predator-Prey Dynamics

The ecosystem's core tension is the predator-prey loop. Fish breed slowly but exist in numbers. Dolphins hunt effectively but must breathe and can fail. Manatees ignore the whole drama. This creates a balanced system where neither predators nor prey can fully dominate.

Fish Behavior

Fish forage peacefully until a dolphin enters a 1.5-unit radius. At that instant, all nearby fish (within the radius) reverse course and swim away at full speed. If the dolphin stays near, fish keep fleeing. If the dolphin moves away or surfaces, fish calm down and return to foraging within 1-2 seconds. This creates dramatic chases where prey dodge obstacles and the dolphin must predict their path rather than just chase linearly.

Dolphin Strategy

Dolphins don't randomly hunt. They use a simple search pattern: move forward, raycasting a cone ahead for fish. When they detect prey, they lock onto the nearest target and accelerate. If the dolphin gets close enough (0.5 units), it kills and consumes the fish, restoring hunger points. If a chase lasts too long (say, 10 seconds) without contact, the dolphin gives up and returns to searching.

Kill Mechanics

When a dolphin reaches within 0.5 units of a fish, the fish is instantly removed and a death particle effect plays at that position. The dolphin gains food points. The natural pace of hunting is limited by the dolphins' need to surface for air every 60 seconds, which interrupts chases and gives fish time to scatter. This prevents single predators from annihilating the entire fish population in seconds.

Population Equilibrium

There are no spawners or timers - every creature in PolyFish exists because another creature reproduced. Fish eat food particles and reproduce after reaching a food threshold. Dolphins hunt fish and reproduce the same way. Manatees are the farmers of the ocean floor, tending to the kelp fields by grazing on plants and seeding new growth through their waste. The result is a system where populations oscillate naturally: too many fish depletes the food supply, slowing reproduction and letting dolphins catch up. Too few fish means dolphins starve and die off, giving the fish room to bounce back.

Fish Evasion

React to predators at 1.5 unit radius, reverse instantly, scatter in random directions. AI updates every frame for responsive dodge. Can hide in kelp or terrain obstacles.

Dolphin Predation

Sprint at 3.5x speed through prey schooling, kill at 0.5 unit contact range. Hunt duration capped at 10s per attempt. Hunger cooldown prevents population collapse.

The predator-prey system isn't perfect - fish don't have complex evasion AI like real schooling behavior. But the simplicity works: the game feels alive because creatures constantly interact, sometimes the player is witnessing a hunt, and sometimes they're watching a lucky fish escape. That dynamic interplay is what makes the ecosystem feel real.

The predator-prey simulator demonstrates food chain dynamics in action. Fish (small amber dots) actively seek and consume food particles (green circles). When a dolphin (blue dot) approaches, fish detect the threat and flee. Both species use energy over time and must feed to reproduce. Dead creatures seed new food. The population chart at the bottom tracks fish and dolphin populations in real time, showing predator-prey cycles as they emerge naturally from individual behaviors.