Queries

Most roguelikes involve systems where you need to efficiently find actors or entities with certain components—such as all enemies, or everyone at a specific location. Prism provides a built-in query system to make this easy and efficient.

Basic usage

To start a query, call IQueryable.query with the component types you want to require. This interface is implemented by Level, MapBuilder, and ActorStorage.

local query = level:query(prism.components.Controller, prism.components.Collider)

This creates a Query object. You can add more required components later with Query:with().

query:with(prism.components.Senses)

You can also restrict the query to a single tile with Query:at().

query:at(10, 5)

Iterating over results

Use Query:iter() to get an iterator over matching actors and their components:

for actor, controller, collider, senses in query:iter() do
    -- do stuff
end

Alternatively, use Query:each() to apply a function to each match:

query:each(function(actor, controller, collider, senses)
    -- do stuff
end)

Gathering results

To gather results into a list, use Query:gather():

local results = query:gather()

for _, actor in ipairs(results) do
    -- Do something with them
end

Getting a single result

Use Query:first() to get the first match:

local actor, playerController = level:query(prism.components.PlayerController):first()

Good for singleton components like if your game has only one actor with a PlayerController. First calls iter behind the scenes and discards the iterator after the first result.

Putting it together

Here’s an example of it all put together:

local query = level:query(prism.components.Controller, prism.components.Senses)
    :with(prism.components.Senses)
    :at(x, y)

for actor, controller, collider, senses in query:iter() do
    -- do stuff
end

Note

Query performance is optimized internally based on your filters. Position-based queries and single-component queries are particularly fast.