# ride.ludic - the rider's stick steers what they are on: a horse walks, canters on stamina and # stops at water, a slope or a trunk; a boat is rowed - a stroke and a turn handed to its hull, # which the water floats, the wind drifts and the lake bed stops export function vehicle_update(vehicles_st: mut VehiclesState, ix: float, iz: float, run: bool, dt: float) -> void { let v = vehicles_st.ve_cur if v == null { return } if v.kind == VEHICLE_BOAT { ve_row(vehicles_st, v, ix, iz, dt) } else { ve_ride_horse(vehicles_st, v, ix, iz, run, dt) } VehicleWorld.placed(v) VehicleRider.ride_at(v.x, v.y + v.seat_h, v.z, v.yaw, Math.abs(v.speed)) } # the stick is the oars: forward and back a stroke, left and right the two pulled against each # other; the swell at the edge takes the outward share of a stroke function ve_row(vehicles_st: mut VehiclesState, v: Vehicle, ix: float, iz: float, dt: float) -> void { ve_hull_read(v) let take = ve_swell(vehicles_st, v, iz, dt) let sp = vehicle_spec(vehicles_st, v.kind) VehicleHull.row(v.nid, iz * sp.row * (1.0 - take), -ix * sp.row_turn) let d = Math.abs(v.speed) * dt if d > 0.0 { ve_moved_add(vehicles_st, v, d) } } # where the hull is now, and how fast it goes along its bow function ve_hull_read(v: Vehicle) -> void { if not VehicleHull.read(v.nid) { return } v.x = VehicleHull.x() v.y = VehicleHull.y() v.z = VehicleHull.z() v.yaw = VehicleHull.yaw() v.speed = VehicleHull.speed() } # a boat gets a longer leash than a swimmer and the same current at the end of it: the outward # part of the stroke only, so a boat at the limit can always be put about. The share it takes. function ve_swell(vehicles_st: mut VehiclesState, v: Vehicle, iz: float, dt: float) -> float { var fx = -Math.sin(v.yaw) var fz = -Math.cos(v.yaw) if iz < 0.0 { fx = -fx fz = -fz } let take = Math.clamp(VehicleWorld.swell(v.x, v.z, fx, fz), 0.0, 1.0) if take > 0.55 and vehicles_st.ve_swell_said < 0.0 { vehicles_st.ve_swell_said = 14.0 ve_say(vehicles_st, VEHICLE_SWELL, v, take) } vehicles_st.ve_swell_said = vehicles_st.ve_swell_said - dt return take } # every boat: a rowed one pushed by the wind across the lake; one nobody rows moored where it was # called or left, its hull read back and held there export function vehicles_tick(vehicles_st: VehiclesState, dt: float) -> void { let l = ve_all(vehicles_st) let w = VehicleWorld.wind() let wy = VehicleWorld.wind_yaw() for i in 0 .. len(l) { let v = l[i] if v.kind != VEHICLE_BOAT { continue } if v.rider >= 0 { let f = w * vehicle_spec(vehicles_st, v.kind).wind if f > 0.0 { VehicleHull.drift(v.nid, -Math.sin(wy) * f, -Math.cos(wy) * f) } continue } if not VehicleWorld.active(v.x, v.z) { continue } # outside every zone: left where it lies ve_hull_read(v) ve_hold(v) VehicleWorld.placed(v) } } # a moored hull that has moved off its mooring (a knock, the swell) is put back on it, at rest function ve_hold(v: Vehicle) -> void { let dx = v.x - v.home_x let dz = v.z - v.home_z let dyaw = Math.abs(Math.atan2(Math.sin(v.yaw - v.home_yaw), Math.cos(v.yaw - v.home_yaw))) if dx * dx + dz * dz < 0.0004 and dyaw < 0.01 and Math.abs(v.speed) < 0.01 { return } v.x = v.home_x v.z = v.home_z v.yaw = v.home_yaw v.y = VehicleWorld.water(v.x, v.z) + 0.02 v.speed = 0.0 VehicleHull.put(v.nid, v.x, v.y, v.z, v.yaw) }