Skip to content

@carrot/engine-framework-physics ​

ts

Pooled particle physics system for the Carrot engine framework.

Installation ​

bash
npm install @carrot/engine-framework-physics

Architecture / How It Works ​

The package provides NewtonSystem, a GameSystem subclass that manages a pool of NewtonParticle objects. It runs scene-independently - register it on the Game and it ticks every frame.

Particle Lifecycle ​

  1. Particles are pre-allocated in a Pool<NewtonParticle> (from @carrot/collections)
  2. emit(count) spawns particles from the pool
  3. Each frame, update(delta) applies gravity, air friction, position integration, and rotation
  4. Particles die when age >= maxAge (default 100 frames)

Physics Model ​

Per frame, for each alive particle:

  • velocity += gravity then velocity *= airFriction
  • position += velocity * delta
  • rotation += angularVelocity * delta
  • age++, killed when age >= maxAge

This is a simple Newtonian integrator - suitable for particle effects, not rigid body simulation.

Dependencies ​

PackageUsed For
@carrot/engine-frameworkGameSystem base class
@carrot/maths-geometryVector2 for position/velocity
@carrot/collectionsPool and PoolItem for particle pooling

Build ​

bash
npm run build    # runs tsc

Output goes to dist/. Package is ESM ("type": "module").


Usage Guide ​

Pooled particle physics system for the Carrot engine framework.

Import ​

ts
import { NewtonSystem, NewtonParticle } from '@carrot/engine-framework-physics';

Common Patterns ​

1. Basic particle system ​

ts
const newton = new NewtonSystem({
  maxParticles: 500,
  gravity: -9.81,
  airFriction: 0.99,
});

game.addSystem(newton);

2. Emitting particles ​

ts
// Spawn 10 particles from the pool
newton.emit(10);

3. Customizing particles after spawn ​

ts
newton.emit(5);

for (const particle of newton.particles) {
  if (particle.isAlive && particle.age === 0) {
    particle.position = new Vector2(100, 200);
    particle.velocity = new Vector2(
      Math.random() * 100 - 50,
      Math.random() * 200,
    );
    particle.maxAge = 60; // 60 frames lifetime
    particle.angularVelocity = Math.random() * 2 - 1;
  }
}

4. Reading particle state for rendering ​

ts
// In a render behaviour or pipeline stage
for (const particle of newton.particles) {
  if (!particle.isAlive) continue;
  drawParticle(particle.position, particle.rotation, particle.age / particle.maxAge);
}

5. Configuring gravity and friction at runtime ​

ts
// Zero-G mode
newton.gravity = 0;
newton.airFriction = 1.0; // no friction

// Heavy mode
newton.gravity = -20;
newton.airFriction = 0.95;

Carrot