feat(perception): ground vision cone in human sensory physiology
- Visible half-angle 150° → 100° (200° arc), matching average human binocular field. Blind spot widens from 60° to 160° — genuine vulnerability behind the character. - Forward half-angle stays at 60° (120° arc) — binocular overlap zone. - Peripheral zone represents combined sensory awareness: visual periphery + subconscious sound/motion tracking, not just eyes. - Per-character VisionConeConfig allows implants and perception modes (D-017) to widen beyond the unaugmented baseline. - Fog shader: smooth back-edge gradient via smoothstep blend between Layer 2 (peripheral) and Layer 3 (deep fog), eliminating blocky stair-stepped tiles at the rear of the vision cone. - D-015 updated with physiological basis and per-character config. - D-017 updated with vision cone modification by perception modes. - D-020 updated with protocol versioning policy: PROTOCOL_VERSION gates wire format, not gameplay parameters. - DB backup after sprint 21 close. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,21 @@
|
||||
//! Vision cone system (D-015)
|
||||
//!
|
||||
//! Modulates raw shadowcast output with direction-dependent sectors:
|
||||
//! - Forward: full LOS range, full detail (~120 degree arc)
|
||||
//! - Peripheral: reduced range, dimmer (~90 degrees each side)
|
||||
//! - Behind: blind (excluded from output)
|
||||
//! Modulates raw shadowcast output with direction-dependent sectors
|
||||
//! grounded in human sensory physiology:
|
||||
//!
|
||||
//! - Forward: 120° arc (60° half-angle) — binocular overlap zone where
|
||||
//! both eyes converge. Stereoscopic depth, high acuity. Full LOS range.
|
||||
//! - Peripheral: extends to 200° arc (100° half-angle) — combined sensory
|
||||
//! awareness envelope. Beyond pure visual acuity (~120°), this includes
|
||||
//! subconscious tracking of sound cues, movement in the corner of the
|
||||
//! eye, and ambient sensory input. Reduced range, dimmer rendering.
|
||||
//! The fog shader gradient (D-059) is aligned to this outer edge.
|
||||
//! - Behind: 160° blind arc — no sensory awareness without explicit cues.
|
||||
//! You can be snuck up on. Monologue system (D-016) bridges this gap
|
||||
//! when the character's other senses fire.
|
||||
//!
|
||||
//! Reference: binocular field ~200° horizontal, overlap ~120°,
|
||||
//! far peripheral limit ~100-105° per eye (Wikipedia, NCBI NBK220).
|
||||
//!
|
||||
//! Y-down convention: North = (0, -1)
|
||||
|
||||
@@ -22,16 +34,23 @@ impl Default for Facing {
|
||||
}
|
||||
}
|
||||
|
||||
/// Vision cone configuration per D-015
|
||||
/// Vision cone configuration per D-015.
|
||||
///
|
||||
/// Angles grounded in human visual field physiology:
|
||||
/// - forward_half_angle (60°): binocular overlap — where both eyes converge,
|
||||
/// providing stereoscopic depth and high acuity.
|
||||
/// - visible_half_angle (100°): average human binocular field limit — the
|
||||
/// outermost boundary of peripheral vision. The fog shader's transparency
|
||||
/// gradient is aligned to this edge.
|
||||
pub struct VisionConeConfig {
|
||||
/// Maximum vision range for forward sector (in tiles)
|
||||
pub forward_range: i32,
|
||||
/// Maximum vision range for peripheral sector (shorter than forward)
|
||||
pub peripheral_range: i32,
|
||||
/// Half-angle of forward cone in radians (~60 degrees = 120 degree arc)
|
||||
/// Half-angle of forward cone in radians (60° = 120° arc, binocular overlap)
|
||||
pub forward_half_angle: f32,
|
||||
/// Half-angle of total visible cone in radians (~150 degrees = 300 degree arc)
|
||||
/// Tiles beyond this are in the blind spot
|
||||
/// Half-angle of total visible cone in radians (100° = 200° arc, peripheral limit)
|
||||
/// Tiles beyond this are in the blind spot (~160° behind)
|
||||
pub visible_half_angle: f32,
|
||||
}
|
||||
|
||||
@@ -40,8 +59,8 @@ impl Default for VisionConeConfig {
|
||||
Self {
|
||||
forward_range: 20,
|
||||
peripheral_range: 12,
|
||||
forward_half_angle: std::f32::consts::FRAC_PI_3, // 60 degrees = 120 degree arc
|
||||
visible_half_angle: 5.0 * std::f32::consts::FRAC_PI_6, // 150 degrees = 300 degree arc
|
||||
forward_half_angle: std::f32::consts::FRAC_PI_3, // 60° = 120° arc (binocular overlap)
|
||||
visible_half_angle: 100.0_f32.to_radians(), // 100° = 200° arc (peripheral limit)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,7 +277,7 @@ mod tests {
|
||||
assert!(!cone.is_empty());
|
||||
|
||||
// Tile directly south (same x, far behind) should be in blind spot
|
||||
// The blind spot is the 60 degrees directly behind
|
||||
// The blind spot is ~160 degrees behind (beyond 100° peripheral limit)
|
||||
let has_direct_south_far = cone.iter().any(|&(x, y, _)| x == 5 && y >= 10);
|
||||
assert!(
|
||||
!has_direct_south_far,
|
||||
|
||||
Reference in New Issue
Block a user