Ix Dev 2 - Game Engine
Ix Game Engine
I use a custom engine for my games' logic. At a high level, the engine:
Entities
- Uses Entities, but not Components or Systems
- I use archetype-based entities in a sum type AnyEntity:
Loading syntax highlighter...
- I use a single
state.entities: AnyEntity[]array to hold all game entities of all archetypes, but don't access it directly - instead using specialized in-memory indexes (wrapped by anEntityIndexclass) and centralizedaddEntity, removeEntity, queryEntitieshelpers- Adding an entity adds it to state and the EntityIndex wrapper
- The EntityIndex wrapper adds it to a few specialized indexes:
Loading syntax highlighter...
- Removing removes from both as well
- Indexes are rebuilt from the state source-of-truth when changing maps or loading a save
- Entities are queried via a unified
queryEntities(queryDef)function, which picks from indexes as appropriate to optimize the result
Loading syntax highlighter...
Game Loop
- Runs logic via a once-per-frame update function
runGameUpdate(delta, inputWrapper)
Loading syntax highlighter...
Costs and Grants
Items, money, and experience are all given or taken from entities using Bundle objects (aliased as Cost and Grant for readability).
Loading syntax highlighter...
Attributes
Attributes are standardized numeric values on an entity, such as HP, Max HP, Energy, and Cooldown. These are all wrapped in an attributes object, with standardized helpers to add, subtract, and display values appropriately. Attributes may have other attributes linked to them - such as Max HP linked to HP, capping that attribute.
Effects
Abilities, interactions, game logic, and UI elements are all driven by Effects - low-level game-specific primitive operations. As of writing I currently have:
Loading syntax highlighter...
As you can see, these are a mix of UI (message, open screen), entity-specific, and global effects. I try to write all game-specific logic - vs systems or structure - using effects.
UI components support effects (and other game objects) neatly, with a wrapped EffectButton component:
Loading syntax highlighter...
Effects use a standard source-and-targets system through the EffectContext, passed through to all effect appliers:
Loading syntax highlighter...
Effect targets are accessed through a uniform getTargets() function. Some effects hardcode which of source/target it applies to (open screen is agnostic for instance), but most use an overridable affects: EffectTarget. This allows an effect chain to eg damage both the source and target entities for different amounts, or heal the source while damaging the target.