Acron Engine Key Facts

Everything below assumes Python scripting against the Acron C++ core.

Scene Graph

  • All 3D objects live in a tree rooted at render; 2D/UI objects live under render2d.

  • Every node is accessed through a NodePath handle — never manipulate AcronNode directly.

  • Parent-relative transforms: node.setPos(x, y, z), node.setHpr(h, p, r), node.setScale(s).

  • World-space transform: node.getPos(render), node.getMat(render).

  • Attach to scene: node.reparentTo(parent). Remove: node.detachNode() (keeps alive) or node.removeNode() (destroys).

Game Loop

  • ShowBase.run() starts the loop. Never write a manual while True.

  • Tasks registered with taskMgr.add(fn, 'name', sort=N) are called once per frame in ascending sort order.

  • Return task.cont to keep running, task.done to stop.

  • Delta time: globalClock.getDt() or task.dt inside the task function.

  • Deferred single-shot: taskMgr.doMethodLater(seconds, fn, 'name').

Events (Observer / Messenger)

  • messenger.send('event-name', [arg1, arg2]) — fire an event from anywhere.

  • Classes inherit DirectObject and call self.accept('event-name', handler) to subscribe.

  • Unsubscribe: self.ignore('event-name') or self.ignoreAll() (call in every destroy()).

  • Input events are strings: 'w', 'w-up', 'mouse1', 'arrow_left'.

Finite State Machine

  • from direct.fsm.FSM import FSM — inherit, don’t hand-roll.

  • Define enterStateName() / exitStateName() method pairs.

  • Transition: self.request('StateName'). Restrict with defaultTransitions dict.

  • Always call self.cleanup() on destruction.

Animation & Intervals

  • Static models: loader.loadModel('file.bam') → NodePath.

  • Animated models: Actor('model.bam', {'anim': 'anim.bam'}). Play: .loop('anim'), .play('anim'), .stop().

  • Timed sequences: Sequence(LerpPosInterval(node, t, pos), FunctionInterval(fn), Wait(t)).

  • Start: seq.start() / seq.loop(). All intervals managed by ivalMgr.

Memory & Cleanup

  • Nodes are reference-counted. A NodePath not reparented into the scene graph and with no Python reference will be garbage-collected.

  • Pattern: hide inactive objects (node.hide()) rather than destroying and re-creating them (see Object Pool).

  • ModelPool caches model files — loader.loadModel() is safe to call repeatedly with the same path.

Audio

  • Load: loader.loadSfx('file.ogg') (sound effect) / loader.loadMusic('file.ogg') (music).

  • Play: sound.play(). Stop: sound.stop(). Loop: sound.setLoop(True).

  • 3D positional audio: attach an AudioSound3D to a NodePath.

Collision

  • Add a solid to a CollisionNode, reparent to the entity’s root NodePath.

  • Global traverser: base.cTrav = CollisionTraverser().

  • Filter with bitmasks: cn.setFromCollideMask(BitMask32.bit(0)).

  • Handlers: CollisionHandlerPusher (physics response), CollisionHandlerEvent (fire events), CollisionHandlerQueue (manual query).

Useful Globals

Global

Type

Purpose

base

ShowBase

Window, camera, mouse, audio managers

taskMgr

TaskManager

Add / remove / query tasks

messenger

Messenger

Send and receive events

loader

Loader

Load models, textures, sounds

ivalMgr

IntervalManager

Track running intervals

globalClock

ClockObject

Delta time, frame time, frame rate

render

NodePath

Root of the 3D scene graph

render2d

NodePath

Root of the 2D / UI scene graph

camera

NodePath

Default camera node