134 lines
7 KiB
Text
134 lines
7 KiB
Text
# ports.ludic - what the body asks the game. Unbound, the world is a dry plain with no colliders,
|
|
# the boots manage 1.05 m a metre, the body is fresh and nothing holds or carries it.
|
|
export port CharacterGround {
|
|
height: fn(float, float) -> float # the world's own ground: pure, never the body's
|
|
# (x, z, r, from_y, step, base): the top of a collider within `step` above from_y, else base
|
|
top_at: fn(float, float, float, float, float, float) -> float = fn chr__top_plain
|
|
bed: fn(float, float) -> float = fn chr__bed_plain # the bed under water (unbound: the ground)
|
|
water: fn(float, float) -> float = fn chr__dry # the surface over a point
|
|
# (x, z, r, y0, y1): true when a collider takes a body of radius r there; pushed_x / _z say where to
|
|
push: fn(float, float, float, float, float) -> bool = fn chr__no_push
|
|
pushed_x: fn() -> float = fn chr__asked_x
|
|
pushed_z: fn() -> float = fn chr__asked_z
|
|
slope: fn(float, float) -> float = fn chr__slope_plain # 0 flat .. 1 a wall
|
|
slope_limit: fn() -> float = fn chr__boots # the rise a metre the boots take
|
|
current: fn(float, float, float, float) -> float = fn chr__still # (x, z, fx, fz): 0..1 of a stroke lost
|
|
# (x, y, z, vx, vz, jump, step, max_slope_deg, dt): the body on land moved from where it stands at
|
|
# (vx, vz) across, jump > 0 leaving the ground at that speed up; the ground after it (CHAR_WALK_*),
|
|
# and walked_x / _y / _z where it is. The game's physics walker; there is no default mover.
|
|
walk: fn(float, float, float, float, float, float, float, float, float) -> int
|
|
walked_x: fn() -> float
|
|
walked_y: fn() -> float
|
|
walked_z: fn() -> float
|
|
}
|
|
|
|
export port CharacterBody {
|
|
pace: fn() -> float = fn chr__one # the walk and run, times (gear, a tired body)
|
|
sneaking: fn() -> bool = fn chr__no
|
|
breath: fn() -> float = fn chr__one # the lungs, times
|
|
riding: fn() -> bool = fn chr__no # something else carries the body
|
|
ride: fn(float, float, bool, float) -> void = fn chr__not_carried # (ix, iz, run, dt) while riding
|
|
holding: fn() -> bool = fn chr__no # at work on something: face it
|
|
hold_x: fn() -> float = fn chr__zero
|
|
hold_z: fn() -> float = fn chr__zero
|
|
eyes_ok: fn() -> bool = fn chr__yes # first person may be used now
|
|
}
|
|
|
|
# the stick, once a frame: move is in the camera's frame (+z ahead), look is radians this frame
|
|
export port CharacterInput {
|
|
move_x: fn() -> float = fn chr__zero
|
|
move_z: fn() -> float = fn chr__zero
|
|
run: fn() -> bool = fn chr__no
|
|
jump: fn() -> bool = fn chr__no
|
|
look_yaw: fn() -> float = fn chr__zero
|
|
look_pitch: fn() -> float = fn chr__zero
|
|
zoom: fn() -> float = fn chr__zero # wheel notches, in toward the body
|
|
look_always: fn() -> bool = fn chr__no # the look is held: never settle behind
|
|
}
|
|
|
|
export state CharacterState {
|
|
chr_out_x: float = 0.0
|
|
chr_out_z: float = 0.0
|
|
chr_ask_x: float = 0.0
|
|
chr_ask_z: float = 0.0
|
|
chr_x: float = 0.0
|
|
chr_y: float = 0.0
|
|
chr_z: float = 0.0
|
|
chr_yaw: float = 0.0 # facing, radians; 0 faces -z
|
|
chr_speed: float = 0.0 # m/s along the facing
|
|
chr_phase: float = 0.0 # the gait: one cycle is two steps, advanced by ground covered
|
|
chr_move: float = 0.0 # 0 standing .. 1 moving
|
|
chr_run: float = 0.0 # 0 walking .. 1 running
|
|
chr_time: float = 0.0
|
|
chr_water: float = -10000.0 # the water line under the body, every update
|
|
chr_walk_speed: float = 3.2
|
|
chr_run_speed: float = 6.8
|
|
chr_vy: float = 0.0
|
|
chr_air: bool = false
|
|
chr_air_vx: float = 0.0
|
|
chr_air_vz: float = 0.0
|
|
chr_knock: float = 0.0 # a knock-back's speed up, handed to the walker on the next step
|
|
chr_land: float = 0.0 # seconds of the landing's crouch left
|
|
chr_steep: float = 0.0 # seconds of "that was too steep" left to say
|
|
chr_can_run: bool = true
|
|
chr_step: float = 0.0 # metres covered this frame
|
|
chr_sit: bool = false
|
|
chr_sit_mode: int = 0
|
|
chr_sit_t: float = 0.0 # 0 standing .. 1 sat, eased over a quarter second
|
|
chr_sit_x: float = 0.0 # the seat's point, walked to over the blend
|
|
chr_sit_y: float = 0.0 # the seat's top
|
|
chr_sit_z: float = 0.0
|
|
chr_sit_h: float = 0.0 # the seat's top above the feet; 0 on the ground
|
|
chr_sit_yaw: float = 0.0
|
|
chr_leave_x: float = 0.0 # where standing up leaves the seat for
|
|
chr_leave_z: float = 0.0
|
|
chr_swim: bool = false
|
|
chr_dive: bool = false
|
|
chr_depth: float = 0.0 # metres below the surface
|
|
chr_breath: float = 0.0
|
|
chr_float: float = 0.0 # 0 swimming .. 1 floating
|
|
chr_swim_phase: float = 0.0
|
|
chr_edge_said: float = 0.0
|
|
chr_holds: int = CHAR_HOLD_SCREEN
|
|
chr_cam_yaw: float = 0.0
|
|
chr_cam_pitch: float = -0.157
|
|
chr_cam_dist: float = 4.2
|
|
chr_lock: bool = false # the orbit never settles behind on its own
|
|
chr_fps: bool = false
|
|
chr_fps_bob: float = 0.0
|
|
chr_piv_x: float = 0.0
|
|
chr_piv_y: float = 0.0
|
|
chr_piv_z: float = 0.0
|
|
chr_eye_x: float = 0.0 # where the camera is and where it looks, once computed
|
|
chr_eye_y: float = 0.0
|
|
chr_eye_z: float = 0.0
|
|
chr_eye_yaw: float = 0.0
|
|
chr_eye_pitch: float = 0.0
|
|
chr_eyes_now: bool = false # the last camera was the eyes: the figure is hidden
|
|
chr_safe_x: float = 0.0
|
|
chr_safe_z: float = 0.0
|
|
chr_fact_q: Queue<CharacterFact> = chr_fact_q__new()
|
|
@max(1024) chr_fpool: []CharacterFact = chr_fpool_new() # every fact record made, reused once no drain holds it
|
|
@max(1024) chr_ffree: []CharacterFact = chr_ffree_new()
|
|
chr_fnext: int = 0
|
|
}
|
|
function chr__top_plain(x: float, z: float, r: float, from_y: float, step: float, base: float) -> float { return base }
|
|
function chr__bed_plain(x: float, z: float) -> float { return CharacterGround.height(x, z) }
|
|
function chr__dry(x: float, z: float) -> float { return -10000.0 }
|
|
function chr__no_push(x: float, z: float, r: float, y0: float, y1: float) -> bool { return false }
|
|
function chr__asked_x(character_st: CharacterState) -> float { return character_st.chr_ask_x }
|
|
function chr__asked_z(character_st: CharacterState) -> float { return character_st.chr_ask_z }
|
|
function chr__slope_plain(x: float, z: float) -> float {
|
|
let e = 2.0
|
|
let dx = CharacterGround.height(x + e, z) - CharacterGround.height(x - e, z)
|
|
let dz = CharacterGround.height(x, z + e) - CharacterGround.height(x, z - e)
|
|
return 1.0 - 4.0 / Math.sqrt(dx * dx + dz * dz + 16.0)
|
|
}
|
|
function chr__boots() -> float { return 1.05 }
|
|
function chr__still(x: float, z: float, fx: float, fz: float) -> float { return 0.0 }
|
|
function chr__one() -> float { return 1.0 }
|
|
function chr__zero() -> float { return 0.0 }
|
|
function chr__no() -> bool { return false }
|
|
function chr__yes() -> bool { return true }
|
|
function chr__not_carried(ix: float, iz: float, run: bool, dt: float) -> void { }
|
|
function chr_fact_q__new() -> Queue<CharacterFact> { return queue_new("character.facts") }
|