C++ API Reference

Single include: #include <Simple3D/Simple3D.h>
All public symbols live in the Simple3D:: namespace. Use using namespace Simple3D; in implementation files for brevity. Never use it in headers — this pollutes the global namespace for users of your headers.

Game

Game is the base class for your application. Override Start(), Update(), and optionally Stop(). Instantiate via the factory function CreateGame<T>() which sets up all engine internals before returning.

#include <Simple3D/Core/Game.h>

class MyGame : public Simple3D::Game {
public:
    void Start()           override;
    void Update(float dt)  override;
    void Stop()            override;  // optional
};

int main() {
    return Simple3D::CreateGame<MyGame>()->Run();
}

Never do engine work in the constructor

The engine is not initialised until Run() is called. All entity creation, asset loading, and scene setup must happen in Start(), not in the constructor of your Game subclass.

Lifecycle callbacks

SignatureWhen calledNotes
void Start() Once, after engine fully initialised, before first frame Create all entities, cameras, labels here. Audio and Lua ready.
void Update(float dt) Every frame dt is the duration of the previous frame in seconds. Clamped to max 0.1 s to prevent physics tunnelling on frame spikes.
void Stop() Once, when application is exiting Optional. Called before engine shutdown. For cleanup of non-RAII resources.

Scene creation

SignatureReturnsDescription
CreateEntity(string name)Entity* Creates a new scene entity with the given name and registers it. Name must be unique within the scene for FindEntity to work reliably.
FindEntity(string name)Entity* Looks up a registered entity by name. Returns nullptr if not found. Searches only entities created via CreateEntity().
DestroyEntity(Entity* e)void Removes the entity from the scene, fires Stop() on any attached Lua scripts, removes it from the registry, and frees memory. Do not use the pointer after this call.
CreateCamera()Camera* Creates a camera entity at world origin. Multiple cameras are supported (split-screen). The first created camera is the default viewport camera.
CreateLabel(string text)Label* Creates an on-screen UI text element. Default position (0, 0), font size 14, color white.
LoadTileMap(string path)Entity* Loads a Tiled .tmx file and returns the root tile map entity. Collision layers in the .tmx become RigidBody2D + CollisionPolygon2D components. PhysicsWorld2D is activated automatically.

Audio

SignatureDescription
PlayMusic(string path, bool loop = true) Streams audio from disk. Supports OGG Vorbis and WAV. Only one music track plays at a time; calling again replaces the current track. loop = false plays the track once then stops.
StopMusic() Stops the currently playing music immediately. No fade-out. For fade-out, decrease master volume gradually over several frames before calling StopMusic().
PlaySound(string path, float volume = 1.0f) Fires a one-shot sound effect. Does not block; returns immediately. Multiple simultaneous sounds are mixed by the engine. volume range: 0.0 (silent) – 1.0 (full). Values > 1.0 are clamped.
SetMasterVolume(float v) Sets the master volume for all audio output (music + SFX). Range: 0.0 – 1.0. Persists for the lifetime of the application.

Asset paths for audio

Audio paths are relative to the Data/ resource directory, like all other assets. Example: PlayMusic("Music/theme.ogg") loads Data/Music/theme.ogg.

Keyboard & Mouse Input

SignatureReturnsDescription
IsKeyDown(Key k)bool True every frame the key is held. Use for continuous actions (movement, accelerate).
IsKeyPressed(Key k)bool True only on the first frame the key transitions from up to down. Use for one-shot actions (jump, fire, toggle).
IsMouseButtonDown(MouseButton b)bool True while the mouse button is held. Buttons: MouseButton::Left, ::Right, ::Middle.
GetMousePosition()Vector2 Current mouse cursor position in screen pixels. (0,0) is top-left.
GetMouseDelta()Vector2 Mouse movement since last frame in pixels. Use for camera rotation in FPS games. When the camera is in FPS mode, the cursor is captured and GetMouseDelta() returns raw mouse input, not bounded by screen edges.

Key enum — full reference

