API

Ark's public API.

World

The World is the central data storage for Entities, Components and Resources.

Ark.WorldMethod
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,
)
source
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.

source
Ark.is_lockedFunction
is_locked(world::World)::Bool

Returns whether the world is currently locked for modifications.

source
Ark.StructArrayStorageType
StructArrayStorage

Marks 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,
)
source
Ark.VectorStorageType
VectorStorage

Marks 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,
)
source

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.new_entity!Function
new_entity!(world::World, values::Tuple)::Entity

Creates 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)))
source
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: The World instance 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
end
source
new_entities!(world::World, n::Int, comp_types::Tuple)::Batch

Creates 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: The World instance 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
end
source
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: The World instance to query.
  • entity::Entity: The entity to copy.
  • add::Tuple: Components to add, like with=(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),
)
source

Components

Components contain the data associated with Entities.

Ark.get_componentsFunction
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))
source
Ark.has_componentsFunction
has_components(world::World, entity::Entity, comp_types::Tuple)::Bool

Returns whether an Entity has all given components.

Example

has = has_components(world, entity, (Position, Velocity))
source
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)))
source
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),))
source
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))
source
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),
)
source

Queries

Queries are used to filter and process Entities with a certain set of Components.

Ark.QueryMethod
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: The World instance 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 and with components, can't be combined with without.

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
end
source
Ark.close!Method
close!(q::Query)

Closes the query and unlocks the world.

Must be called if a query is not fully iterated.

source
Ark.count_entitiesMethod
count_entities(q::Query)

Returns the number of matching entities in the query.

Does not iterate or close! the query.

Note

The time complexity is linear with the number of archetypes in the query's pre-selection. It is equivalent to iterating the query's archetypes and summing up their lengths.

source
Base.lengthMethod
length(q::Query)

Returns the number of matching archetypes with at least one entity in the query.

Does not iterate or close! the query.

Note

The time complexity is linear with the number of archetypes in the query's pre-selection.

source
Ark.EntitiesType
Entities

Archetype column for entities. Can be iterated and indexed like a Vector.

Used in query iteration.

source
Ark.@unpackMacro
@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
end
source
Ark.unpackFunction
unpack(a::StructArrayView)

Unpacks the components (i.e. field vectors) of a StructArrayStorage column returned from a Query. See also @unpack.

source
unpack(a::FieldViewable)

Unpacks the components (i.e. field vectors) of a VectorStorage column returned from a Query. See also @unpack.

Note

Setting values on unpacked non-isbits fields of immutable components has a certain overhead, as the underlying struct needs to be reconstructed and written to memory. See

source

Resources

Resources are singleton-like data structures that appear only once in a World and are not associated to an Entity.

Ark.get_resourceFunction
get_resource(world::World, res_type::Type{T})::T

Get the resource of type T from the world.

source
Ark.has_resourceFunction
has_resource(world::World, res_type::Type{T})::Bool

Check if a resource of type T is in the world.

source
Ark.add_resource!Function
add_resource!(world::World, res::T)::T

Add the given resource to the world. Returns the newly added resource.

source
Ark.set_resource!Function
set_resource!(world::World, res::T)::T

Overwrites an existing resource in the world. Returns the newly overwritten resource.

source
Ark.remove_resource!Function
remove_resource!(world::World, res_type::Type{T})::T

Remove the resource of type T from the world. Returns the removed resource.

source

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.BatchType
Batch

A 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.

source
Ark.close!Method
close!(b::Batch)

Closes the batch iterator and unlocks the world.

Must be called if a batch is not fully iterated.

source
Ark.count_entitiesMethod
count_entities(b::Batch)

Returns the number of entities in the batch.

Does not iterate or close! the batch.

Note

The time complexity is linear with the number of archetypes in the batch. For batch entity creation, the number of archetype is always 1.

source
Base.lengthMethod
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.

source

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.EventTypeType
EventType

Type 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.
source
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)
source
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 a do block.
  • world::World: The World to observe.
  • event::EventType: The EventType to observe.
  • components::Tuple=(): The component types to observe. Must be empty for OnCreateEntity and OnRemoveEntity.
  • 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 be with.
  • 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)
end
source
observe!(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.

source
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))
source

Index