Skip to content

[Bug] solidAt() tests a single point, so the diver clips ~1m into geometry #122

Description

@N1k4G

solidAt() takes no diver radius or extent parameter, and both call sites in the physics loop pass the diver's centre only. Movement stops when the centre enters a structure, so the diver sprite penetrates roughly a metre into walls, hulls and decks before the engine reacts.

The function

src/sites.js:797 — bare point-in-AABB:

function solidAt(x, d) {
  var s = activeSite();
  if (!s) return false;
  for (var i = 0; i < s.structures.length; i++) {
    var w = s.structures[i];
    if (x >= w.x1 && x <= w.x2 && d >= w.dTop && d <= w.dBottom) return true;
  }
  return false;
}

Call sites: src/physics.js:132 (vertical sub-step) and src/physics.js:182 (horizontal sub-step). Both pass diverX / depth unmodified.

Reproduction

Probing the wreck's bow stem (AABB x1:14, x2:16, dTop:28, dBottom:66) at d = 33.8 via window.gameAPI.solidAt:

Diver x centre x − 0.5 m x − 1 m Reading
16.0 solid solid solid blocked, correct
16.4 open solid solid body 0.5 m inside hull, reads open
16.7 open open solid body 1 m inside hull, reads open
17.5 open open open genuinely clear

Driving the horizontal loop leftward from x = 19, the diver settles at x ≈ 16.67 — the point where its centre meets the stem — with its left side roughly a metre inside the hull.

Possible relation to #101

#101 ("Review rock (AABB boulder) hitboxes") was closed without a definitive fix, framed as "collision may trigger noticeably before/after the diver visually touches the rock."

A point test produces exactly that, systematically: collision always fires late by half the sprite's width, on every structure in every site, regardless of how well the AABB fits the art. That may account for some of the original feedback that opened #101 — worth checking whether fixing extent here resolves it, before doing per-rock AABB tuning.

Note this is a separate axis from #101's actual subject. #101 asks whether the box matches the silhouette; this asks whether the diver has a body at all. Both can be wrong independently.

Notes

  • Not affected by feat: WP-07 site and asset pipeline #119. solidAt() is not reimplemented there — the parity test replays the legacy function against the extracted data, so this behaviour carries across unchanged. The new validation checks profile ordering, box inversion and depth reachability, but nothing about diver extent.
  • Any fix needs to keep the existing "only block when crossing from open water into solid" escape hatch at src/physics.js:131-134, which lets a diver who somehow starts inside a structure swim free.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions