rollRotation
Since 0.6
rotation after rolling along displacement: {@link rollFromMotion}'s delta applied in the world frame, renormalised.
For an entity with no parent, whose rotation is its world rotation.
Signature
export function rollRotation(rotation: Quat, displacement: Vec3, radius: number, normal: Vec3 = [0, 1, 0]): Quat
Import: import { rollRotation } from "@argus/gameplay"
Example
The tested fixture crates/editor/templates/behaviours/roll.ts.
import type { Behavior, Vec3 } from "@argus/api"
import { followGround, rollRotation, type GroundFollow } from "@argus/gameplay"
/**
* A ball this script moves: rolls across the ground at a steady speed, stays on it, and spins the
* way it is going.
*
* The two hard parts come from `@argus/gameplay`, the helpers the engine ships, rather than being
* written again here. `followGround` casts from above the ball's own position, keeps it resting on
* whatever is under it at its radius, and lets it fall off an edge instead of snapping down.
* `rollRotation` turns the distance it actually moved into the spin that matches it (`rollFromMotion`
* is the same thing as an axis and an angle): forward motion, forward spin, one radian per radius
* travelled. Move across the ground first (x and z), then call `followGround`, then roll by what
* the two together did.
*
* Give the entity no rigidbody: this script is what moves it. A collider on it is fine.
*/
interface State {
/** `followGround`'s memory between ticks. */
ground?: GroundFollow
}
interface Props {
/** Metres per second. Default 2. */
speed?: number
/** Direction to roll, degrees about the vertical: 0 is +x, 90 is -z. Default 0. */
heading?: number
/** The ball's radius, metres: how high it rests and how fast it spins. Default 0.5. */
radius?: number
}
export default {
update(ctx, dt) {
const speed = typeof ctx.props.speed === "number" ? ctx.props.speed : 2
const heading = ((typeof ctx.props.heading === "number" ? ctx.props.heading : 0) * Math.PI) / 180
const radius = typeof ctx.props.radius === "number" ? ctx.props.radius : 0.5
const before = ctx.entity.worldPosition
const p = ctx.entity.position
ctx.entity.position = [p[0] + Math.cos(heading) * speed * dt, p[1], p[2] - Math.sin(heading) * speed * dt]
const ground = followGround(ctx, { radius })
const after = ctx.entity.worldPosition
const moved: Vec3 = [after[0] - before[0], after[1] - before[1], after[2] - before[2]]
ctx.entity.rotation = rollRotation(ctx.entity.rotation, moved, radius, ground.normal)
},
} satisfies Behavior<State, Props>