The Xenon Engine

June 30, 2025 ยท View on GitHub

Introduction

The Xenon engine is focused for 2D games. It provides a feature-rich and easy to use interface for developing games.

Documentation

There is an LDoc generated documentation website available in the docs folder. It will provide you with better information.

log (string)

A logging function.

setScene (string)

Sets the current scene.

getScene ()

Gets the current scene name.

clearSceneSprites (string)

Clears the sprites in a scene.

clearScreen ()

Clear the screen and dirty rects.

titleScreen ()

Show the xenon title screen.

setCWD (string)

Set CWD for xenon to reference.

sprite:SetPosition (x, y)

Set the direct position of a sprite.

sprite:GetSize ()

Returns the size of the sprite.

sprite:Move (dx, dy)

Moves the sprite by a delta amount.

sprite:Delete (time)

Delete a sprite after a certain amount of time.

sprite:SetScene (scene)

Sets the sprite's scene.

sprite:SetLayer (layer)

Sets the sprite's layer.

sprite:GetMetadataValue (key)

Gets a metadata value from the sprite. Useful for tracking health or other stats.

sprite:SetMetadataValue (key, value)

Sets a metadata value to the sprite. Useful for tracking health or other stats.

sprite:AttachOnSpriteClick (event, func)

Attach a callback function to an event.

sprite:SmoothPosition (x, y, time)

Linearly move a sprite to a direct position.

sprite:SmoothMove (x, y, time)

Linearly move a sprite by a delta amount.

sprite:SetIdle (isIdle)

Set a sprite's idle value.

sprite:FireAnimation (animation)

Fire a sprite's animation.

newSpriteRef (string, string)

Creates a new animated sprite from a reference file.

newStillSpriteRef (string, string)

Creates a new static sprite from a reference file.

inputLoop ()

Starts the input event processing loop.

registerKey (string, function)

Registers a callback for key events.

getKeyState (string)

Gets the current state of a key.

clearKeyTransients ()

Clears transient key states (press/release).

createMovementSystem (table[, table], options)

Creates a movement system for a sprite.

createProjectileSystem (source, options)

Creates a projectile system for a sprite

createCollisionGroup ()

Creates a collision group for sprite collision detection.

update (number)

Updates the game state and renders sprites.

runGame (function)

Runs the main game loop with the provided update function.

Explanation

Let's go over this small game.

local xenon = require("/xenon_engine/main")

local player = xenon.newSpriteRef("player", "testgame/assets/spriterefs/example.spr")
player:SetPosition(10, 10)
player:SetIdle(true)

local movementSystem = xenon.createMovementSystem(player, {
    speed = 5,
    moveInterval = 0.10
})

local projectileSystem = xenon.createProjectileSystem(player, {
    spritePath = "testgame/assets/spriterefs/fire.spr",
    speed = 8,
    lifetime = 3,
    layer = 1
})

xenon.registerKey("e", function(state)
    if state == "press" then
        player:FireAnimation("extraAnim1")
        projectileSystem:Fire(player.facing)
    end
end)

local function gameLoop()
    while true do
        movementSystem:Update()
        
        projectileSystem:Update()
        
        xenon.update(0.05)
        sleep(0.05)
    end
end

xenon.runGame(gameLoop)

example.spr

{
    allAnim = {
        duration = 0.3, 
        anims = {"../sprites/example/allAnim1.nfp", "../sprites/example/allAnim2.nfp"}
    },
    allIdle = {
        duration = 1, 
        anims = {"../sprites/example/allIdle.nfp"}
    },
    extraAnim1 = {
        allDirections = true,
        duration = 0.5,
        anims = {"../sprites/example/extraAnim1.nfp"},
        loop = false
    }
}

As a small note: Individual forward, left, etc. and idle animations can be provided if you would prefer a different animation for each direction. This tutorial uses the allAnim and allIdle feature to make this breifer.

fire.spr (stillSprite)

{
    sprite = "../sprites/fire/fire.nfp"
}

To use the xenon engine, you must do as the game does: local xenon = require("/xenon_engine/main").

local player = xenon.newSpriteRef("player", "testgame/assets/spriterefs/example.spr")

Creates a new sprite "player" which uses the sprite reference example.spr

player:SetPosition(10, 10)
player:SetIdle(true)

Sets the position and idle of the sprite. See the documentation for more information.

local movementSystem = xenon.createMovementSystem(player, {
    speed = 5,
    moveInterval = 0.10
})

Instead of writing a long chain of registerKeys for getting input, a simple createMovementSystem function exists that automatically allows W, A, S and D to move the sprite.

local projectileSystem = xenon.createProjectileSystem(player, {
    spritePath = "testgame/assets/spriterefs/fire.spr",
    speed = 8,
    lifetime = 3,
    layer = 1
})

This creates a reusable projectile system, so that projectileSystem:Fire call be called and used easily many times.

xenon.registerKey("e", function(state)
    if state == "press" then
        player:FireAnimation("extraAnim1")
        projectileSystem:Fire(player.facing)
    end
end)

This registers the "e" key to fire the extra animation and fire the projectile.

local function gameLoop()
    while true do
        movementSystem:Update()
        projectileSystem:Update()
        
        xenon.update(0.05)
        sleep(0.05)
    end
end

xenon.runGame(gameLoop)

This last part is the game and render loop. It is almost entirely handled internally, so it is very compact.