/** * Fish Behavior & Animation Constants * * All magic numbers extracted and documented for maintainability. * Values are tuned for a calm, ambient deep ocean aesthetic. */ import type { DepthLayer, FishSpecies } from "../models/OceanModels.js"; /** * Depth layer visual properties. * Far fish appear smaller/slower (parallax effect simulating distance). * Near fish are larger/faster and more prominent. */ export declare const DEPTH_LAYER_CONFIG: Record; /** * Probability distribution for depth layer assignment. * More fish in mid layer creates natural depth distribution. */ export declare const DEPTH_LAYER_DISTRIBUTION: { /** Probability of far layer (0-25%) */ farThreshold: number; /** Probability of mid layer (25-70%) */ midThreshold: number; }; export declare const FISH_MOVEMENT: { /** Base horizontal speed range [min, max] in pixels per second */ baseSpeed: readonly [25, 55]; /** Vertical drift range (pixels per second, centered at 0) */ verticalDrift: number; /** Bobbing animation amplitude range [min, max] in pixels */ bobAmplitude: readonly [2, 5]; /** Bobbing animation speed range [min, max] (radians per frame at 60fps) */ bobSpeed: readonly [0.008, 0.02]; /** Maximum spawn offset from screen edge (pixels or fraction of width) */ spawnOffset: { pixels: number; fractionOfWidth: number; }; }; /** * Species-specific speed multipliers * Fast fish like sleek predators swim faster than tropical fish */ export declare const SPECIES_SPEED_MULTIPLIERS: Record; export declare const BEHAVIOR_CONFIG: { /** * Cruising: Normal swimming state * Fish swim in one direction with gentle bob motion */ cruising: { /** Duration range [min, max] in seconds before behavior change */ duration: readonly [8, 20]; }; /** * Turning: Fish reverses direction * Triggered randomly or when approaching screen edge */ turning: { /** Fixed duration in seconds */ duration: number; /** Speed multiplier during turn (slows down) */ speedMultiplier: number; /** Maximum rotation angle in radians */ maxRotation: number; }; /** * Darting: Natural fish C-start escape response * * Based on fish biomechanics research: real fish use a three-phase escape: * 1. COIL (preparatory): Body tenses, bends into C-shape (~50ms) * 2. BURST (propulsive): Explosive tail flip acceleration (~150ms) * 3. RECOVERY (deceleration): Gradual easeOutExpo slowdown (~400ms) * * Reference: Journal of Experimental Biology - Fish Escape Responses */ darting: { /** Total duration of all three phases (seconds) */ duration: number; /** Phase 1: Coil (preparatory) - body tenses before burst */ coilDuration: number; coilSpeedMultiplier: number; /** Phase 2: Burst (propulsive) - explosive acceleration */ burstDuration: number; burstSpeedMultiplier: readonly [4, 6]; /** Phase 3: Recovery (deceleration) - gradual slowdown */ recoveryDuration: number; /** Legacy: kept for compatibility but not used in new 3-phase system */ speedMultiplier: readonly [2.5, 4]; }; /** * Schooling: Fish follow group leader * Maintains formation while cruising */ schooling: { /** Duration range [min, max] in seconds */ duration: readonly [10, 25]; }; /** * Passing: Fast direct swimmer - no bobbing, straight line * Creates variety with some fish that zoom across the screen */ passing: { /** Duration range [min, max] in seconds */ duration: readonly [2, 4]; /** Speed multiplier range [min, max] - much faster than cruising */ speedMultiplier: readonly [3, 5]; /** Body flex is reduced for streamlined appearance */ bodyFlexMultiplier: number; }; /** * Ascending: Swimming upward with focus on vertical movement * Fish browses toward the surface */ ascending: { /** Duration range [min, max] in seconds */ duration: readonly [1.5, 3]; /** Speed multiplier (slightly slower than cruising) */ speedMultiplier: number; /** Vertical movement range [min, max] pixels per second */ verticalSpeed: readonly [30, 60]; /** Body rotation angle range [min, max] in radians (tilted up) */ bodyRotation: readonly [0.26, 0.44]; }; /** * Descending: Swimming downward with focus on vertical movement * Fish browses toward the depths */ descending: { /** Duration range [min, max] in seconds */ duration: readonly [1.5, 3]; /** Speed multiplier (slightly slower than cruising) */ speedMultiplier: number; /** Vertical movement range [min, max] pixels per second (negative = down) */ verticalSpeed: readonly [-60, -30]; /** Body rotation angle range [min, max] in radians (tilted down) */ bodyRotation: readonly [-0.44, -0.26]; }; /** * Approaching: Swimming toward camera (z decreasing) * Fish grows larger and more prominent */ approaching: { /** Duration range [min, max] in seconds - slow for smooth scaling */ duration: readonly [3, 6]; /** Z-axis change range [min, max] - how much closer the fish gets */ zChange: readonly [-0.4, -0.2]; /** Speed multiplier (normal horizontal movement) */ speedMultiplier: number; }; /** * Receding: Swimming away from camera (z increasing) * Fish shrinks and fades into the background */ receding: { /** Duration range [min, max] in seconds - slow for smooth scaling */ duration: readonly [3, 6]; /** Z-axis change range [min, max] - how much farther the fish gets */ zChange: readonly [0.2, 0.4]; /** Speed multiplier (normal horizontal movement) */ speedMultiplier: number; }; }; /** * Depth transition configuration for 3D z-axis movement */ export declare const DEPTH_TRANSITION: { /** Lerp speed for z-axis movement (per frame at 60fps) */ lerpSpeed: number; /** Minimum z value (closest to camera) */ minZ: number; /** Maximum z value (farthest from camera) */ maxZ: number; /** Scale factor: scale = 1 - (z * scaleReduction) */ scaleReduction: number; /** Opacity factor: opacity = 1 - (z * opacityReduction) */ opacityReduction: number; /** Speed factor: speed = 1 - (z * speedReduction) */ speedReduction: number; }; /** * Probability of transitioning to each behavior from cruising. * Probabilities are checked in order; remaining = continue cruising. */ export declare const BEHAVIOR_TRANSITION_PROBABILITY: { /** Chance to initiate a turn (8%) */ turn: number; /** Chance to dart/startle (4%) - checked after turn */ dart: number; /** Chance to start passing (fast straight swim) (3%) */ passing: number; /** Chance to start ascending (5%) */ ascending: number; /** Chance to start descending (5%) */ descending: number; /** Chance to approach (swim toward camera) (2%) */ approaching: number; /** Chance to recede (swim away from camera) (2%) */ receding: number; }; /** * Species-specific vertical preferences within their depth band. * Controls where fish spawn and drift over time. * * preferredZone: [0, 1] where 0 = top of band, 1 = bottom * zoneAffinity: how strongly fish are drawn back to preferred zone (0-1) * ascendingMod/descendingMod: multipliers for vertical movement probability */ export declare const SPECIES_VERTICAL_PREFERENCES: Record; /** * Species-specific behavior probability modifiers. * Multipliers applied to base probabilities. */ export declare const SPECIES_BEHAVIOR_MODIFIERS: Record>>; /** * Edge awareness thresholds. * Fish are more likely to turn when approaching screen edges. */ export declare const EDGE_AWARENESS: { /** Distance from edge (as fraction of screen width) to start considering turn */ warningZone: number; /** Multiplier for turn probability when in warning zone */ turnProbabilityMultiplier: number; }; export declare const FLOCKING_CONFIG: { /** * Separation: Steer to avoid crowding nearby fish */ separation: { /** Radius within which separation force applies (pixels) */ radius: number; /** Strength of separation force */ weight: number; }; /** * Alignment: Steer towards average heading of nearby fish */ alignment: { /** Radius within which alignment force applies (pixels) */ radius: number; /** Strength of alignment force */ weight: number; }; /** * Cohesion: Steer towards center of mass of nearby fish */ cohesion: { /** Radius within which cohesion force applies (pixels) */ radius: number; /** Strength of cohesion force */ weight: number; }; /** Maximum steering force per frame (limits sudden turns) */ maxSteeringForce: number; /** School formation */ school: { /** Target number of fish per school */ size: readonly [2, 4]; /** Percentage of fish population to form into schools */ populationFraction: number; }; }; export declare const FISH_VISUALS: { /** Tail wiggle animation speed multiplier (relative to movement speed) */ tailWiggleSpeed: number; /** Maximum tail skew for wiggle effect */ maxTailSkew: number; /** Rotation response to vertical drift (tilt when swimming up/down) */ driftRotationFactor: number; /** Rotation smoothing factor (0-1, lower = smoother) */ rotationSmoothing: number; }; export declare const SPAWN_CONFIG: { /** Delay range [min, max] in seconds before respawning off-screen fish */ respawnDelay: readonly [2, 8]; /** Buffer zone beyond screen edge before fish is considered "off-screen" */ offScreenBuffer: number; }; export declare const FISH_COUNTS: Record; export declare const JELLYFISH_COUNTS: Record; import type { FishMood, MoodVisuals } from "../types/fish-personality-types.js"; /** * Mood decay rates (per second) * Higher = faster return to calm */ export declare const MOOD_DECAY_RATES: Record; /** * Visual modifiers for each mood * Applied to rendering to express emotional state */ export declare const MOOD_VISUALS: Record; /** * Mood thresholds for automatic transitions */ export declare const MOOD_THRESHOLDS: { /** Energy below this triggers tired mood */ tiredEnergy: number; /** Hunger above this triggers hungry mood */ hungryLevel: number; /** Seconds without stimulus before mood decays */ boredTimeout: number; /** Energy below this prevents playful mood */ playfulMinEnergy: number; }; /** * Stimulus effects on mood */ export declare const STIMULUS_EFFECTS: Record<"food" | "threat" | "friend" | "novelty", { mood: FishMood; energyCost: number; hungerEffect: number; }>; /** * Energy and hunger drift rates per second */ export declare const METABOLISM_RATES: { /** Energy drain per second (base rate) */ energyDrain: number; /** Energy drain multiplier when moving fast */ fastMovementDrain: number; /** Hunger increase per second */ hungerIncrease: number; /** Energy recovery when resting */ restRecovery: number; }; /** * Exponential-approach rates (1/s) for easing `speed` toward `targetSpeed`. * Higher = snappier ramp. Darting is high so the C-start still bursts, but over * ~120ms not one frame. Tunable live in OceanLab. */ export declare const MOTION_SMOOTHING: { /** default speed ease rate for cruise/pass/ascend/descend/etc. */ speedRate: number; /** faster ease during darting burst so it still reads as explosive */ dartSpeedRate: number; /** heading ease rate for turns (direction flip ramps through 0) */ headingRate: number; }; /** * Real fish modulate tail-beat FREQUENCY with swim speed far more than * amplitude (amplitude saturates quickly - a sprinting fish beats faster, it * doesn't flop wider). Scaling both linearly with speed made darts/chases * look like panicked flopping at 4-6x amplitude. */ export declare const SWIM_GAIT: { /** tail-beat frequency multiplier clamp [min, max] vs speed ratio */ frequencyScale: readonly [0.4, 2.5]; /** amplitude multiplier = sqrt(speedRatio) clamped to [min, max] */ amplitudeScale: readonly [0.5, 1.4]; /** * Bob amplitude damping at speed: fast fish hold a level line. Scale = * 1 / (1 + (speedRatio - 1) * bobDamping), clamped to bobScaleMin. */ bobDamping: number; bobScaleMin: number; }; /** * Fish turn in an arc, not a flat pivot. During the turning behavior the fish * carves a subtle vertical arc (peaking mid-turn), which with the heading * ease reads as a banked U-turn instead of a moonwalk reverse. */ export declare const TURN_ARC: { /** peak vertical carve speed (px/s) at the middle of the turn */ peakVerticalSpeed: number; }; export declare const LATERAL_WANDER: { /** base frequency for the smooth wander signal */ frequency: number; /** amplitude (px) of the dart-phase lateral wander */ dartAmplitude: number; /** amplitude (px) of the recovery-phase residual wander */ recoveryAmplitude: number; }; export declare const CURSOR_FLEE: { /** base scatter radius (px), scaled by boldness in computeFlee */ radius: number; /** peak horizontal speed multiplier at full flee intensity */ speedMultiplier: number; /** vertical flee velocity scale (px/s) at full intensity */ verticalForce: number; /** panic duration (s) seeded on trigger; recovery eases over this window */ panicDuration: number; /** master on/off; flee is active wherever the ocean background renders */ enabled: boolean; }; //# sourceMappingURL=fish-constants.d.ts.map