1. ¿Qué es el Reverse Player?

El Reverse Player es una consola portátil virtual que ejecuta programas escritos en QBJr. Está pensada para mobile-first: su diseño simula la forma y los controles de una handheld retro con estética neon oscura. Tiene pantalla central, D-pad a la izquierda, botones de acción a la derecha, bumpers L/R en la parte superior, y botones de sistema (SELECT/START) debajo de la pantalla.

REVERSE PLAYER
TOPBAR
256 × 240
D-PAD · A · B · X · Y · L · R
SELECT   START
Pantalla virtual
Resolución configurable. Default: 256×240. Pixel-perfect scaling automático.
Controles táctiles
D-pad + 4 botones de acción + 2 bumpers. Escala ajustable con slider.
Teclado físico
Simultáneo con los botones táctiles. Mapeo configurable.
Browser-first
Sin instalación. Chrome, Firefox, Safari, Edge modernos. Modo vertical recomendado en mobile.
📌 NOTAEl Player no es un IDE. Es el motor de ejecución. Para escribir y probar código, usar el QBJr. IDE.

2. Carga de programas

MÉTODODESCRIPCIÓN
Botón LOADAbre el selector de archivo del sistema operativo. Acepta .qbjr (programa), .txt (programa en texto plano), .zip (proyecto completo con assets).
Drag & dropArrastrá el archivo sobre la pantalla. Mismos tipos que LOAD.
ZIPCarpeta con main.qbjr + assets. El Player extrae en memoria y carga main.qbjr como entrada.

Estructura de un proyecto ZIP

mi_juego.zip
├── main.qbjr ← punto de entrada obligatorio
├── datos/
│ ├── mapa.qdat
│ └── sala_1.qdat
└── recursos/
├── sprites.png
└── musica.mp3
📌El archivo de entrada debe llamarse main.qbjr. Los paths en el código son relativos a la raíz del ZIP. Ejemplo: CARGAR DATOS "datos/mapa.qdat" COMO mapa.

3. Controles

El Player acepta botones táctiles en pantalla y teclado físico simultáneamente. Un programa puede detectar input de cualquiera de las dos fuentes sin distinción.

D-pad — Movimiento

BOTÓN TÁCTILTECLADO (predeterminado)
↑ ArribaArrowUp / W
↓ AbajoArrowDown / S
← IzquierdaArrowLeft / A
→ DerechaArrowRight / D

Botones de acción

BOTÓNTECLADOFUNCIÓN SUGERIDA
A (verde)Enter / ZAceptar, interactuar, confirmar.
B (rojo)Espacio / XAcción secundaria: saltar, esquivar.
X (azul)Ctrl izq. / CTerciaria: agacharse, cubrirse.
Y (amarillo)Tab / IMenú, inventario, estadísticas.
📌Los roles de los botones son sugeridos, no obligatorios. Cada programa define su propia semántica. TECLADO("Z") y TECLADO(FLECHA_ARRIBA) detectan la misma fuente que el botón A y el D-pad.

Bumpers y sistema

BOTÓNTECLADOFUNCIÓN
L (izquierdo)Shift izq. / QAcción lateral izquierda.
R (derecho)Alt izq. / EAcción lateral derecha.
SELECTEscapeCancela acciones, abre menús en el programa.
START(sin tecla física)Pausa o reanuda el programa. Ver §4.

4. PAUSAR vs START

Hay dos tipos de pausa que funcionan de forma independiente:

TIPODESCRIPCIÓN
PAUSAR (código QBJr.)El programa suspende su ejecución hasta que se llame REANUDAR o hasta que el usuario presione START. Iniciada por el código del juego.
START (botón del sistema)Pausa o reanuda el engine directamente, sin pasar por el código QBJr. Funciona aunque el programa no use PAUSAR.
⚠ IMPORTANTESTART no tiene tecla física equivalente por diseño. Es la única forma garantizada de salir de un PAUSAR programático desde el teclado. El botón táctil START en pantalla siempre funciona.

5. Configuración

El botón en la topbar abre el panel de configuración. Los cambios se guardan automáticamente en localStorage.

Mapeo de teclas

ACCIÓNDESCRIPCIÓN
Tocar botón → presionar teclaToca un botón táctil en el panel, luego presiona la tecla o botón de mouse deseado.
Hasta 2 teclas por acciónCada botón acepta dos teclas simultáneas. Ejemplo: A acepta Enter Y Z.
Botones de mouseMouseLeft, MouseMiddle, MouseRight son válidos.
ResetVuelve al mapeo predeterminado de la §3.

Escala de controles

Un slider de 7 pasos ajusta el tamaño de los controles táctiles (D-pad y botones), no el de la pantalla. La pantalla siempre ocupa el máximo espacio disponible.

FACTORUSO SUGERIDO
0.50× · 0.75×Más espacio de pantalla en mobile. Controles pequeños.
1.00×Tamaño predeterminado.
1.25× · 1.50×Recomendado para pantallas grandes o tablets.
1.75× · 2.00×Controles grandes, para accesibilidad.
📌El Player calcula automáticamente el tamaño máximo posible para los controles. El slider muestra el valor pedido pero aplica el valor real si el pedido excede el espacio disponible.

