Overview

SCM is a compact engine built for fast iteration and predictable runtime behavior. The core is native and performance oriented. Gameplay logic and UI are in Lua.

Goals

Keep the workflow simple, reduce boilerplate, and make small to mid sized projects easy to ship without an editor dependency.

Workflow

Scenes are stored as JSON, assets live in folders, and scripts are plain Lua files. You edit text, run the game, and iterate quickly.

Quick Start

Minimal Layout

Project/
  Scenes/
    main.scene.json
  Scripts/
    main.lua
  Assets/

First Scene

The engine looks for Scenes/main.scene.json. If it is missing, it can create a default scene.

First Script

local M = {}

function M.oninit()
    Print("init")
end

function M.onupdate()
    -- logic
end

return M

Run

Build with the batch script and launch the executable. The scene will load and the Lua entry script will run automatically.

Project Structure

Scenes

JSON files that describe entities, components, render settings, fog, and skybox settings.

Scripts

Lua files that provide behavior. Scripts can be attached to entities or used as global logic.

Assets

Models, textures, and audio. Paths are stored in scenes and scripts as relative strings.

Config

A simple config file controls window size, title, FPS, and vsync.

Engine Core

The core owns the window, the render loop, and the active scene. It initializes subsystems and shuts them down cleanly.

Startup

The engine reads config, creates a window, initializes audio, scene manager, scripting, and particles, then loads the entry scene and scripts.

Main Loop

Each frame runs script updates, processes scene requests, updates particles and audio, then renders 3D and UI.

Scene Requests

Scene load, unload, and activate requests are deferred and applied at the end of the frame.

Shutdown

All resources are released, render targets are cleaned up, and the window is closed.

Scene System

Scenes are containers for entities and settings. Multiple scenes can be loaded, but only one is active.

Scene JSON

A scene defines a list of entities. Each entity stores a name, GUID, and component data.

Render Settings

Ambient light and fog are stored per scene and passed to the renderer each frame.

Skybox

Scenes can specify a skybox texture and panorama flag. The renderer will build a cubemap when needed.

ECS Model

The engine uses a lightweight entity component system. Entities are IDs. Components store all data.

Entities

Entities can be created, destroyed, named, tagged, and queried. Scripts usually interact by name or tag.

Components

Core components include Transform, Camera, MeshRenderer, Material, Light, Collider, AudioSource, AudioListener, SpriteRenderer, ParticleEmitter, Script, Animator, Properties, and CustomComponents.

Parenting

Parent relationships are stored via GUID. Child transforms are combined with parent transforms at runtime.

Properties

Properties and CustomComponents provide flexible JSON storage for game-specific data.

Rendering

The renderer supports models, primitives, sprites, and skyboxes. The default shading model is PBR.

Materials and PBR

Materials define albedo and optional textures for metallic, roughness, AO, and normal. Numeric factors and UV scaling are also supported.

Lighting

Directional and point lights are supported. Light data is passed to the shader each frame.

Shadows

The primary directional light can cast shadows via a depth map. Shadow bias is adjustable in the shader.

Fog and Ambient

Fog color and density are per scene. Ambient light is applied before direct lighting.

Environment

Skyboxes can be panorama textures or cubemaps. If cubemap generation fails, a 2D shader fallback is used.

Sprites

SpriteRenderer draws textured billboards in 3D. Sprites can face the camera or use a fixed orientation.

Animation

Model animations are supported through the Animator component.

Animator Component

Animator tracks clip index, playback speed, looping, and current time.

Clips

Clips are loaded from the model. Scripts can play, pause, stop, and switch clips at runtime.

Physics

Physics provides simple collision, triggers, and spatial queries.

Colliders

Collider shapes include box, sphere, and capsule. Triggers are supported via a flag.

Queries

Raycast and overlap queries return entities and hit data for gameplay logic.

Events

Scripts receive oncollision and ontrigger events for enter, stay, and exit.

Audio

Audio sources are attached to entities. A listener defines the point of hearing.

Sources and Listener

Sources play clips, can be spatial or non spatial, and may loop. The listener usually follows the camera.

Groups

Volume can be controlled per audio group for global balancing.

Particles

The particle system is component driven and updated every frame.

Emitters

Emitters control rate, lifetime, speed, size, spread, gravity, drag, and color over time.

Textures

Particles can use sprite sheets with frame columns, rows, and animation FPS.

Scripting

Lua scripts drive gameplay and UI. Each script returns a table of callbacks.

Lifecycle

Common callbacks are oninit, onupdate, onfixedupdate, onlateupdate, and collision or trigger events.

Messaging

Scripts can send messages to other scripts or broadcast to all scripts in the active scene.