Key constantsDescription
Key::A … Key::ZLetter keys
Key::Num0 … Key::Num9Number row keys
Key::F1 … Key::F12Function keys
Key::EscapeEscape
Key::ReturnEnter / Return
Key::SpaceSpace bar
Key::BackspaceBackspace
Key::TabTab
Key constantsDescription
Key::LShift, Key::RShiftShift keys
Key::LCtrl, Key::RCtrlControl keys
Key::LAlt, Key::RAltAlt keys
Key::Left, Key::RightArrow keys
Key::Up, Key::DownArrow keys
Key::Home, Key::EndHome / End
Key::PageUp, Key::PageDownPage keys
Key::Insert, Key::DeleteInsert / Delete
Key::KP0 … Key::KP9Numpad digits
Key::KPPlus, Key::KPMinusNumpad operators

Touch Input

Touch input is available on Android, iOS, and desktop systems with a touch screen. On desktop without a touch screen, all touch counts return 0.

int n = GetTouchCount();           // number of active touch points (0–10)

for (int i = 0; i < n; ++i) {
    Vector2 pos  = GetTouchPosition(i);   // screen pixels; (0,0) top-left
    Vector2 dlt  = GetTouchDelta(i);      // movement since last frame
    float   pres = GetTouchPressure(i);   // 0.0 (lightest) – 1.0 (hardest)
}

// Detect tap (first frame of new touch):
bool tapped = (GetTouchCount() > 0 && GetTouchDelta(0).Length() < 2.0f);
SignatureReturnsDescription
GetTouchCount()int Number of currently active touch points. 0 if no touch. Max 10 (hardware-dependent).
GetTouchPosition(int index)Vector2 Screen position of touch point index in pixels.
GetTouchDelta(int index)Vector2 Movement of touch point index since the previous frame.
GetTouchPressure(int index)float Pressure of touch point index. 0.0 – 1.0. Always returns 1.0 on hardware that does not support pressure sensing.

Rendering & Window

SignatureDescription
SetClearColor(Color c) Background color drawn before the scene. Default: Color(0.1f, 0.1f, 0.15f) (dark blue-grey). Takes effect from the next frame.
SetWindowTitle(string title) Sets the OS window title bar text. Can be called at any time, including from Update() to show FPS or player info.

Navigation (NavMesh)

Navigation mesh baking must be called after placing all static level geometry in Start(). It is a potentially expensive one-time operation (runs on a worker thread in Urho3D, so Start() returns immediately).

SignatureDescription
BuildNavMesh(
  float agentRadius = 0.4f,
  float agentHeight = 1.8f,
  float cellSize = 0.3f
)
Bakes a Recast/Detour navigation mesh from all static geometry in the scene (entities with AddRigidBody(0.0f)).

agentRadius: Minimum passage width the agent can navigate (metres). Increase to prevent agents squeezing through tight gaps.
agentHeight: Agent height (metres). Areas with lower ceilings will be marked unwalkable.
cellSize: Voxel size for the bake. Smaller = more accurate mesh, but slower to bake and more memory.

Miscellaneous

SignatureReturnsDescription
Quit() Signals the engine to exit the main loop cleanly. Stop() is called before the application terminates. Safe to call from Update() or Lua callbacks.
GetTime()float Seconds elapsed since the application started (since Run() was called). Uses the engine's monotonic clock — not affected by system time changes.
GetDeltaTime()float Duration of the most recently completed frame in seconds. Same value passed as dt to Update(). Useful for Lua code that needs dt outside of Update().
CreateNetworkManager()NetworkManager* Creates and registers the network manager. Call once in Start(). Calling more than once returns the existing instance.
GetNetworkManager()NetworkManager* Returns the existing NetworkManager, or nullptr if CreateNetworkManager() has not been called.

Entity

Entities are created via Game::CreateEntity(name) and destroyed via Game::DestroyEntity(e). Do not delete them manually.

Entity* e = CreateEntity("MyObject");

Transform

