The destruction of the objects are handled by the garbage-collector metamethod. (Does this make sense? This means that an out-of-scope object will stay visible in game until garbage collection.)

The components of the Entity Component System are not pure-data members, but instead derived classes of a specific base class. (For example Renderable for all renderable objects, Transformable for all movable objects.) Because of this it's not a conventional ECS, but more like a OO + ECS, but up to now it works wonders for me.

I am concerned about the use of design patterns, about the ease-of-use of the API, its scalability and error-proneness.

-- All initing must be done here
function init( instance ) -- the parameter is the engine api
    -- Save API into Engine variable for later use
    Engine = instance

    -- Create separate apis for accessing different parts of engine using the
    -- Engine passed to us
    -- And make them all global for further use.

    -- ECS - Entity component system interaction.
    ECS = Engine:CreateECSAPI()

    -- Graphics interaction.
    Graphics = Engine:CreateGraphicsAPI()

    -- Input handling.
    Input = Engine:CreateInputAPI()

    -- Setup mouse callback
    Input:AddMouseCallback( "OnMouse" )

    -- Get index of the forward renderable component.
    ForwardComponent = ECS:GetComponentIndex( "renderable_forward" )

    -- Create text with given text and font size.
    Text = Graphics:CreateTextObject( "The quick brown fox is lazy.", 40 )
    Text:SetColor( { 1, 1, 1 } )
    Text:SetPosition( { 0, 0.5 } )

    -- Create a fullscreen rectanlge as background.
    Rect = Graphics:CreateRectangle( { 1.0, 1.0 } )
    Rect:SetSize( { 2.0, 2.0 } )
    Rect:SetPosition( { 0.0, 0.0 } )

    -- Entity must be created for anything to be processed by the engine.
    -- Processed can mean rendered/updated/simulated/synchronized.
    TextEntity = ECS:CreateEntity()
    RectEntity = ECS:CreateEntity()

    -- To render something in 2D we must add a renderable to its 
    -- renderable_forward component.
    TextEntity:SetComponent( ForwardComponent, Text )
    RectEntity:SetComponent( ForwardComponent, Rect )

    -- Current time
    Time = 0

    Clicks = { "next" = 1 }


-- If we click, it places a "Click" text there.
function OnMouse( type, x, y )
    if type == Input.Button then
        local entity = ECS:CreateEntity()
        local textobject = Graphics:CreateTextObject( "Click" )
        textobject:SetPosition( { x, y } )

        entity:SetComponent( ForwardComponent, textobject )

        local next = Clicks["next"]
        Clicks[next] = { entity, textobject }
        Clicks["next"] = next + 1

--Called each frame
--dt is the time since last update in seconds.
--use it for frame-independent movement
function update( dt )

    -- Save current time by storing the time elapsed.
    Time = Time + dt
    local s = math.sin( Time )
    Rect.SetColor( { s, s, s } )

  • \$\begingroup\$ The variable scope in lua, by default, is global. Use local everywhere you create variables unless global is needed. \$\endgroup\$ – hjpotter92 Mar 30 '15 at 10:44
  • \$\begingroup\$ @hjpotter92 I see no instance where something is global that shouldn't be(tough some are not used in this small example). Could you pinpoint which one you mean? \$\endgroup\$ – akaltar Mar 30 '15 at 12:06
  • \$\begingroup\$ The very first statement: Engine = instance \$\endgroup\$ – hjpotter92 Mar 30 '15 at 12:20
  • \$\begingroup\$ @hjpotter92 While it may not be clear, thats the "handle" to the whole API, so if I need to access it anywhere else in my code(like changing the view matrix, or some other global thing), then I will need it, so its global. \$\endgroup\$ – akaltar Mar 30 '15 at 12:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.