Global Scripts

Global Lua files can expose functions such as OnInit that the engine calls once.

Lua files must be saved as UTF-8 without BOM.

UI and Debug

UI and debug drawing are immediate mode and executed after 3D rendering.

UI Commands

Draw rectangles, outlines, text, and textures directly from Lua each frame.

UI Input

A simple text input widget is provided. It returns current text, focus state, and change flag.

Debug Draw

Debug helpers draw 3D lines, rays, points, and screen text overlays.

Input

Keyboard

KeyDown, KeyPressed, and KeyReleased are available for per frame control.

Mouse

Mouse position, delta, wheel, and buttons are available. Mouse lock and visibility can be toggled.

Time and Update Order

Delta

Delta returns the last frame time after timeScale is applied. GetFPS returns the current FPS.

Fixed Step

FixedDelta controls the fixed update step for physics and timers.

Resource Management

Caching

Models, textures, fonts, and audio are cached by path to avoid redundant loading.

Build and Run

Default Build

The batch script configures CMake, builds, and launches the editor executable.

Release

For release builds, disable editor targets and embed project data if needed.

Embedded Project Data

Embedding Flow

A Python tool converts Scenes and Scripts into a generated C++ file compiled into the engine.

Runtime Fallback

At runtime the engine tries disk files first, then falls back to embedded data.

Lua API

The Lua API is grouped by domain. The sections below summarize all available functions and the behavior you can expect in scripts.

Base Types

TypeDescription
entity64 bit handle represented as a number.
vec3Table {x,y,z} or indexed {[1]=x,[2]=y,[3]=z}.
quatTable {x,y,z,w} or indexed {[1]=x,[2]=y,[3]=z,[4]=w}.

Core and Time

FunctionDescription
Quit()Close the application.
SetTimeScale(scale)Set time scale multiplier.
GetTimeScale()Get current time scale.
SetFixedDelta(dt)Set fixed update delta.
GetFixedDelta()Get fixed update delta.
SetTargetFPS(fps)Set FPS target.
GetTargetFPS()Get FPS target.
Time()Time since startup.
Delta()Scaled frame delta.
GetFPS()Current FPS.

Scenes

FunctionDescription
SceneCreate(name)Create a new scene.
LoadScene(path)Request scene load, deferred to end of frame.
SaveScene(path, id?)Save a scene to disk.
SceneSetActive(id)Request active scene change.
SceneGetActive()Get active scene id.
SceneUnload(id)Request scene unload.
SceneList()List loaded scenes.

Entities

FunctionDescription
CreateEntity(name?)Create entity.
DestroyEntity(entity)Destroy entity.
IsAlive(entity)Check if entity is valid.
FindEntityByName(name)Find first entity by name.
GetName(entity)Get name.
SetName(entity, name)Set name.
GetGuid(entity)Get GUID.
SetTag(entity, tag)Set tag.
GetTag(entity)Get tag.
FindByTag(tag)Find entities by tag.
SetActive(entity, enabled)Enable or disable entity.
IsActive(entity)Check active state.

Components

FunctionDescription
AddComponent(entity, name)Add component by name.
RemoveComponent(entity, name)Remove component.
HasComponent(entity, name)Check component.
SetComponent(entity, name, table)Update component fields.
GetComponent(entity, name)Get component data.

Properties

FunctionDescription
SetProperty(entity, key, value)Set property value.
GetProperty(entity, key)Get property value.
HasProperty(entity, key)Check property existence.
RemoveProperty(entity, key)Remove property.

Scripts and Messages

FunctionDescription
AddScript(entity, file)Attach script to entity.
RemoveScript(entity)Remove script from entity.
SetScriptEnabled(entity, enabled)Enable or disable script.
SendMessage(entity, fn, ...)Call method on entity script.
Broadcast(fn, ...)Call method on all scripts.
CallGlobal(fn, ...)Call a global Lua function.

Transform

FunctionDescription
SetPosition(entity, x, y, z)Set position.
GetPosition(entity)Get position.
SetRotationDeg(entity, x, y, z)Set rotation in degrees.
GetRotationDeg(entity)Get rotation in degrees.
SetRotationQuat(entity, x, y, z, w)Set rotation quaternion.
GetRotationQuat(entity)Get rotation quaternion.
SetScale(entity, x, y, z)Set scale.
GetScale(entity)Get scale.

Input

FunctionDescription
KeyDown(key)Key held.
KeyPressed(key)Key pressed this frame.
KeyReleased(key)Key released this frame.
MouseDelta()Mouse delta.
MouseDown(btn)Mouse held.
MousePressed(btn)Mouse pressed this frame.
MouseReleased(btn)Mouse released this frame.
MousePos()Mouse position.
MouseWheel()Mouse wheel delta.
SetMouseLock(lock)Lock mouse cursor.
SetMouseVisible(visible)Show or hide cursor.

File System

FunctionDescription
FSReadText(path)Read text file.
FSWriteText(path, text?)Write text file.
FSAppendText(path, text?)Append text file.
FSExists(path)Check path exists.
FSDelete(path)Delete file.
FSListDir(path)List directory.

Audio

FunctionDescription
SetAudioGroupVolume(group, volume)Set group volume.
GetAudioGroupVolume(group)Get group volume.
AudioPlay(entity)Play source.
AudioPause(entity)Pause source.
AudioResume(entity)Resume source.
AudioStop(entity)Stop source.

Physics

FunctionDescription
Raycast(ox,oy,oz, dx,dy,dz, maxDist)Raycast, returns hit info.
RaycastIgnore(ox,oy,oz, dx,dy,dz, maxDist, ignore)Raycast with ignore entity.
OverlapSphere(cx,cy,cz, r)Sphere overlap query.
OverlapBox(cx,cy,cz, sx,sy,sz)Box overlap query.
OverlapCapsule(cx,cy,cz, h, r)Capsule overlap query.

Fog and Ambient

FunctionDescription
SetFog(enabled, r,g,b,a, density)Set fog parameters.
GetFog()Get fog parameters.
SetAmbient(r,g,b,a)Set ambient color.
GetAmbient()Get ambient color.

UI

FunctionDescription
UIRect(x,y,w,h, r?,g?,b?,a?)Draw filled rect.
UIRectOutline(x,y,w,h, thickness?, r?,g?,b?,a?)Draw rect outline.
UIText(text,x,y, size?, r?,g?,b?,a?)Draw text.
UIFont(path?, size?)Set UI font.
UIImage(path, x,y,w,h, r?,g?,b?,a?)Draw image.
UIInput(id, x,y,w,h, text?, size?, r?,g?,b?,a?)Text input widget.

Animation

FunctionDescription
AnimPlay(entity, clip?)Play clip.
AnimPause(entity)Pause animation.
AnimResume(entity)Resume animation.
AnimStop(entity)Stop animation.
AnimSetLoop(entity, loop)Set looping.
AnimSetSpeed(entity, speed)Set speed.
AnimSetClip(entity, clip)Set clip index.

Debug

FunctionDescription
DebugLine(x1,y1,z1, x2,y2,z2, r?,g?,b?,a?)Draw 3D line.
DebugRay(ox,oy,oz, dx,dy,dz, len, r?,g?,b?,a?)Draw ray.
DebugPoint(x,y,z, size?, r?,g?,b?,a?)Draw point.
DebugText(text,x,y, size?, r?,g?,b?,a?)Draw screen text.

Timers and Coroutines

FunctionDescription
SetTimeout(sec, fn)Run once after delay.
SetInterval(sec, fn)Repeat at interval.
ClearTimer(id)Cancel timer.
StartCoroutine(fn)Start coroutine.
StopCoroutine(id)Stop coroutine.
Wait(sec)Yield for seconds.

Math

FunctionDescription
Math.Vec3(x,y,z)Create vec3.
Math.Vec3Add(a,b)Add vectors.
Math.Vec3Sub(a,b)Subtract vectors.
Math.Vec3Mul(a, s|b)Multiply by scalar or vector.
Math.Vec3Dot(a,b)Dot product.
Math.Vec3Cross(a,b)Cross product.
Math.Vec3Length(v)Vector length.
Math.Vec3Normalize(v)Normalize vector.
Math.Vec3Lerp(a,b,t)Vector lerp.
Math.Lerp(a,b,t)Scalar lerp.
Math.Clamp(v, min, max)Clamp value.
Math.Random(min, max)Random float.
Math.RandomInt(min, max)Random int.
Math.Deg2Rad(deg)Degrees to radians.
Math.Rad2Deg(rad)Radians to degrees.
Math.QuatFromEuler(x,y,z)Create quaternion.
Math.QuatMul(a,b)Quaternion multiply.

Key and Mouse Constants

Constants include KEY_A to KEY_Z, KEY_0 to KEY_9, function keys, arrows, modifiers, numpad, and mouse buttons such as MOUSE_LEFT.

Troubleshooting

Lua BOM

If you see unexpected symbol near '<\\239>', the Lua file has a BOM header. Re-save the file as UTF-8 without BOM.

Limits and Notes

Scope

SCM focuses on clarity and fast iteration. It does not aim to replace full editor pipelines. Use it when you want simple structure and direct control.