ludic/packages/ludic.character/walk.ludic

74 lines
3.5 KiB
Text

# walk.ludic - the step itself: swimming, in the air, or on the ground; the distance, for the gait
function chr_travel(character_st: mut CharacterState, dx: float, dz: float, fx: float, fz: float, jump: bool, dt: float) -> float {
if character_st.chr_swim {
chr_swim_tick(character_st, dx, dz, jump, dt)
return character_st.chr_speed * dt
}
return chr_walk(character_st, fx, fz, dx, dz, jump, dt)
}
# on land the game's walker moves the body (CharacterGround.walk): gravity, landing, a step up to
# CHAR_STEP, a slope up to what the boots take. The rules stay here: how fast, where, when a jump
# leaves, when the lake takes the body, and what is said about it.
function chr_walk(character_st: mut CharacterState, fx: float, fz: float, dx: float, dz: float, jump: bool, dt: float) -> float {
var vx = fx * character_st.chr_speed
var vz = fz * character_st.chr_speed
var up = 0.0
if character_st.chr_knock > 0.0 {
up = character_st.chr_knock
character_st.chr_knock = 0.0
vx = character_st.chr_air_vx
vz = character_st.chr_air_vz
} else if character_st.chr_air {
character_st.chr_air_vx = character_st.chr_air_vx + dx * (4.0 * dt)
character_st.chr_air_vz = character_st.chr_air_vz + dz * (4.0 * dt)
vx = character_st.chr_air_vx
vz = character_st.chr_air_vz
} else if jump and character_st.chr_can_run and character_st.chr_land < 0.05 {
up = 5.0
character_st.chr_air_vx = vx
character_st.chr_air_vz = vz
chr_say(character_st, CHAR_JUMPED, 0.0)
}
let slope = Math.atan2(CharacterGround.slope_limit(), 1.0) * 57.29578
let g = CharacterGround.walk(character_st.chr_x, character_st.chr_y, character_st.chr_z, vx, vz, up, CHAR_STEP, slope, dt)
return chr_walked(character_st, g, up > 0.0, dt)
}
# where the walker put the body, and what that means: the lake, a landing, a slope too steep
function chr_walked(character_st: mut CharacterState, g: int, jumped: bool, dt: float) -> float {
let nx = CharacterGround.walked_x()
let ny = CharacterGround.walked_y()
let nz = CharacterGround.walked_z()
if ny < CharacterGround.water(nx, nz) - CHAR_WADE_MAX {
chr_enter_water(character_st, nx, nz)
return character_st.chr_speed * dt
}
let was_air = character_st.chr_air
character_st.chr_air = g == CHAR_WALK_AIR or jumped
if was_air and not character_st.chr_air { chr_landed(character_st) }
if g == CHAR_WALK_STEEP and not character_st.chr_air {
if not (character_st.chr_steep > 0.0) { chr_say(character_st, CHAR_TOO_STEEP, ny - character_st.chr_y) }
character_st.chr_steep = 1.2
character_st.chr_speed = 0.0
}
let mx = nx - character_st.chr_x
let mz = nz - character_st.chr_z
character_st.chr_step = Math.sqrt(mx * mx + mz * mz)
character_st.chr_vy = (ny - character_st.chr_y) / Math.max(dt, 0.0001)
character_st.chr_x = nx
character_st.chr_y = ny
character_st.chr_z = nz
if character_st.chr_air { return character_st.chr_speed * (dt * 0.4) }
return character_st.chr_speed * dt
}
function chr_landed(character_st: mut CharacterState) -> void {
character_st.chr_land = 0.22
let carried = Math.sqrt(character_st.chr_air_vx * character_st.chr_air_vx + character_st.chr_air_vz * character_st.chr_air_vz)
# the walk goes on only as fast as the air was carrying it the way it faces (a knock from the
# front does not walk it back into what knocked it)
let along = -Math.sin(character_st.chr_yaw) * character_st.chr_air_vx - Math.cos(character_st.chr_yaw) * character_st.chr_air_vz
character_st.chr_speed = Math.max(along, 0.0)
chr_say(character_st, CHAR_LANDED, carried)
}