RoadLine
Since 0.6
A road's centre line, from ctx.world.road(id).
Read-only. Positions are in the road entity's own frame (add the entity's transform for the world's). The engine builds it once per road, so calling ctx.world.road(id) again is cheap and returns the same object; keeping it from init is still fine. @example const road = ctx.world.road("circuit")! const here = road.closest(ctx.entity.position, ctx.state.s) // lap progress, off-road distance const ahead = road.at(here.s + 20) // a point to steer toward if (Math.abs(here.offset) > ahead.halfWidth) ctx.hud.prompt("road.off")
Signature
export interface RoadLine {
/** Metres once around a closed road, end to end on an open one. */
readonly length: number
/** True for a loop (a lap circuit), false for an open road; `at` wraps on a closed road and clamps on an open one. */
readonly closed: boolean
/** Width of the kerb strip outside each edge, metres; 0 for a road with no `kerb`. `halfWidth` does not include it. */
readonly kerbWidth: number
/** Height of the kerb strip, metres; 0 with no `kerb`. */
readonly kerbHeight: number
/** The wall the file asked for, or null for a road with no `barrier`. */
readonly barrier: RoadBarrier | null
/** The road's trigger gates, in order along it: the child entity's scene id (`ctx.world.find(id)`) and its distance along the road. Gate 0 is the start line. */
readonly gates: readonly { readonly id: string; readonly s: number }[]
/** The centre line at distance `s`. */
at(s: number): RoadSample
/**
* The nearest point on the centre line to `pos`. With `hintS` only samples within `windowM` (default
* 40 m) of it are searched, so a car asking every tick cannot jump to a crossing section of road.
*/
closest(pos: Vec3, hintS?: number, windowM?: number): RoadClosest
/**
* Where the kerb and the wall stand at distance `s`, as lateral distances from the centre line. The wall
* is `halfWidth + kerbWidth + offsetM` out: keep a car's centre inside `barrier.inner` minus its radius
* and it stays on the road side of it.
*/
edge(s: number): RoadEdge
/** The centre line as points `stepM` apart (default the road's sample step): a minimap polyline. */
polyline(stepM?: number): Vec3[]
}
Import: import type { RoadLine } from "@argus/api"
Members
| Member | Signature | Description |
|---|---|---|
length | readonly length: number | Metres once around a closed road, end to end on an open one. |
closed | readonly closed: boolean | True for a loop (a lap circuit), false for an open road; at wraps on a closed road and clamps on an open one. |
kerbWidth | readonly kerbWidth: number | Width of the kerb strip outside each edge, metres; 0 for a road with no kerb. halfWidth does not include it. |
kerbHeight | readonly kerbHeight: number | Height of the kerb strip, metres; 0 with no kerb. |
barrier | readonly barrier: RoadBarrier | null | The wall the file asked for, or null for a road with no barrier. |
gates | readonly gates: readonly { readonly id: string; readonly s: number }[] | The road's trigger gates, in order along it: the child entity's scene id (ctx.world.find(id)) and its distance along the road. Gate 0 is the start line. |
at | at(s: number): RoadSample | The centre line at distance s. |
closest | closest(pos: Vec3, hintS?: number, windowM?: number): RoadClosest | The nearest point on the centre line to pos. With hintS only samples within windowM (default 40 m) of it are searched, so a car asking every tick cannot jump to a crossing section of road. |
edge | edge(s: number): RoadEdge | Where the kerb and the wall stand at distance s, as lateral distances from the centre line. The wall is halfWidth + kerbWidth + offsetM out: keep a car's centre inside barrier.inner minus its radius and it stays on the road side of it. |
polyline | polyline(stepM?: number): Vec3[] | The centre line as points stepM apart (default the road's sample step): a minimap polyline. |
Example
The tested fixture fixtures/app/agent.ts.
import type { Behavior } from "@argus/api"
// Sends a nav agent to `props.target` once, then reports arrival through ctx.state so the
// test can read it without polling the crowd directly.
export default {
init(ctx) {
ctx.state.arrived = false
ctx.nav?.goTo(ctx.props.target as [number, number, number])
},
update(ctx) {
if (ctx.nav?.arrived) ctx.state.arrived = true
},
} satisfies Behavior