Card 07/ 08
Practice: Sorting Particle State Into Shared and Per-Particle
Colour, sprite, position, velocity and texture; which belong in the flyweight?
A particle system is a natural Flyweight, and this exercise asks you to sort its state and then build it. A game animates ten thousand particles, each either a spark or a puff of smoke. Every spark has the same colour, sprite and texture, and so does every puff. Each particle has its own position and velocity, which change every frame.
- Sort colour, sprite, texture, position and velocity into intrinsic and extrinsic.
- Write the flyweight and the particle that holds it.
- How many flyweight objects do ten thousand particles need?
- Should the flyweight be mutable, so the game can change a particle's colour when it fades?
Show a solution
| Field | Kind | Why |
|---|---|---|
| Colour | Intrinsic | The same for every particle of one type |
| Sprite | Intrinsic | The same for every particle of one type |
| Texture | Intrinsic | The same for every particle of one type |
| Position | Extrinsic | Different for each particle, and changes every frame |
| Velocity | Extrinsic | Different for each particle |
import random
from dataclasses import dataclass
@dataclass(frozen=True)
class ParticleType:
name: str
colour: str
sprite: str
texture: str
@dataclass
class Particle:
kind: ParticleType
x: float
y: float
dx: float
dy: float
def move(self) -> None:
self.x += self.dx
self.y += self.dy
types = {
"spark": ParticleType("spark", "orange", "spark.png", "glow"),
"smoke": ParticleType("smoke", "grey", "puff.png", "soft"),
}
rng = random.Random(7)
particles = [
Particle(types[rng.choice(["spark", "smoke"])], 0.0, 0.0, rng.uniform(-1, 1), rng.uniform(0, 2))
for _ in range(10_000)
]
for particle in particles:
particle.move()
print(f"particles: {len(particles)}")
print(f"particle types: {len({id(p.kind) for p in particles})}")
print(f"sparks: {sum(p.kind is types['spark'] for p in particles)}")particles: 10000
particle types: 2
sparks: 4983Ten thousand particles need two flyweights, one per type, as the count of distinct objects shows. The flyweight must not be mutable: changing the colour on a shared ParticleType would fade every spark at once. A fading colour differs per particle, so it is extrinsic, and belongs on Particle beside the position.
← → move through sections and cards