Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Level Objects

Objects are created by creating a folder in level/objects. As each folder corresponds to an object that can be referenced from within Tiled, the name of the folder == the object name as used in Tiled.

From there, an Object must have a Lua file titled main.lua within it. This file is the first file that the engine executes when it loads the object. From here, you can use Lua’s require function to include other files in the same folder (or files in subfolders), and the engine will execute them appropriately, allowing you to split up the object into multiple files. This combination of files, whatever it may be, is the scope in which an object can access/set its own variables. This scope is local to each instance of an object; changes to variables are not shared with objects of the same type.

Each Object has certain variables that are always created by the engine, such as their position and their size. These are presented to scripts as fields within a global variable called Object. This same type is also relevent to an object’s collision callback (see below) as it’s how you get information on what it collides with. The Object global also has functions that can be used with your object (i.e. Object.get_collision_info for checking for an object’s collision with a tile), and the Object type received in the collision function has its own methods that can be executed (this is how objects can communicate in the collision function, they can get/set each other’s variables via Object:get and Object:set). However, these are not mutually exclusive; you can’t use the Object functions on an object you get in the collision function, and you can’t use the Object’s methods on the global Object.

Objects are also currently* responsible for loading textures with Renderer:load_texture. They can draw them manually via Renderer:draw_texture_opt, but the engine will automatically draw objects that don’t override the draw function (see below).

*The plan is to eventually have objects have configuration files which can set this too, allowing for objects that only have a tick function.

When in doubt, see the player object’s main.lua, which has everything wrapped up neatly and can thus serve as good example code.

Callbacks

To give an object functionality, there are several functions (“callbacks”) you can define anywhere within your object’s Lua scope that will get called by the engine appropriately:

These should idomatically be put in main.lua, but they can be placed in other files.

All of them are optional. Your main.lua file can be completely blank (though it does have to exist), resulting in an invisible object that does nothing.

init function

Called upon the object’s creation.

--- @param win Window
--- @param renderer Renderer
function init(win, renderer)
-- ...
end

tick function

Called every tick for every object in the level.

---@param win Window
-- tick function
function tick(win)
-- ...
end

draw function

Called for every object on screen. This is where you draw a texture at your object’s position.

--- @param renderer Renderer
--- @param cameraPos Vec2
function draw(renderer, cameraPos)
-- ...
end

Notice that camera position is passed in. If you want to draw something at your object’s current position, you need to do something like:

-- textureOptions being a TextureOptions in this case.
textureOptions.dest.x = (Object.position.x - cameraPos.x)
textureOptions.dest.y = (Object.position.y - cameraPos.y)

If this function is not present in your script, the above equations will be applied to Object.texture_options, and the object will be drawn automatically using them.

on_collide function

Called upon the object colliding with another object.

---@param obj Object
function on_collide(obj)
-- ...
end