fix(spatial): decorrelate spawn radius from angle to stop avatar overlap
The previous spawn fix (radius 20 -> 6) traded one problem for another: hashing only the angle onto a small fixed-radius ring means two names whose hashes land near the same angle bucket (only 360 of them) now separate by just a few pixels of arc instead of dozens, since arc length scales with radius. Confirmed against the actual guest names from a live session (guest-pxj6/guest-rd7o): old algorithm placed them ~11 room units apart, easily close enough for their ~34px graph nodes to visually merge into what looked like a single dot. Now the radius is hashed independently from the angle (8-19 units), so an angle collision no longer implies a full positional overlap. Same test names now land ~27.6 units apart. Still well within the range that keeps audio at full gain (refDistance=4). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f68e77472e
commit
8474a85ed2
1 file changed
+20
-10
+20
-10
@@ -1524,17 +1524,27 @@ setInterval(() => {
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
// Spawn me slightly off-center so two people don't land exactly on top of
|
||||
// each other — small radius on purpose: at refDistance=4/rolloffFactor=1.4,
|
||||
// the old radius-20 ring put name-hash-unlucky pairs up to 40 units apart
|
||||
// (diametrically opposite), which is already down to ~7% audio gain before
|
||||
// anyone's said a word.
|
||||
// Spawn me slightly off-center so people don't land on top of each other.
|
||||
// A single hashed angle on a *fixed* radius ring (the previous approach)
|
||||
// puts anyone whose name hashes to a nearby angle almost exactly on top of
|
||||
// each other too — on a small ring, "nearby angle" is only a few pixels of
|
||||
// arc, and with just 360 angle buckets that's common (especially with the
|
||||
// same recurring guest-xxxx test names). Hashing the radius independently
|
||||
// from the angle means an angle collision no longer implies a full overlap.
|
||||
// Both stay small enough that at refDistance=4/rolloffFactor=1.4 (see
|
||||
// updatePanner) nobody starts out attenuated — this is purely about the
|
||||
// dots being visually distinguishable, not audio range.
|
||||
(() => {
|
||||
let h = 0;
|
||||
for (const c of S.myId || S.name) h = (h * 33 + c.charCodeAt(0)) >>> 0;
|
||||
const a = (h % 360) * (Math.PI / 180);
|
||||
S.me.x = 50 + 6 * Math.cos(a);
|
||||
S.me.y = 50 + 6 * Math.sin(a);
|
||||
const key = S.myId || S.name;
|
||||
let hAngle = 0, hRadius = 0;
|
||||
for (const c of key) {
|
||||
hAngle = (hAngle * 33 + c.charCodeAt(0)) >>> 0;
|
||||
hRadius = (hRadius * 17 + c.charCodeAt(0) + 7) >>> 0;
|
||||
}
|
||||
const a = (hAngle % 360) * (Math.PI / 180);
|
||||
const r = 8 + (hRadius % 12); // 8..19 room units
|
||||
S.me.x = 50 + r * Math.cos(a);
|
||||
S.me.y = 50 + r * Math.sin(a);
|
||||
})();
|
||||
|
||||
window.addEventListener('keydown', (ev) => {
|
||||
|
||||
Reference in new issue
Block a user