SignatureReturnsDescription
SetPosition(float x, float y, float z) Sets the world-space position. Equivalent to SetPosition(Vector3(x,y,z)).
SetPosition(Vector3 pos) Sets world-space position from a Vector3.
GetPosition()Vector3 Returns current world-space position.
SetRotation(Quaternion q) Sets world-space rotation. Construct with Quaternion(yaw, pitch, roll) where angles are in degrees.
GetRotation()Quaternion Returns current world-space rotation.
SetScale(float s) Uniform scale. SetScale(2.0f) doubles the entity in all dimensions.
SetScale(Vector3 s) Non-uniform scale. SetScale(Vector3(1, 2, 1)) doubles height only.
MoveRelative(Vector3 delta) Moves the entity in world space by delta. If a RigidBody is present, sets its linear velocity for the frame to achieve the movement; otherwise directly translates the node. Preferred over SetPosition(GetPosition() + delta) for physics-based characters.

3D Rendering

SignatureDescription
AddModel(string path) Loads a 3D mesh from the resource cache and attaches a StaticModel component. Supported: OBJ, FBX, GLTF/GLB, MDL (Urho3D native). A default material is applied if no material file is found at the same path with a .xml extension.
AddDirectionalLight(Color color, float intensity) Adds an infinite directional light (like the sun). Direction is determined by the entity's rotation. Set with SetRotation(Quaternion(pitch, yaw, 0)) where pitch=45 and yaw=-30 gives a typical outdoor sun angle.
AddPointLight(Color color, float range) Adds an omnidirectional point light. range is the distance in metres at which the light fades to zero. Uses linear attenuation by default.
AddSpotLight(Color color, float range, float angle) Adds a cone-shaped spot light. range is the cone depth in metres; angle is the full cone angle in degrees (e.g., 30 = 15° on each side of center). Aimed in the entity's local -Z direction.

2D Rendering

SignatureDescription
AddSprite2D(string path) Attaches a StaticSprite2D. The sprite is rendered in the XY plane. Position is in world units (convert from pixels using the PPU value set in Camera::Setup2D).
AddAnimatedSprite2D(string scmlPath) Attaches an AnimatedSprite2D driven by a Spriter .scml file. Call PlayAnimation2D(name) to start a specific animation.
PlayAnimation2D(string name, bool loop = true, float speed = 1.0f) Plays the named animation from the attached Spriter animation set. loop = false plays once then holds the last frame. speed multiplies the playback rate.
SetFlipX2D(bool flip) Mirrors the sprite horizontally. Use to face a 2D character in the direction of movement without needing separate left/right animation sets.

Physics — 3D (Bullet)

// ── Adding physics ─────────────────────────────────────────────────
e->AddRigidBody(70.0f);                        // 70 kg dynamic body
e->AddRigidBody(0.0f);                         // 0 kg = static (immovable)

e->AddBoxCollider(Vector3(1, 2, 1));           // full-size (not half-extents)
e->AddCapsuleCollider(0.4f, 1.75f);           // radius, total height
e->AddSphereCollider(0.5f);                   // radius
e->AddMeshCollider("Models/dungeon.obj");      // triangle mesh (static only)

// ── Forces & velocity ──────────────────────────────────────────────
e->ApplyImpulse(Vector3(0, 8, 0));             // instant velocity change (jump)
e->ApplyForce(Vector3(0, 0, 20));              // continuous force (rocket)
e->SetLinearVelocity(Vector3(5, 0, 0));       // override velocity directly
Vector3 v = e->GetLinearVelocity();

// ── Ground detection ──────────────────────────────────────────────
bool grounded = e->IsOnGround();                // raycast 0.7m downward

// ── Collision filtering ────────────────────────────────────────────
e->SetCollisionLayer(1);   // bit flags — which layer this body IS on
e->SetCollisionMask(0xFF); // bit flags — which layers it COLLIDES with

Trigger volumes

// Trigger shapes
e->AddTriggerBox(Vector3(4, 3, 4));
e->AddTriggerSphere(2.5f);
e->AddTriggerCapsule(0.8f, 2.0f);

// Callbacks — 'other' is the Entity that entered / exited
e->SetOnTriggerEnter([](Entity* other) {
    // Fire on first overlapping frame.
    // 'other' pointer is guaranteed valid during this call.
});
e->SetOnTriggerExit([](Entity* other) {
    // Fire on first non-overlapping frame after overlap.
});

Collision layers — bit flags

Layer 1 = 0x01, layer 2 = 0x02, layer 3 = 0x04, etc. A body on layer 0x01 with mask 0xFF collides with everything. A body on layer 0x02 with mask 0x01 collides only with layer 1 bodies. Camera collision avoidance raycasts against static layer 2 only.

Full 3D physics method table

MethodParametersNotes
AddRigidBody(mass)mass: float kg0.0f = static, immovable
AddBoxCollider(size)size: Vector3 (full dimensions)Box origin at entity position
AddCapsuleCollider(r, h)r: radius, h: total heightCapsule axis along Y
AddSphereCollider(r)r: radius
AddMeshCollider(path)path: model fileConcave; static bodies only
AddTriggerBox(size)size: Vector3No collision response
AddTriggerSphere(r)r: radius
AddTriggerCapsule(r, h)r, h
SetOnTriggerEnter(fn)fn: void(Entity*)First overlapping frame
SetOnTriggerExit(fn)fn: void(Entity*)First non-overlapping frame
ApplyImpulse(v)v: Vector3Instant ΔV in m/s (mass-weighted)
ApplyForce(v)v: Vector3 NContinuous force; accumulates per frame
SetLinearVelocity(v)v: Vector3 m/sOverrides velocity directly
GetLinearVelocity()Returns Vector3 m/s
IsOnGround()Returns bool; ray length 0.7 m
SetCollisionLayer(bits)bits: intBit mask of which layer this is on
SetCollisionMask(bits)bits: intBit mask of layers to collide with

Physics — 2D (Box2D)

e->AddRigidBody2D(60.0f);            // dynamic; mass in kg
e->AddRigidBody2D(0.0f);             // static
e->AddBoxCollider2D(1.0f, 2.0f);    // width, height in world units
e->AddCircleCollider2D(0.5f);       // radius in world units

e->SetLinearVelocity2D(Vector2(5, 0));
Vector2 v = e->GetLinearVelocity2D();
e->ApplyImpulse2D(Vector2(0, 8));

bool grounded = e->IsOnGround2D();   // downward ray 0.6 m

Animation

e->AddAnimationController();
AnimationController* anim = e->GetAnimationController();
// Returns nullptr if AddAnimationController() has not been called yet.
MethodParametersDescription
Play(name) name: string Play on layer 0, looped, 0.2s cross-fade. Fades out all other clips on the same layer.
Play(name, layer, loop, fadeTime) name, layer: int, loop: bool, fadeTime: float s Full control over layer assignment and cross-fade duration. Use separate layers for upper/lower body blending.
PlayBlend(name, layer) name, layer: int Plays alongside other animations on the same layer without fading them out. Use for additive overlays (e.g., aiming while running).
Stop(name, fadeTime) name, fadeTime: float s Stops the named animation with optional cross-fade to the next playing clip.
StopAll() Stops all playing animations immediately on all layers.
IsPlaying(name) name: string Returns bool — true if the clip is currently active (including cross-fading out).
SetWeight(name, weight) name, weight: float 0–1 Sets the blend weight of a clip. 0.0 = invisible but still running. Use with PlayBlend for smooth transitions.
SetSpeed(name, speed) name, speed: float Sets playback speed multiplier. 1.0 = normal, 2.0 = double speed, 0.5 = half speed, negative values play backward.
GetTime(name) name: string Returns float — playback position in seconds. Useful for synchronising sound effects to animation events.

Navigation

// First, bake nav-mesh in Start() after placing all static terrain:
BuildNavMesh(0.35f, 1.8f, 0.25f);

// Query path from enemy to a target (returns empty vector if no path):
std::vector<Vector3> path = enemy->FindPath(player);
std::vector<Vector3> path = enemy->FindPath(Vector3(10, 0, 5));

// Auto-follow: call in Update(). Recomputes path when target drifts > 1 m.
// Returns true while still moving, false when destination reached.
bool moving = enemy->MoveToward(player, 3.5f, dt);   // 3.5 m/s
bool moving = enemy->MoveToward(Vector3(10, 0, 5), 3.5f, dt);

enemy->StopMoving();   // clear cached path, zero horizontal velocity

When to call BuildNavMesh

Call BuildNavMesh() once at the end of Start(), after all static level entities (floor, walls, platforms) have been placed. Dynamic entities (player, enemies, crates) should not be present yet, or their colliders will be baked into the mesh and block navigation. Calling BuildNavMesh() again rebuilds from scratch.

