Prototype¶
Intent: Create new objects by cloning an existing configured instance rather than constructing from scratch each time.
Note
The book Game Programming Patterns notes that the classic Prototype design pattern — where each class implements a clone() method — is rarely the best approach in modern games, because most games no longer use a separate class per monster/entity type. The more useful takeaway is the concept of spawning via a template object. In Acron this maps naturally to a factory that reuses a pre-loaded NodePath template, combined with ModelPool for file-level caching.
Acron Mapping¶
Pattern role |
Acron equivalent |
|---|---|
Prototype (template) |
A pre-configured |
Clone (shallow) |
|
Clone (deep / independent) |
|
Spawner |
Factory function that calls copy/instance and applies overrides |
How to Implement¶
Load and fully configure the prototype once at startup:
proto = loader.loadModel('enemy.bam') proto.setScale(1.5) proto.setColorScale(1, 0.2, 0.2, 1)
Choose clone depth:
Independent copy (can be modified without affecting others):
clone = proto.copyTo(render)Shared geometry (position-only variation, cheaper):
clone = proto.instanceTo(render)
Apply per-clone overrides after cloning:
clone.setPos(x, y, z).Attach Python-side state (health, AI data) to a wrapper object that holds a reference to the
NodePath.For
Actor(animated), you must subclass or re-load —Actordoes not supportcopyTo()properly. Use a factory that callsActor(model, anims)each time, relying onModelPoolto share the underlying geometry.
Code Sketch (Python)¶
class EnemySpawner:
def __init__(self):
# Build prototype once
self._proto = loader.loadModel('assets/goblin.bam')
self._proto.setScale(1.0)
def spawn(self, pos, color_scale=(1, 1, 1, 1)):
clone = self._proto.copyTo(render)
clone.setPos(pos)
clone.setColorScale(*color_scale)
return Enemy(node=clone)
class Enemy:
def __init__(self, node):
self.node = node
self.health = 30
def destroy(self):
self.node.removeNode()
Pitfalls¶
copyTo() vs instanceTo():
copyTo()duplicates geometry data — use it when instances need independent render attributes.instanceTo()is cheaper but all instances share the same material state.Actor cloning:
Actor.copyTo()does not copy animation bindings. For animated enemies use a factory that constructs a freshActorper instance;ModelPoolensures the.bamis loaded only once.Prototype visible in scene: after building the prototype, call
proto.detachNode()so it isn’t rendered. Keep a Python reference to prevent garbage collection.