Skip to content

Procedural Content Generation

Procedural content means building or arranging scene objects from code instead of placing everything by hand in the editor. Lemonate supports this through typed Sg* creators, the Loader module, and Prefabs.

When to use which tool

Approach Best for
SgBox.create, SgSphere.create Simple primitives, blocking volumes, debug geometry
SgMesh.create Placing imported mesh items at many positions
SgPrefab.create Reusable designed hierarchies (enemies, props)
SgTerrain.create Heightmap-based landscapes
SgGridMap.create Tile-based levels from grid map items

End-to-end example

This behaviour builds a small scene in init() using await for sequential loading. See Promises and Await for async rules.

local Loader = require 'engine/loader'
local Material = require 'engine/items/material'
local SgCamera = require 'engine/sceneobjects/sgcamera'
local SgLightsource = require 'engine/sceneobjects/sglightsource'
local SgSphere = require 'engine/sceneobjects/sgsphere'
local SgBox = require 'engine/sceneobjects/sgbox'
local Transform = require 'engine/math/transform'
local Vector3 = require 'engine/math/vector3'
local Color = require 'engine/data/color'

local ProcGen = Class.new(Behaviour)

function ProcGen:init()
    await(SgCamera.create({
        active = true,
        transform = Transform.new(Vector3.new(0, 2, 8)),
        type = SgCamera.Projection.Perspective,
        tags = {"mainCamera"},
    }))

    local wood = await(Loader.loadImage("/resources/textures/wood"))
    local material = await(Material.create({ albedoMap = wood }))

    await(SgBox.create({
        name = "Ground",
        width = 10, height = 0.2, depth = 10,
        transform = Transform.new(Vector3.new(0, -0.1, 0)),
        material = material,
    }))

    for i = 1, 4 do
        await(SgSphere.create({
            name = "Ball" .. i,
            radius = 0.5,
            transform = Transform.new(Vector3.new(i * 1.5, 0.5, 0)),
            material = material,
        }))
    end

    await(SgLightsource.create({
        type = SgLightsource.LightType.Directional,
        intensity = 5,
        color = Color.new(255, 255, 255),
    }))
end

return ProcGen

Grid-based levels

For tile maps, load a grid map item and create an SgGridMap:

local SgGridMap = require 'engine/sceneobjects/sggridmap'

local map = await(Loader.loadGridMap("/resources/gridmaps/level1"))
await(SgGridMap.create({ gridMap = map }))

Terrain

Heightmap terrain is created with SgTerrain and linked heightmap/material items. See SgTerrain.

Tips

  • Cache loaded items in init(); do not reload every frame.
  • Parent spawned objects under a SgGroup for easier cleanup.
  • Use Scene Graph for find/tag/layer patterns after generation.
  • Full type-specific options are in the SceneObject reference.

Further reading