Scripting

e->AddScript("Scripts/enemy.lua");

Each entity can have one script. The script file is loaded from the resource cache. If the file is not found, a warning is logged and no script is attached (the entity continues to work normally). The script's Start() is called on the first frame after Start() of the game has completed.

Hierarchy

Entity* child  = parent->CreateChild("Weapon");
Entity* parent = child->GetParent();   // nullptr for root entities

Child entities inherit their parent's transform (position, rotation, scale). Moving the parent moves all children. This is used for weapon attachment, character sub-parts, and complex hierarchical objects.

When the parent entity is destroyed via DestroyEntity(parent), all children are also destroyed and removed from the registry.

Camera

Camera* cam = CreateCamera();

Third-Person Follow

MethodParametersDescription
Follow(entity, distance, height) entity: Entity*, distance: float m, height: float m Camera follows entity at distance metres behind and height metres above. Default height: 2.0f.
LookAt(entity) entity: Entity* Camera continuously points at the entity. Use with Follow.
LookAt(Vector3 point) point: Vector3 Camera continuously points at a fixed world-space point.
SetSmoothFollow(enabled, speed) enabled: bool, speed: float (default 5.0) Lerps camera position towards follow target each frame. Higher speed = snappier. ~8 feels responsive; ~3 feels floaty.
Detach() Stops following/orbiting; releases mouse capture if in FPS mode. Camera stays at its current position.

Orbit Mode

MethodParametersDescription
SetOrbitMode(target, radius) target: Entity*, radius: float m Camera orbits target at radius metres. Hold right mouse button and drag to rotate.
SetOrbitAngles(yaw, pitch) yaw: float°, pitch: float° Initial yaw (horizontal) and pitch (vertical) angles in degrees.
SetOrbitSensitivity(s) s: float degrees/pixel Mouse drag sensitivity. Default: 0.3. Lower values are slower.
SetOrbitPitchLimits(minPitch, maxPitch) minPitch, maxPitch: float° Clamps vertical rotation. Example: (-30, 75) prevents the camera from flipping upside-down.

First-Person (FPS) Mode

MethodParametersDescription
SetFPSMode(entity) entity: Entity* Attaches camera to the entity at head level. Mouse cursor captured; raw mouse delta used for look rotation.
SetFPSMode() Free-floating FPS camera with no attached entity. Useful for editor fly-through mode.
SetFPSAngles(yaw, pitch) yaw: float°, pitch: float° Initial look direction. yaw=0 looks toward +Z; pitch=0 looks horizontally.
SetFPSSensitivity(s) s: float degrees/pixel Mouse look sensitivity. Default: 0.15. Typical range 0.05 – 0.3.
SetFPSHeadOffset(height) height: float m Vertical offset from entity origin. A 1.8 m tall character should use ~1.65 to put the camera near eye level.

Camera Collision Avoidance

cam->SetCollisionEnabled(true);

When enabled, the camera raycasts between the follow target and its intended position. If a static collision object is in the way, the camera is pulled in to avoid clipping. Only raycasts against static bodies on collision layer 2. Dynamic objects (enemies, crates) do not block the camera.

2D / Orthographic Setup

cam->Setup2D(100.0f);   // 100 pixels per world unit
// Equivalent to:
cam->SetOrthographic(true);
cam->SetOrthoSize(7.2f);   // 720 px / 100 ppu = 7.2 world units visible vertically
MethodParametersDescription
Setup2D(ppu) ppu: float pixels-per-unit Shorthand: enables orthographic projection, sets Z position to -10, configures OrthoSize from screen height and ppu. Suitable for 2D games.
SetOrthographic(enabled) enabled: bool Switches between perspective (false) and orthographic (true) projection.
SetOrthoSize(size) size: float world units Height of the visible area in world units. Width is derived from the window aspect ratio.

Split-Screen

cam1->SetViewport(0, 0.0f, 0.0f, 0.5f, 1.0f);  // index, x, y, w, h  (0–1 normalized)
cam2->SetViewport(1, 0.5f, 0.0f, 0.5f, 1.0f);

Viewport coordinates are in the range 0–1 (fraction of the window). The index parameter (0, 1, 2, …) determines render order; higher indices draw on top. All viewport cameras share the same scene.

