API
Ark's public API.
World
The World is the central data storage for Entities, Components and Resources.
Ark.World — Method
World(
comp_types::Type...;
initial_capacity::Int=128,
allow_mutable::Bool=false,
)Creates a new, empty World for the given component types.
All component types that will be used with the world must be specified. This allows Ark to use Julia's compile-time method generation to achieve the best performance.
For each component type, an individual storage mode can be set. See also VectorStorage and StructArrayStorage.
Additional arguments can be used to allow mutable component types (forbidden by default and discouraged) and an initial capacity for entities in archetypes.
Arguments
comp_types: The component types used by the world.initial_capacity: Initial capacity for entities in each archetype and in the entity index.allow_mutable: Allows mutable components. Use with care, as all mutable objects are heap-allocated in Julia.
Examples
A World where all components use the default storage mode:
world = World(
Position,
Velocity,
)A World with individually configured storage modes:
world = World(
Position => StructArrayStorage,
Velocity => StructArrayStorage,
Health => VectorStorage,
)Ark.reset! — Function
reset!(world::World)Removes all entities and resources from the world, and un-registers all observers. Does NOT free reserved memory or remove archetypes.
Can be used to run systematic simulations without the need to re-allocate memory for each run. Accelerates re-populating the world by a factor of 2-3.
Ark.is_locked — Function
is_locked(world::World)::BoolReturns whether the world is currently locked for modifications.
Ark.StructArrayStorage — Type
StructArrayStorageMarks component types for using StructArray-like storage mode in the world constructor.
In StructArray storages, mutable components are not allowed.
See also VectorStorage.
Example
world = World(
Position => StructArrayStorage,
Velocity => StructArrayStorage,
)Ark.VectorStorage — Type
VectorStorageMarks component types for using Vector storage mode in the world constructor. As this is the default storage mode if the storage type is not specified.
See also StructArrayStorage.
Example
world = World(
Position => VectorStorage,
Velocity => VectorStorage,
)Entities
Entities are the "game objects" or "model entities". An entity if just an ID with a generation, but Components can be attached to an entity.
Ark.Entity — Type
EntityEntity identifier.
Entities can be constructed using a World via new_entity!.
Entities can be safely stored in components and resources.
Ark.zero_entity — Constant
const zero_entity::EntityThe reserved zero Entity value. Can be used to represent "no entity"/"nil".
Ark.new_entity! — Function
new_entity!(world::World, values::Tuple)::EntityCreates a new Entity with the given component values. Types are inferred from the values.
Example
entity = new_entity!(world, (Position(0, 0), Velocity(1, 1)))Ark.new_entities! — Function
new_entities!(world::World, n::Int, defaults::Tuple; iterate::Bool=false)::Union{Batch,Nothing}Creates the given number of Entity, initialized with default values. Component types are inferred from the provided default values.
If iterate is true, a Batch iterator over the newly created entities is returned that can be used for initialization.
See also new_entities! for creating entities from component types.
Arguments
world::World: TheWorldinstance to use.n::Int: The number of entities to create.defaults::Tuple: A tuple of default values for initialization, like(Position(0, 0), Velocity(1, 1)).iterate::Bool: Whether to return a batch for individual entity initialization.
Examples
Create 100 entities from default values:
new_entities!(world, 100, (Position(0, 0), Velocity(1, 1)))Create 100 entities from default values and iterate them:
for (entities, positions, velocities) in new_entities!(world, 100, (Position(0, 0), Velocity(1, 1)); iterate=true)
for i in eachindex(entities)
positions[i] = Position(rand(), rand())
end
endnew_entities!(world::World, n::Int, comp_types::Tuple)::BatchCreates the given number of Entity.
Returns a Batch iterator over the newly created entities that should be used to initialize components. Note that components are not initialized/undef unless set in the iterator!
See also new_entities! for creating entities from default values.
Arguments
world::World: TheWorldinstance to use.n::Int: The number of entities to create.comp_types::Tuple: Component types for the new entities, like(Position, Velocity).
Example
Create 100 entities from component types and initialize them:
for (entities, positions, velocities) in new_entities!(world, 100, (Position, Velocity))
for i in eachindex(entities)
positions[i] = Position(rand(), rand())
velocities[i] = Velocity(1, 1)
end
endArk.remove_entity! — Function
remove_entity!(world::World, entity::Entity)Removes an Entity from the World.
Example
remove_entity!(world, entity)Ark.copy_entity! — Function
copy_entity!(
world::World,
entity::Entity;
add::Tuple=(),
remove::Tuple=(),
mode=:copy,
)Copies an Entity, optionally adding and/or removing components.
Mutable and non-isbits components are shallow copied by default. This can be changed with the mode argument.
Arguments
world: TheWorldinstance to query.entity::Entity: The entity to copy.add::Tuple: Components to add, likewith=(Health(0),).remove::Tuple: Component types to remove, like(Position,Velocity).mode::Tuple: Copy mode for mutable and non-isbits components. Modes are :ref, :copy, :deepcopy.
Examples
Simple copy of an entity:
entity1 = copy_entity!(world, entity)Copy an entity, adding and removing some components in the same operation:
entity2 = copy_entity!(world, entity;
add=(Health(100),),
remove=(Position, Velocity),
)Ark.is_alive — Function
is_alive(world::World, entity::Entity)::BoolReturns whether an Entity is alive.
Ark.is_zero — Function
is_zero(entity::Entity)::BoolReturns whether an Entity is the reserved zero_entity.
Components
Components contain the data associated with Entities.
Ark.get_components — Function
get_components(world::World, entity::Entity, comp_types::Tuple)Get the given components for an Entity. Components are returned in a tuple.
Example
pos, vel = get_components(world, entity, (Position, Velocity))Ark.has_components — Function
has_components(world::World, entity::Entity, comp_types::Tuple)::BoolReturns whether an Entity has all given components.
Example
has = has_components(world, entity, (Position, Velocity))Ark.set_components! — Function
set_components!(world::World, entity::Entity, values::Tuple)Sets the given component values for an Entity. Types are inferred from the values. The entity must already have all these components.
Example
set_components!(world, entity, (Position(0, 0), Velocity(1, 1)))Ark.add_components! — Function
add_components!(world::World, entity::Entity, values::Tuple)Adds the given component values to an Entity. Types are inferred from the values.
Example
add_components!(world, entity, (Health(100),))Ark.remove_components! — Function
remove_components!(world::World, entity::Entity, comp_types::Tuple)Removes the given components from an Entity.
Example
remove_components!(world, entity, (Position, Velocity))Ark.exchange_components! — Function
exchange_components!(world::World{CS,CT,N}, entity::Entity; add::Tuple, remove::Tuple)Adds and removes components on an Entity. Types are inferred from the add values.
Example
exchange_components!(world, entity;
add=(Health(100),),
remove=(Position, Velocity),
)Queries
Queries are used to filter and process Entities with a certain set of Components.
Ark.Query — Method
Query(
world::World,
comp_types::Tuple;
with::Tuple=(),
without::Tuple=(),
optional::Tuple=(),
exclusive::Bool=false
)Creates a query.
A query is an iterator for processing all entities that match the query's criteria. The query itself iterates matching archetypes, while an inner loop or broadcast operations must be used to manipulate individual entities (see example below).
A query locks the World until it is fully iterated or closed manually. This prevents structural changes like creating and removing entities or adding and removing components during the iteration.
See the user manual chapter on Queries for more details and examples.
Arguments
world: TheWorldinstance to query.comp_types::Tuple: Components the query filters for and provides access to.with::Tuple: Additional components the entities must have.without::Tuple: Components the entities must not have.optional::Tuple: Additional components that are optional in the query.exclusive::Bool: Makes the query exclusive in base andwithcomponents, can't be combined withwithout.
Example
for (entities, positions, velocities) in Query(world, (Position, Velocity))
for i in eachindex(entities)
pos = positions[i]
vel = velocities[i]
positions[i] = Position(pos.x + vel.dx, pos.y + vel.dy)
end
endArk.close! — Method
close!(q::Query)Closes the query and unlocks the world.
Must be called if a query is not fully iterated.
Ark.count_entities — Method
count_entities(q::Query)Returns the number of matching entities in the query.
Does not iterate or close! the query.
Base.length — Method
length(q::Query)Returns the number of matching archetypes with at least one entity in the query.
Does not iterate or close! the query.
Ark.Entities — Type
EntitiesArchetype column for entities. Can be iterated and indexed like a Vector.
Used in query iteration.
Ark.@unpack — Macro
@unpack ...Unpacks the tuple returned from a Query during iteration into field vectors. Field vectors are particularly useful for StructArrayStorages, but can also be used with VectorStorages, although those are currently not equally efficient in broadcasted operations.
Columns for components without fields, like primitives or label components, fall through @unpack unaltered.
See also unpack(::StructArrayView) and unpack(::FieldViewable).
Example
for columns in Query(world, (Position, Velocity))
@unpack entities, (x, y), (dx, dy) = columns
@inbounds x .+= dx
@inbounds y .+= dy
endArk.unpack — Function
unpack(a::StructArrayView)Unpacks the components (i.e. field vectors) of a StructArrayStorage column returned from a Query. See also @unpack.
unpack(a::FieldViewable)Unpacks the components (i.e. field vectors) of a VectorStorage column returned from a Query. See also @unpack.
Resources
Resources are singleton-like data structures that appear only once in a World and are not associated to an Entity.
Ark.get_resource — Function
get_resource(world::World, res_type::Type{T})::TGet the resource of type T from the world.
Ark.has_resource — Function
has_resource(world::World, res_type::Type{T})::BoolCheck if a resource of type T is in the world.
Ark.add_resource! — Function
add_resource!(world::World, res::T)::TAdd the given resource to the world. Returns the newly added resource.
Ark.set_resource! — Function
set_resource!(world::World, res::T)::TOverwrites an existing resource in the world. Returns the newly overwritten resource.
Ark.remove_resource! — Function
remove_resource!(world::World, res_type::Type{T})::TRemove the resource of type T from the world. Returns the removed resource.
Batch
An iterator over entities that were created or modified using batch operations. Behaves like a Query and can be used for component initialization.
Ark.Batch — Type
BatchA batch iterator. This is returned from batch operations and serves for initializing newly added components or otherwise processing the manipulated entities.
The batch itself iterates matching archetypes just like a Query, while an inner loop or broadcast operations must be used to manipulate individual entities.
A batch locks the World until it is fully iterated or closed manually. This prevents structural changes like creating and removing entities or adding and removing components during the iteration.
Ark.close! — Method
close!(b::Batch)Closes the batch iterator and unlocks the world.
Must be called if a batch is not fully iterated.
Ark.count_entities — Method
count_entities(b::Batch)Returns the number of entities in the batch.
Does not iterate or close! the batch.
Base.length — Method
length(b::Batch)Returns the number of archetypes in the batch. For batch entity creation, the number of archetype is always 1.
Does not iterate or close! the batch.
Event system
The event system allows user code to react on structural changes like entity creation and removal and component addition and removal. Further, custom events can be defined and emitted.
Ark.EventType — Type
EventTypeType for built-in and custom events. See EventRegistry for creating custom event types.
Built-in event types
OnCreateEntity: Event emitted when a new entity is created.OnRemoveEntity: Event emitted when an entity is removed from the World.OnAddComponents: Event emitted when components are added to an entity.OnRemoveComponents: Event emitted when components are removed from an entity.
Ark.EventRegistry — Type
EventRegistryServes for creating custom event types.
Ark.EventRegistry — Method
EventRegistry()Creates a new EventRegistry.
Ark.new_event_type! — Function
new_event_type!(reg::EventRegistry, symbol::Symbol)Creates a new custom EventType. Custom event types are best stored in global constants.
The symbol is only used for printing.
Example
registry = EventRegistry()
const OnGameOver = new_event_type!(registry, :OnGameOver)Ark.Observer — Type
ObserverObserver for reacting on built-in and custom events.
See observe! for details. See EventType for built-in, and EventRegistry for custom event types.
Ark.observe! — Function
observe!(
fn::Function,
world::World,
event::EventType,
components::Tuple=();
with::Tuple=(),
without::Tuple=(),
exclusive::Bool=false,
register::Bool=true,
)Creates an Observer and (optionally, default) registers it.
See EventType for built-in, and EventRegistry for custom event types.
Arguments
fn::Function: A callback function to execute when a matching event is received. Can be used via adoblock.world::World: The World to observe.event::EventType: The EventType to observe.components::Tuple=(): The component types to observe. Must be empty forOnCreateEntityandOnRemoveEntity.with::Tuple=(): Components the entity must have.without::Tuple=(): Components the entity must not have.exclusive::Bool=false: Makes the observer exclusive for entities that have exactly the components given bewith.register::Bool=true: Whether the observer is registered immediately. Alternatively, register later with observe!
Example
observe!(world, OnAddComponents, (Position, Velocity); with=(Altitude,)) do entity
println(entity)
endobserve!(world::World, observer::Observer; unregister::Bool=false)Registers or un-registers the given Observer. Note that observers created with observe! are automatically registered by default.
Ark.emit_event! — Function
emit_event!(world::World, event::EventType, entity::Entity, components::Tuple=())Emits a custom event for the given EventType, Entity and optional components. The entity must have the given components. The entity can be the reserved zero_entity.
world::World: The World to emit the event.event::EventType: The EventType to emit.entity::Entity: The Entity to emit the event for.components::Tuple=(): The component types to emit the event for. Optional.
Example
emit_event!(world, OnCollisionDetected, entity, (Position, Velocity))Index
Ark.zero_entityArk.BatchArk.EntitiesArk.EntityArk.EventRegistryArk.EventRegistryArk.EventTypeArk.ObserverArk.QueryArk.QueryArk.StructArrayStorageArk.VectorStorageArk.WorldArk.WorldArk.add_components!Ark.add_resource!Ark.close!Ark.close!Ark.copy_entity!Ark.count_entitiesArk.count_entitiesArk.emit_event!Ark.exchange_components!Ark.get_componentsArk.get_resourceArk.has_componentsArk.has_resourceArk.is_aliveArk.is_lockedArk.is_zeroArk.new_entities!Ark.new_entity!Ark.new_event_type!Ark.observe!Ark.remove_components!Ark.remove_entity!Ark.remove_resource!Ark.reset!Ark.set_components!Ark.set_resource!Ark.unpackBase.lengthBase.lengthArk.@unpack