PooledSpawner

local PooledSpawner = require("encompass").PooledSpawner

A PooledSpawner is a special kind of Spawner which utilizes object pooling. Instead of creating and destroying Entities at runtime, the PooledSpawner generates a fixed amount of a special kind of Entity called a PooledEntity at initialization time, and then handles them appropriately when they are deactivated. This pattern is useful for entities with components that are expensive to generate at runtime.

A pool overflow callback is called when there are no more inactive entities available in the pool. There are four types of pool overflow behaviors included by encompass, but you are free to define your own as well.

Unlike other types of engines, it is OK to read from PooledEntities in a PooledSpawner in the spawn method.

Note: it is an error to call destroy() on a PooledEntity.

Overflow Behavior Reference

PooledSpawner.OverflowBehaviors.fallible

Does nothing. The default behavior.

PooledSpawner.OverflowBehaviors.cycle

Takes an arbitrary active element and calls it to be spawned.

PooledSpawner.OverflowBehaviors.expand

Expands the pool count by 1 and generates a new entity.

PooledSpawner.OverflowBehaviors.throw

Calls a custom throw(spawner) callback on the PooledSpawner.

Function Reference

PooledSpawner.define(name, message_type, pool_count, overflow_behavior)
Arguments:
  • name (string) – The name of the PooledSpawner prototype.
  • message (prototype) – A Message prototype that should be tracked by the PooledSpawner.
  • pool_count (number) – The number of entities that should be generated and placed in the pool at initialization time.
  • overflow_behavior (function) – Optional. A function that is called when there are no more inactive entities available in the pool, and an entity is requested to be activated. The function should take the PooledSpawner as an argument and return an entity, or nil if a new entity should not be activated. If no argument is passed, defaults to PooledSpawner.OverflowBehavior.fallible

Defines a PooledSpawner that will track the given Message prototype.

Example:

local PooledSpawner = require('encompass').PooledSpawner
local PhysicsParticleSpawner = PooledSpawner.define(
    'PhysicsParticleSpawner',
    PhysicsParticleSpawnMessage,
    PARTICLE_MAX,
    PooledSpawner.OverflowBehaviors.cycle
)
PooledSpawner:generate(entity)
Arguments:
  • entity (Entity) – A new instance of PooledEntity.

This callback function runs when the PooledSpawner is added to the World at initialization time. It runs n times, where n is the given pool count.

The programmer must override this function or an error will be thrown.

Example:

function ParticleSpawner:generate(particle_entity)
    particle_entity:add_component(VelocityComponent, { x = 10, y = 10 })
end

If the pool count were 50, the ParticleSpawner would create 50 of these entities and add them to the inactive pool at initialization time.

PooledSpawner:spawn(entity, message)
Arguments:
  • entity (Entity) – A reference to the entity that is to be activated.
  • message (Message) – A reference to a message that has been tracked by the PooledSpawner.

This callback is triggered when a Message of the specified prototype is produced by a Detecter. The programmer must override this function or an error will be thrown.

Example:

function PhysicsParticleSpawner:spawn(particle_entity, physics_particle_spawn_message)
    local position = physics_particle_spawn_message.position
    local velocity = physics_particle_spawn_message.velocity

    local transform_component = particle_entity:get_component(TransformComponent)
    local velocity_component = particle_entity:get_component(VelocityComponent)
    local collision_component = particle_entity:get_component(PhysicsComponent)
    local body = collision_component.body

    transform_component.position = position
    velocity_component.linear = velocity
    collision_component.x_position = position.x
    collision_component.y_position = position.y
    collision_component.linear_velocity = velocity:clone()
    body:setX(position.x)
    body:setY(position.y)
    body:setLinearVelocity(velocity:unpack())

    if particle_entity:has_component(CreateMessageTimerComponent) then
        particle_entity:get_component(CreateMessageTimerComponent).time = 10
    else
        particle_entity:add_component(CreateMessageTimerComponent, {
            time = 10,
            message_to_create = DeactivateMessage,
            message_args = { entity = particle_entity }
        })
    end
end