Projection Parameters

MethodParametersDefaultDescription
SetFOV(degrees)float°45°Vertical field of view in degrees. Typical: 60–90 for FPS, 45 for third-person.
SetNearClip(dist)float m0.1Near clip plane. Objects closer than this are clipped. Use the smallest value that avoids z-fighting (0.1 m typical for indoor, 0.5 m for large outdoor).
SetFarClip(dist)float m1000.0Far clip plane. Objects farther than this are not rendered. Set to the maximum visibility distance to reduce depth buffer precision issues.

NetworkManager

NetworkManager* net = CreateNetworkManager();

Message ID ranges

IDs 0–99 are reserved by Urho3D for internal scene replication and engine messages. Use IDs 100–32767 for your game messages. Define them as constants: const int MSG_PLAYER_POS = 100;

Server side

MethodDescription
StartServer(int port, int maxClients = 128)Start listening on the given port. maxClients limits simultaneous connections.
StopServer()Stop accepting connections; disconnect all clients.
IsServer()Returns bool — true if server is running.
SetOnClientConnected(fn)fn signature: void(int clientId). Called when a new client successfully connects.
SetOnClientDisconnected(fn)fn signature: void(int clientId). Called when a client disconnects.
Broadcast(int msgId, vector<uint8_t> data)Send to all connected clients.
SendToClient(int clientId, int msgId, vector<uint8_t> data)Send to a specific client only.

Client side

MethodDescription
Connect(string host, int port)Connect to a server. Non-blocking; result arrives via SetOnServerConnected callback.
Disconnect()Disconnect from the server.
IsConnected()Returns bool.
SetOnServerConnected(fn)fn: void(). Called when connection is established and ready to use.
SetOnServerDisconnected(fn)fn: void(). Called on disconnect or connection failure.
SendToServer(int msgId, vector<uint8_t> data)Send a message to the server.

Both sides

net->SetOnMessage([](int sender, int msgId,
                    const std::vector<uint8_t>& data) {
    // sender == 0  → came from server (on client)
    // sender == N  → came from client N (on server)
    if (msgId == 100) {
        // unpack data …
    }
});

Label (UI)

Label* lbl = CreateLabel("Score: 0");
MethodParametersDescription
SetText(string t)stringUpdate displayed text. Safe to call every frame (no expensive re-layout unless text actually changes).
SetPosition(int x, int y)screen pixels(0,0) is top-left corner of the window.
SetFontSize(int px)pixelsFont size in screen pixels. Default: 14.
SetColor(Color c)Color RGBAText color with alpha. Color(1,1,1,0.5f) = semi-transparent white.
SetVisible(bool v)boolShow or hide without destroying the label. Useful for toggling HUD elements.

Math Types

All types are re-exported from Urho3D math as Simple3D:: aliases. They are ABI-identical — no conversion overhead when crossing the API boundary.

TypeMembersKey methods
Vector2 .x, .y Length(), Normalized(), Dot(v), operators +, -, *, /
Vector3 .x, .y, .z Length(), Normalized(), Dot(v), Cross(v), Distance(v)
Vector4 .x, .y, .z, .w Length(), Normalized()
Color .r, .g, .b, .a Constants: Color::WHITE, ::BLACK, ::RED, ::GREEN, ::BLUE, ::YELLOW, ::CYAN, ::MAGENTA, ::TRANSPARENT
Quaternion .x, .y, .z, .w Quaternion(yaw, pitch, roll) — degrees. Normalized(), Inverse(), operator* (compose), ToEulerAngles()
Matrix3 3×3 Rotation matrix, normal transform
Matrix3x4 3×4 Affine transform (most entity transforms)
Matrix4 4×4 Projection matrix, full perspective transform
BoundingBox .min, .max (Vector3) Axis-aligned bounding box. IsInside(pt), Merge(box)
Rect .min, .max (Vector2) Float rectangle (UV, screen region)
IntRect .left, .top, .right, .bottom Integer rectangle (pixel-exact regions)
IntVector2 .x, .y Integer 2D point (mouse position, tile coord)
IntVector3 .x, .y, .z Integer 3D point (voxel position)