6. Overlays de estado

El Player muestra pantallas superpuestas en respuesta a eventos del ciclo de vida del programa:

🟢 Boot sequence

Al cargar el Player por primera vez. Animación de arranque con 4 fases y barra de progreso (~2 segundos). Luego pantalla idle con efecto CRT.

🟡 Carga (LOAD)

Al cargar un archivo. Muestra 4 fases simuladas: Leyendo → Parseando → Inicializando → Listo. Si hay errores de parseo, transiciona a ERROR.

🔵 FIN

Al terminar con FINALIZAR. Presionar Enter o Z para volver a idle. START reinicia el programa desde cero.

🔴 ERROR

Errores de parseo o runtime. Lista cada error con línea, columna y descripción. La consola LOG tiene el contexto completo.

🟣 SETTINGS

Panel de configuración (§5). No interrumpe la ejecución — el game loop sigue corriendo mientras está abierto.

⬜ LOG

Consola del intérprete (§7). Historial de todos los mensajes del engine y del programa.

7. Consola del entorno (LOG)

El botón LOG en la topbar abre la consola. Muestra todos los mensajes del intérprete, el runtime, errores del browser, y el output del comando IMPRIMIR.

INFOMensajes informativos generales del engine.
ENGINEEventos del motor: inicio, módulos cargados, finalización.
LOADCarga de archivos: .qbjr, .qdat, ZIP, imágenes, audio.
WARNAdvertencias: recursos faltantes, valores fuera de rango.
ERRORErrores de parseo o runtime. Incluyen línea y descripción.
PRINTOutput de la instrucción IMPRIMIR del programa QBJr.

Usar IMPRIMIR para depurar

La instrucción IMPRIMIR escribe en la consola sin afectar el canvas. Es la herramienta principal de debugging en QBJr.

IMPRIMIR "Posición jugador:" x y
IMPRIMIR "Sala actual:" salaActual
IMPRIMIR "VelY:" VEL_Y(jugador 1)
IMPRIMIR 2 + 3  ' imprime 5
💡 CONSEJOLa consola captura window.onerror, console.warn, console.error y promesas rechazadas. Todo error del browser aparece aquí — es el primer lugar a mirar cuando algo falla silenciosamente.

8. Statusbar

La barra debajo de la pantalla muestra información en tiempo real, actualizada cada segundo:

CAMPODESCRIPCIÓN
ResoluciónAncho × Alto en píxeles de la pantalla virtual. Definido por PANTALLA en el programa.
FPSFotogramas por segundo actuales. Target: 60fps.
Versión intérpreteVersión del motor QBJr. cargado. Ejemplo: v0.9.31.
EstadoRUNNING · PAUSED · STOPPED · IDLE.
📌La resolución se lee 200ms después de que empieza la ejecución para dar tiempo al intérprete a procesar la instrucción PANTALLA.

9. Especificaciones técnicas

PARÁMETROVALOR
Resolución predeterminada256 × 240 px (NES). Configurable con PANTALLA.
Resoluciones históricas256×192 (MSX) · 256×224 (NES/SNES) · 256×240 (NES) · 320×200 (DOS VGA) · 320×240 (GBA) · 640×480 (VGA).
EscaladoPixel-perfect sin interpolación. La pantalla ocupa el máximo espacio disponible manteniendo aspect ratio.
Game looprequestAnimationFrame. Target 60fps. Delta time clampado a 50ms para física.
Fuente canvas (TEXTO)Press Start 2P — fuente pixel genuina. Cargada antes del boot.
Fuente HUD topbarOrbitron.
Fuente statusbarShare Tech Mono.
Fuente idle / bootVT323 (efecto CRT).
Paleta neon UI#0c0c1a · #00e5ff · #ff1a4b · #ffaa00 · #00ff88.
PersistenciaMapeo de teclas y escala guardados en localStorage.
CompatibilidadChrome, Firefox, Safari, Edge modernos (2023+). Sin instalación.

10. Resolución de problemas

PROBLEMASOLUCIÓN
La pantalla queda negra al cargarAbrí la consola LOG. Si hay errores de parseo, el programa no llegó a ejecutarse. Verificá el código en el IDE.
Los controles táctiles no respondenEn algunos browsers mobile los eventos touch requieren foco. Tocar la pantalla una vez antes de jugar.
El programa corre muy lentoDemos de alta carga (Mandelbrot) son lentas por diseño. ESPERAR 0 al final de cada fila cede el control y evita que el browser se congele.
No escucho sonidoEl browser requiere una interacción del usuario antes de reproducir audio. Presionar cualquier botón antes de que el programa intente reproducir.
CARGAR DATOS falla con error de redLos archivos .qdat se cargan con fetch(). Si el Player corre desde file://, el browser bloquea las requests. Usar un servidor local o ZIP de proyecto.
El texto con TEXTO_MD aparece cortadoVerificar que el quinto argumento (alturaMax) sea suficientemente grande, o eliminarlo si no se quiere límite.
PAUSAR no responde al START táctilVerificar que el overlay de pausa sea visible. Si el programa está en un loop infinito sin yield, el Player no puede actualizarse.