Syncromesh/Entity
Per-entity control: movement, native component packs (identity/logic/data/locomotion/waypoint), physics, renderables, animations, tiles, and update handlers.
Operates on individual entities by ID. Covers travel (non-physics movement), physics forces and linear velocity, fixtures, renderables, sprite/tile/text manipulation, animations, and per-entity update callbacks.
Import #
import * as Entity from 'Syncromesh/Entity';Movement #
setTravelVector(id: number, vector: Point): Promise<void>setTravelAngle(id: number, angle: number): Promise<void>setTravelSpeed(id: number, speed: number): Promise<void>getTravelSpeed(id: number): Promise<number>getLocomotionThrust(id: number): Promise<Point>{ x, y }.getPosition(id: number): Promise<Point>getDirection(id: number): Promise<number>setTransform(id: number, position: Point, directionDeg: number): Promise<boolean>Board UI attachments #
A board-local UI element can follow a local or replicated entity without sending per-frame positions through JavaScript. Syncromesh projects the entity's interpolated world transform through the attached window camera immediately before drawing the board UI layer. Attachments are local presentation state and are not replicated. While attached, Syncromesh owns the element's enabled state so missing and offscreen entities can be hidden deterministically.
worldOffsetis applied in board world coordinates before camera projection.screenOffsetis applied in UI pixels after projection.hideOffscreendefaults totrue.- The call is available in board script contexts. It returns
falsefor an inactive entity, invalid window or element IDs, or a host-only script context. - An attachment records the entity activation it was created for, so a recycled local entity ID cannot capture an old overlay.
attachUI(id: number, windowId: number, elementId: number, options?: { worldOffset?: Point, screenOffset?: Point, hideOffscreen?: boolean }): Promise<boolean>detachUI(id: number, windowId: number, elementId: number): Promise<boolean>import * as Entity from 'Syncromesh/Entity';
await Entity.attachUI(shipId, windowId, healthBarId, {
worldOffset: {x: 0, y: 2},
screenOffset: {x: 0, y: -12},
hideOffscreen: true
});Native component packs #
setIdentity(id: number, options: { enabled?: boolean, uid?: number, faction?: number, category?: number, handle?: string, label?: string }): Promise<void>getIdentity(id: number): Promise<{ enabled: boolean, uid: number, faction: number, category: number, handle: string, label: string }>setLogic(id: number, options: { enabled?: boolean, minIntervalSeconds?: number }): Promise<void>getLogic(id: number): Promise<{ enabled: boolean, minIntervalSeconds: number }>int32, float, string, boolean).defineDataField(id: number, key: string, type: string): Promise<boolean>setDataValue(id: number, key: string, index: number, value: string): Promise<boolean>getDataValue(id: number, key: string, index: number): Promise<string | null>getDataType(id: number, key: string): Promise<string | null>removeDataField(id: number, key: string): Promise<boolean>listDataFields(id: number): Promise<Array<{ key: string, type: string }>>setLocomotion(id: number, options: { enabled?: boolean, maxSpeed?: number, adjust?: number, turn?: number, arriveDistance?: number, shortAdjustDistance?: number, faceTravelDirection?: boolean, directWaypointThrust?: boolean }): Promise<void>getLocomotion(id: number): Promise<{ enabled: boolean, maxSpeed: number, adjust: number, turn: number, arriveDistance: number, shortAdjustDistance: number, faceTravelDirection: boolean, directWaypointThrust: boolean }>setWaypointOptions(id: number, options: { enabled?: boolean, closeEnoughDistance?: number }): Promise<void>enqueueWaypoint(id: number, target: Point): Promise<void>popWaypoint(id: number): Promise<boolean>clearWaypoints(id: number): Promise<void>getWaypoints(id: number): Promise<{ enabled: boolean, active: boolean, closeEnoughDistance: number, points: Point[] }>Physics #
addForce(id: number, force: Point, point: Point): Promise<void>addForceToCenter(id: number, force: Point): Promise<void>setLinearVelocity(id: number, velocity: Point): Promise<void>getLinearVelocity(id: number): Promise<Point>true when a body was updated.setBodyBullet(id: number, enabled: boolean): Promise<boolean>- Bounds are computed by unioning each fixture shape's world-space AABB. This does not use Box2D broadphase fat AABBs.
hasBodyreports whether the entity has a physics body.hasFixturesreports whether that body had any fixture shapes to union.- When
hasFixturesis false,min,max,centre,center, andsizeare a zero-sized fallback.
getBodyAabb(id: number): Promise<{ hasBody: boolean, hasFixtures: boolean, min: Point, max: Point, centre: Point, center: Point, size: Point }>- See Physics for fixture shapes and properties.
createFixture(id: number, fixture: FixtureDef): Promise<void>destroyFixtures(id: number): Promise<void>- Existing contacts are refiltered by Box2D.
- Use decimal or hexadecimal strings for 64-bit category and mask values outside JavaScript's safe integer range.
setCollisionFilter(id: number, filter: FixtureFilter): Promise<void>getContacts(id: number): Promise<number[]>Renderables #
- See Render Descriptors for the full descriptor shape.
createRenderable(id: number, descriptor: RenderDescriptor): Promise<number>- Particle lifecycle functions in
Helix/Renderablerequire this handle. - Entity/renderable access is board-script-only. See GPU Particles.
getRenderable(id: number, renderableIndex: number): Promise<number>setSpriteFrame(id: number, renderableIndex: number, frame: number): Promise<void>{ x, y }.getRenderScale(id: number, renderableIndex: number): Promise<Point>setRenderScale(id: number, renderableIndex: number, scale: Point): Promise<void>{ r, g, b, a }. getRenderColor is also available as an alias.getRenderColour(id: number, renderableIndex: number): Promise<Colour>setRenderColor is also available as an alias.setRenderColour(id: number, renderableIndex: number, colour: Colour): Promise<void>getRenderLayer(id: number, renderableIndex: number): Promise<number>setRenderLayer(id: number, renderableIndex: number, layer: number): Promise<void>getRenderOffset(id: number, renderableIndex: number): Promise<Point>setRenderOffset(id: number, renderableIndex: number, offset: Point): Promise<void>getRenderEnabled(id: number, renderableIndex: number): Promise<boolean>setRenderEnabled(id: number, renderableIndex: number, enabled: boolean): Promise<void>Tile maps #
getTileCoord(id: number, renderableIndex: number, worldPoint: Point): Promise<Point>getTile(id: number, renderableIndex: number, tileCoord: Point): Promise<number>setTile(id: number, renderableIndex: number, tileCoord: Point, tileId: number): Promise<void>getMapData(id: number, renderableIndex: number): Promise<number[]>setMapData(id: number, renderableIndex: number, data: number[]): Promise<void>Text #
getRenderable and use Text Colour Areas.setText(id: number, renderableIndex: number, text: string): Promise<void>Animations #
- See Animation for the keyframe format.
addAnimation(id: number, renderableIndex: number, keyframes: KeyFrame[]): Promise<number>startAnimation(id: number, renderableIndex: number, animationId: number): Promise<void>updateAnimation(id: number, renderableIndex: number, animationId: number, keyframes: KeyFrame[]): Promise<void>stopAnimation(id: number, renderableIndex: number): Promise<void>onAnimationEnd(id: number, renderableIndex: number, animationId: number, callback: ((time: number): void) | null) : Promise<void>Update handlers #
- The callback receives
delta(seconds since last call) andtime(engine time). - Return a number to set the minimum delay (seconds) before the next invocation. Return
0for every-frame updates.
registerUpdate(id: number, callback: (delta: number, time: number): number) : Promise<void>- The callback receives
delta(seconds since last call) andtime(engine time). - Return a number to set the minimum delay (seconds) before the next invocation. Return
0for every-frame updates. - This callback runs only when the board is configured as client-only (
Network.setClientOnly(true)). registerLocalUpdateis not gated by entity ownership. Use it for local presentation logic (for example selection FX or UI-driven helpers) that should run for replicas.- It does not run on server-capable boards (including sibling simulation boards).
registerLocalUpdate(id: number, callback: (delta: number, time: number): number) : Promise<void>interrupt(id: number): Promise<void>Examples #
import * as Entity from 'Syncromesh/Entity';
import * as Simulation from 'Syncromesh/Simulation';
const id = await Simulation.spawn({
position: { x: 0, y: 0 },
body: {
type: 'dynamic',
fixture: [{ type: 'circle', radius: 0.5, restitution: 1.0 }]
}
});
// Attach a sprite
const spriteIdx = await Entity.createRenderable(id, {
type: 'sprite',
texture: '/rom/sprites/hero.png',
layer: 100,
frames: [{
size: { x: 16, y: 16 },
origin: { x: 8, y: 16 },
aabb: { min: { x: 0, y: 0 }, max: { x: 16, y: 16 } }
}]
});
// Move with physics velocity
await Entity.setLinearVelocity(id, { x: 5, y: 0 });
// Register a per-frame update
await Entity.registerUpdate(id, (delta, time) => {
// Game logic here
return 0; // call every frame
});