41 lines
3.3 KiB
Markdown
41 lines
3.3 KiB
Markdown
# C++ gameplay
|
|
|
|
In Faset, a gameplay script is **C++ compiled into the Player**. You write ordinary functions and register the callbacks an object needs. There is no C++ interpreter or live replacement of compiled classes. Stop Play, rebuild, export the schema, and start a new Player session.
|
|
|
|
Lua is planned for a later stage. The APIs and tutorials in this section describe the C++ implementation available now.
|
|
|
|
## Start here
|
|
|
|
1. Read [Your first behavior](first-behavior.md) and run the moving-object example.
|
|
2. Learn [when callbacks run](lifecycle.md) before mixing frame updates and physics.
|
|
3. Build a [physics character](physics.md) that can move and jump from the floor.
|
|
4. Try [following, spawning, and timed destruction](examples.md).
|
|
5. Keep the [runtime API reference](api.md) nearby while writing code.
|
|
|
|
The complete tutorial modules are compiled and executed by CTest. The code blocks include those source files directly, so the manual does not maintain separate, untested copies.
|
|
|
|
## What belongs to your module
|
|
|
|
A gameplay directory contains `Gameplay.hpp` and `Gameplay.cpp`. It provides two functions in `faset::gameplay`:
|
|
|
|
- `registerGameplay(runtime::Runtime&)` registers executable behavior callbacks.
|
|
- `schema()` returns a JSON array of component descriptions: stable type and field IDs, versions, defaults, constraints, and Inspector hints.
|
|
|
|
The Player calls registration before loading a scene. The separate SchemaExporter calls `schema()` without creating a game world or running gameplay callbacks. The Editor reads the resulting declaration; it does not load the gameplay binary into the Editor process.
|
|
|
|
A scene object receives a behavior by containing a component whose `type` matches the string passed to `registerBehavior`. Registering a behavior does not attach it to every object. A component can contain data without having any callbacks.
|
|
|
|
## Data, poses, and state
|
|
|
|
`fields(self, type)` returns a **copy of component configuration**. Editing that copy changes neither the saved scene nor the runtime configuration. `transform(self)` returns a copy of the current simulation pose; pass the changed copy to `setTransform` for a non-physical object. A rigid body uses `setVelocity`, `applyImpulse`, or an explicit `teleport` instead.
|
|
|
|
Ordinary C++ state can be captured by callbacks. The spawning tutorial shows state indexed by the full runtime handle and cleaned up in `onDestroy`. Do not capture a reference to a local variable that will disappear after `registerGameplay` returns. Use owned state, or ensure the referenced object outlives the runtime.
|
|
|
|
Scene IDs are saved strings. `EntityHandle` is a temporary reference containing a session, slot, and generation. It must not be written into a save file. Resolve a scene ID with `find`, check `valid`, and expect old handles to stop working after removal or a new Play session.
|
|
|
|
## Current boundaries
|
|
|
|
These examples use per-object callbacks and the implemented typed pose/physics API. They do not provide a universal binding for arbitrary C++ classes, a public EnTT registry, or a general parallel-system scheduler. The runtime is sequential and has one owning thread.
|
|
|
|
MCP belongs to the Editor's authoring, import, build, and process-control services. It does not invoke runtime methods or inspect the live game world. A C++ gameplay change requires the same rebuild whether a person or an agent edited the source.
|