Caso real de desarrollo de CONTRABAND

Pointer lock frente a diálogo clicable

Un producto educativo de Martinez AI Studios

El vuelo quiere el ratón capturado. Los botones de elección 1/2 necesitan el ratón libre. Esos estados chocaron en Last Run.

Durante Last Run, una UI de hail/elección con botones 1/2 clicables podía aparecer con el pointer lock aún activo. Teclado/ratón no podían hacer clic. Mando no necesitaba el mismo aviso. El arreglo documentado es “Pulsa ESC para tomar el mouse”, con dos reglas siguientes: no recapturar mientras el hail está abierto, y tras ESC no volver a pedir ESC.

Categoría
Input / UX
Proyecto
CONTRABAND
Registrado
2026-08-19
Estado
Verificado · publicado

1. Síntoma

Las elecciones de historia clicables estaban en pantalla con document.pointerLockElement activo. El cursor estaba capturado para vuelo. ESC también abría otra UI de saltar el tutorial si el aviso de recaptura era incorrecto.

2. Impacto en el jugador

Una elección a tiempo o crítica (incluido el hail de Varek) no se podía tomar con el ratón. Los jugadores golpeaban ESC y o recapturaban el lock al instante o abrían Saltar. Quien usaba mando no sufría la ruta de clic, así que el bug parecía “aleatorio” según el dispositivo.

3. Reproducción

Entrar a Last Run con teclado/ratón, mantener pointer lock, llegar a un hail con botones 1/2 visibles. Intentar clic. Pulsar ESC. Confirmar si el lock vuelve al instante y si se abre Saltar. lastRunShouldShowReleaseMouseHint es verdadero solo cuando pointerLocked && clickableChoiceVisible && dominantDevice !== "gamepad".

4. Ownership del sistema

La política de pointer lock para historia vs combate live está en pointer-lock-policy.js. Las reglas del aviso de Last Run están en last-run-map-lesson.js / last-run-from-verge.js. Muchos otros sistemas llaman exitPointerLock al abrir estaciones, mapas o historia — el incidente es el handoff que faltaba cuando un overlay clicable abre sin salir del lock.

5. Supuesto erróneo

Si una UI es visible, el ratón está disponible. Si el jugador pulsa ESC, quiere el lock otra vez. Una sola frase de recaptura (“pulsa ESC”) sirve antes y después de que el navegador ya haya soltado el lock.

6. Causa raíz

Pointer lock y DOM clicable son mutuamente excluyentes en Chromium de escritorio. Last Run mostraba elecciones sin salir del lock. Tras soltar el lock con ESC, se seguía mostrando el mismo texto “pulsa ESC”, así que ESC quedaba sobrecargado (recapturar vs Saltar). Mientras el hail seguía abierto, la recaptura volvía a robar el cursor.

7. Arreglo mínimo

Mostrar el aviso de soltar el ratón solo con pointer locked + elecciones clicables visibles + no mando. Mientras ese hail está abierto, ESC no recaptura. Tras ESC, el aviso pasa a clic-para-recapturar y el lock se reintenta solo tras el cooldown del navegador. No cambiar progresión ni recompensas (un toast de Supervivencia posterior se hizo no modal para no soltar el lock).

8. Test de regresión

last-run-from-verge.test.mjs cubre el aviso de ESC y el copy de recaptura. lastRunShouldShowReleaseMouseHint se testa con los tres predicados (lock, elecciones, dispositivo).

9. Validación de release

Log de desarrollo 19 ago 2026, v0.4.148–v0.4.153: aviso ESC, sin recaptura durante el hail, aviso de clic tras ESC. El QA Electron posterior de Last Run (celdas teclado vs mando) es la comprobación estilo release de este corte de input.

10. Lección generalizada

Los modos de captura son excluyentes con overlays clicables. Posee la transición: sal del lock, dile al jugador cómo, y no ates ESC a dos verbos. La UI por dispositivo (ocultar el aviso en mando) es corrección, no pulido.

Extracto simplificado

Simplificado / pseudocódigo para enseñar. No es un volcado de archivos de producción.

El predicado del aviso, simplificado.

// Simplified teaching excerpt — not CONTRABAND production source.
function shouldShowReleaseMouseHint({ pointerLocked, clickableChoiceVisible, dominantDevice }) {
  return pointerLocked && clickableChoiceVisible && dominantDevice !== 'gamepad';
}
// While hail open: ESC must not recapture.
// After ESC: browser already dropped lock — ask for a click, not another ESC.

Evidencia pública

  • Log de desarrollo de CONTRABAND, 19 ago 2026, v0.4.148–v0.4.153 (aviso ESC / recaptura).
  • lastRunShouldShowReleaseMouseHint; pointer-lock-policy.js historia vs combate live.
  • last-run-from-verge.test.mjs

Módulos relacionados del curso insignia

Notas relacionadas