1. Origen del lenguaje
Quick Basic Junior nació como parte de Reverse FAP (Frame Animation Program), un editor de animaciones cuadro a cuadro. Al incorporar soporte para prototipos de videojuegos, surgió la necesidad de un lenguaje propio para definir gráficos e interacciones sin depender de archivos de imagen externos. Ese pseudo-lenguaje creció y se formalizó hasta convertirse en QBJr.
El nombre rinde homenaje a QBasic, el entorno de MS-DOS que introdujo a una generación entera a la programación. El sufijo Junior indica su naturaleza simplificada y su vocación educativa.
📌 PROYECTO REVERSEQBJr. es parte de la suite Reverse: un ecosistema de herramientas de código abierto para la creación de videojuegos retro (8/16 bits), orientado a la experimentación, el aprendizaje y la expresión creativa en español.
2. Filosofía de diseño
Los siguientes principios guían cada decisión del lenguaje. Los primeros seis son del diseño original (v1.0). Los demás surgieron de la implementación real.
Simplicidad ante todo
Cada decisión prioriza la facilidad de aprendizaje sobre la potencia expresiva.
Vocabulario en español
Todas las palabras clave están en español, reduciendo la barrera del idioma para hispanoparlantes.
Una palabra, una función
Ninguna palabra clave comparte nombre con otra. Cada término es único e inequívoco.
Verbos y objetos
Las instrucciones son verbos de acción que operan sobre objetos. Los objetos se crean con CREAR.
Sin repetición de código
El sistema de subprogramas introduce abstracción sin la complejidad de funciones con parámetros.
Valores predeterminados sensatos
Un programa mínimo puede ignorar toda configuración y funcionar correctamente.
Capas de complejidad opcionales
El audio, el color y las capas pueden usarse de forma simple o explorados en profundidad. Nadie está obligado a conocer todo para empezar.
Operadores como palabras completas
AND OR XOR NOT MOD DIV — sin colisión con identificadores de una o dos letras. Solo son keywords en MAYÚSCULAS.
Archivos como datos declarativos
El formato .qdat permite definir mundos e ítems sin saber programar, abriendo el lenguaje a colaboradores no programadores.
3. Historial de versiones
| VERSIÓN | PERÍODO | CAMBIOS PRINCIPALES |
| v1.0 | 2025 | Especificación inicial. Dibujo, variables globales, SI/MIENTRAS/REPETIR/PARA, subprogramas sin parámetros, paleta Retro y Moderna. Operadores lógicos: Y O OX NO. |
| v1.1 | 2025 | Reorganización estructural. Arreglos. SEGUN/CASO. Paleta predeterminada cambia de Moderna a Retro. Configuración global unificada. |
| v2.0 | 2025 | Cambio incompatible: Y/O/OX/NO → AND/OR/XOR/NOT. Identificadores de una letra habilitados. COLISIONA como operador infijo. FPS global. Precedencia documentada formalmente. |
| v2.1 | 2025 | Motor de tiles (CREAR TILESET/TILEMAP, PONER TILE, COLISIONA_TILE). Física (FISICA GRAVEDAD, VELOCIDAD, IMPULSO, EN_SUELO). Archivos y datos (ABRIR/LEER/ESCRIBIR, CARGAR DATOS, formato .qdat). |
| v2.2 | 2025 | Markdown extendido en canvas (TEXTO_MD, ALTURA_MD). IMPRIMIR para debugging. PAUSAR/REANUDAR. Consola del entorno con niveles de log. |
| v2.2+ | 2026 | 10 funciones de cadena avanzadas (BUSCAR, EXTRAER, CORTAR_IZQ, etc.). TEXTO_MD con 5° argumento alturaMax. Incorporadas en implementación de referencia v0.9.8. |
◈ NOTA HISTÓRICA — v2.0El cambio de Y/O/OX/NO a AND/OR/XOR/NOT fue el más significativo del lenguaje. Las letras Y y O colisionaban con variables de uso común (coordenada y, variable o). La solución: palabras completas en inglés que no colisionan con ningún identificador en español.
4. Estructura de un programa
Modelo de ejecución
Un programa en QBJr. se ejecuta de arriba hacia abajo, instrucción por instrucción. El game loop se implementa de forma explícita usando las estructuras de repetición del lenguaje — decisión pedagógica deliberada para que el alumno vea que un juego es literalmente un bucle.
' Estructura típica de un programa QBJr.
PANTALLA 256 240
PALETA retro
COLOR FONDO black
DECLARAR x COMO ENTERO
x = 128
REPETIR
LIMPIAR
SI TECLADO(FLECHA_DERECHA) ENTONCES x = x + 3 FIN SI
CIRCULO x 120 12 RELLENO
ESPERAR 16
HASTA TECLADO(TECLA_ESCAPE)
FINALIZAR
Configuración global
| INSTRUCCIÓN | DESCRIPCIÓN | DEFAULT |
| PANTALLA <w> <h> [COLORES <n>] | Resolución del área de dibujo virtual. | 256×240, 16 colores |
| PALETA retro | moderna | Paleta de 16 colores activa. | retro |
| AUDIO MODO 4 | 8 | Canales de audio para síntesis. | 4 |
| TEMPO <BPM> | Velocidad musical. negra = 60000÷BPM ms. | 120 |
| FPS <n> | Velocidad de animación de sprites. | 60 |
Comentarios y coordenadas
La comilla simple ' inicia un comentario hasta el final de la línea. El sistema de coordenadas tiene el origen (0,0) en la esquina superior izquierda. X crece hacia la derecha, Y crece hacia abajo.
5. Variables y tipos
Todas las variables son globales. No existe scope local. Los nombres son case-insensitive: xJugador y xjugador son la misma variable. Las variables deben declararse antes de usarse.
| TIPO | DESCRIPCIÓN | EJEMPLO |
| ENTERO | Número sin parte decimal. | 42, -7, 0 |
| FLOTANTE | Número con parte decimal. | 3.14, -0.5 |
| TEXTO | Cadena de caracteres entre comillas dobles. | "hola mundo" |
| BOOLEANO | Solo VERDADERO o FALSO. | VERDADERO |
Arreglos
Arreglos unidimensionales de tamaño fijo. El índice es base 1 (el primer elemento es [1]).
DECLARAR inventario[6] COMO TEXTO
inventario[1] = "llave"
inventario[2] = "linterna"
' Recorrer con PARA
PARA i DE 1 A 6
IMPRIMIR inventario[i]
FIN PARA
6. Operadores
| OPERADOR | DESCRIPCIÓN |
| + - * / | Aritméticos. + también concatena TEXTO. |
| ^ | Potencia. 2 ^ 8 = 256 |
| \ | Raíz. 2 \ 9 = 3 (raíz cuadrada de 9). |
| MOD | Resto. 10 MOD 3 = 1 |
| DIV | División entera. 10 DIV 3 = 3 |
| = <> < > <= >= | Comparación. Devuelven VERDADERO/FALSO. |
| AND | Conjunción lógica. Solo en MAYÚSCULAS. |
| OR | Disyunción lógica. Solo en MAYÚSCULAS. |
| XOR | Disyunción exclusiva. Solo en MAYÚSCULAS. |
| NOT | Negación lógica. Solo en MAYÚSCULAS. |
Precedencia (de menor a mayor): OR · XOR → AND → NOT → = <> < > <= >= COLISIONA → + - → * / MOD DIV → ^ \ → - (unario).
⚠ MAYÚSCULASand or not xor en minúsculas son identificadores válidos para variables, no operadores. Un programa puede tener una variable llamada and.
7. Control de flujo
Condicional SI
SI vida <= 0 ENTONCES
HACER game_over
OTRO SI vida < 25 ENTONCES
HACER advertencia
SI NO
HACER estado_normal
FIN SI
Selección SEGUN
SEGUN direccion
CASO "norte": HACER ir_norte
CASO "sur": HACER ir_sur
CASO OTRO: HACER detenerse
FIN SEGUN
Ciclos
| FORMA | CUÁNDO SE EVALÚA | MÍNIMO DE EJECUCIONES |
| MIENTRAS cond … FIN MIENTRAS | Al inicio | 0 (puede no ejecutar) |
| REPETIR HASTA cond … FIN REPETIR | Al inicio | 0 |
| REPETIR … HASTA cond | Al final | 1 (siempre ejecuta) |
| REPETIR … MIENTRAS cond | Al final | 1 |
| PARA i DE a A b [ENPASOSDE n] | Al inicio | 0 si a > b |
Control adicional
| INSTRUCCIÓN | DESCRIPCIÓN |
| ESCAPAR | Interrumpe el ciclo actual. |
| ESPERAR <ms> | Pausa en milisegundos. Cede al game loop. |
| PAUSAR | Suspende hasta REANUDAR o START del Player. |
| REANUDAR | Reanuda si estaba suspendido. |
| FINALIZAR | Termina el programa. |
| IMPRIMIR <expr…> | Escribe en consola del Player sin afectar el canvas. Para debugging. |
8. Subprogramas
Los subprogramas no reciben parámetros ni devuelven valores. Operan sobre las variables globales del programa. Se definen con DEFINIR y se invocan con HACER.
DECLARAR sx COMO ENTERO
DECLARAR sy COMO ENTERO
DEFINIR dibujar_estrella
POLIGONO sx sy 30 5 RELLENO
FIN DEFINIR
sx = 64 sy = 80 HACER dibujar_estrella
sx = 192 sy = 80 HACER dibujar_estrella
9. Paletas de colores
QBJr. incluye dos paletas de 16 colores. La paleta predeterminada es retro. Los colores se referencian siempre por nombre, nunca por número.
Paleta RETRO (predeterminada)
black
white
red
lime
blue
yellow
cyan
magenta
silver
gray
maroon
olive
green
purple
teal
navy
Paleta MODERNA
negro
blanco
rojo
verde
azul
amarillo
cian
magenta
gris
naranja
violeta
marrón
rosa
lima
celeste
dorado
HSL(h, s, l) genera colores dinámicos donde h=0-360 (matiz), s=0-100 (saturación), l=0-100 (luminosidad). Se usa donde se espera un nombre de color.
10. Geometría y dibujo
| INSTRUCCIÓN | DESCRIPCIÓN |
| TRAZO <px> | Grosor del trazo en píxeles. Default: 1. |
| COLOR <c> | Trazo y relleno al mismo color. |
| COLOR TRAZO <c> RELLENO <c> | Trazo y relleno distintos en una instrucción. |
| COLOR FONDO <c> | Color de fondo para LIMPIAR. |
| LIMPIAR | Rellena la pantalla con COLOR FONDO. |
| PUNTO <x> <y> | Punto de 1×1 px. |
| LINEA <x1> <y1> … [CERRAR] [RELLENO] | Líneas contiguas. CERRAR cierra el path. |
| CIRCULO <x> <y> <r> [RELLENO] | Círculo con centro y radio. |
| RECTANGULO <x> <y> <ancho> <alto> [RELLENO] | Orden: ancho antes que alto. |
| POLIGONO <x> <y> <r> <lados> [RELLENO] | Polígono regular inscrito. |
| TRIANGULO <variantes> [RELLENO] | Por vértices, EQUILATERO, ISOSCELES o ESCALENO. |
| RELLENAR <x> <y> | Flood fill desde el punto. |
11. Texto en canvas
| INSTRUCCIÓN | DESCRIPCIÓN |
| TEXTO <x> <y> <expr> [SOMBREADO] | Dibuja texto con fuente Press Start 2P. SOMBREADO pinta el fondo. |
| TEXTO_MD <x> <y> <ancho> <expr> [<alto>] | Texto con markdown extendido y word-wrap. El 5° arg limita la altura. |
| ALTURA_MD(<ancho>, <expr>) | Calcula la altura que ocuparía el texto sin dibujarlo. |
12. Markdown extendido
Sintaxis disponible dentro de TEXTO_MD:
| MARCADO | EFECTO |
| # texto # | Blanco brillante (título inline). |
| *texto* | Rojo (alerta/peligro). |
| _texto_ | Verde (objetos/ítems). |
| **texto** | Negrita. |
| //texto// | Cursiva. |
| __texto__ | Subrayado. |
| ~~texto~~ | Tachado. |
| ^texto^ | Superíndice. |
| ~texto~ | Subíndice. |
| [c=color]texto[/c] | Color por nombre de paleta o valor hex. |
| # Título / ## h2 / ### h3 | Encabezados estructurales. |
| --- / ---===--- | Línea divisoria / decorada. |
13. Sprites y animaciones
Un sprite define el tipo de entidad. Una instancia es la copia activa en pantalla con posición, rotación y estado propios. Múltiples instancias del mismo sprite son independientes.
| INSTRUCCIÓN | DESCRIPCIÓN |
| CREAR SPRITE <nombre> [<imagen>] | Define tipo de sprite. Sin imagen: acepta animaciones. |
| MOSTRAR <sprite> <inst> [EN <x> <y>] | Muestra o crea una instancia. |
| OCULTAR <sprite> [<inst>] | Oculta una o todas las instancias. |
| BORRAR <sprite> | Destruye sprite e instancias. |
| MOVER [HITBOX] <sprite> <inst> A <x> <y> | Mueve la instancia o solo su hitbox. |
| ROTAR / ESCALAR [HITBOX] … | Rota o escala instancia o hitbox. |
| VOLTEAR <sprite> <inst> HORIZONTAL | VERTICAL | Espeja la instancia. |
| CREAR ANIMACION <nom> DE <sprite> CON <imgs…> | Define animación con fotogramas. |
| REPRODUCIR <anim> DE <sprite> <inst> [BUCLE] [POR <n>] | Reproduce la animación. |
14. Audio
Archivos externos
| INSTRUCCIÓN | DESCRIPCIÓN |
| CREAR SONIDO / MUSICA <nombre> <archivo> | Define SFX o BGM desde archivo externo. |
| REPRODUCIR <n> [BUCLE] [VOLUMEN <v>] [PANEO <p>] | Reproduce. Volumen 0-100, paneo -50 a 50. |
| DETENER <n> [FADE <ms>] | Detiene con fundido opcional. |
Síntesis por pistas
CREAR PISTA intro
DINAMICA mf
NOTA Do4:ne Re4:ne Mi4:ne Fa4:bl
SILENCIO co
FIN PISTA
REPRODUCIR intro BUCLE
Figuras: cu (cuadrada) · re (redonda) · bl (blanca) · ne (negra) · co (corchea) · sc (semicorchea) · punto = ×1.5. Dinámicas: pp p mp mf f ff.
15. Capas y scroll
| CAPA | COMPORTAMIENTO |
| 0, 1, 2 | Fondos con parallax. Factor configurable por capa. |
| 3 | Capa principal. Responde a SCROLL. |
| 4 | Capa frontal. Se mueve con la capa 3. |
| 5 | HUD. Siempre al frente, independiente del scroll. |
| INSTRUCCIÓN | DESCRIPCIÓN |
| FONDO <capa> <imagen> <factor> | Carga imagen en la capa con factor de scroll. |
| SCROLL <dirección | ruta> <velocidad> | Mueve la capa principal. |
| RUTA <nombre> DESDE <x> <y> EN <figura> | Define ruta de scroll geométrica compleja. |
16. Motor de tiles
| INSTRUCCIÓN | DESCRIPCIÓN |
| CREAR TILESET <n> <archivo> <tw> <th> | Divide imagen en celdas tw×th. IDs base 1. |
| CREAR TILEMAP <n> <cols> <filas> [EN CAPA <c>] | Grilla en la capa indicada. Default: capa 3. |
| PONER TILE <tilemap> <col> <fila> <id> [RIGIDO] | Coloca tile. RIGIDO activa hitbox automática. |
| BORRAR TILE <tilemap> <col> <fila> | Elimina el tile. |
| MOSTRAR / OCULTAR / BORRAR TILEMAP <n> | Control de visibilidad y destrucción. |
| COLISIONA_TILE(<sprite> <inst>) | VERDADERO si la hitbox colisiona con tile RIGIDO. |
17. Física
| INSTRUCCIÓN | DESCRIPCIÓN |
| FISICA GRAVEDAD <v> | Aceleración en px/s². Default: 500. |
| FISICA SPRITE <sprite> <inst> ACTIVA | INACTIVA | Activa o desactiva física sobre la instancia. |
| VELOCIDAD <sprite> <inst> A <vx> <vy> | Velocidad en px/s. Negativos: usar paréntesis. |
| IMPULSO <sprite> <inst> A <fx> <fy> | Impulso instantáneo. Útil para saltos. |
| EN_SUELO(<sprite> <inst>) | VERDADERO si está sobre tile rígido. |
| VEL_X(<sprite> <inst>) | Velocidad horizontal actual en px/s. |
| VEL_Y(<sprite> <inst>) | Velocidad vertical actual en px/s. |
📌 NEGATIVOSVELOCIDAD p 1 A 100 (-200) — los valores negativos directos requieren paréntesis para evitar ambigüedad con el operador de resta.
18. Archivos y datos
| INSTRUCCIÓN | DESCRIPCIÓN |
| ABRIR <ruta> COMO <n> LECTURA | ESCRITURA | ANEXAR | LECTURA: fetch del servidor. ESCRITURA: localStorage. |
| LEER <archivo> <variable> | Lee la siguiente línea. |
| ESCRIBIR <archivo> <texto> | Escribe una línea. |
| CERRAR <archivo> | Cierra y persiste. |
| FIN_ARCHIVO(<archivo>) | VERDADERO si no hay más líneas. |
| CARGAR DATOS <ruta> COMO <n> | Carga y parsea un archivo .qdat. |
| LEER_DATO(<datos> <sección> <clave>) | Retorna el valor de la clave en la sección. |
📌 FORMATO .qdatSecciones con [nombre], pares clave = valor, comentarios con #, valores multilínea con triple comilla """…""".
20. Colisiones
| FORMA | DESCRIPCIÓN |
| <spriteA> COLISIONA <spriteB> | Operador infijo. VERDADERO si las hitboxes se solapan (AABB). |
| COLISIONA(<sprite>) | VERDADERO si el sprite colisiona con cualquier otro. |
| COLISIONA_TILE(<sprite> <inst>) | VERDADERO si colisiona con tile RIGIDO activo. |
21. Funciones matemáticas
| FUNCIÓN | DESCRIPCIÓN |
| ABS(<n>) | Valor absoluto. |
| RAIZ(<n>) | Raíz cuadrada. |
| POTENCIA(<b>,<e>) | Potencia. |
| SEN / COS / TAN (<grados>) | Trigonométricas en grados (no radianes). |
| LOG / LOG10 / LOG2 (<n>) | Logaritmos natural, base 10, base 2. |
| RND() | Número aleatorio entre 0 y 1. |
| TRUNCAR(<n>) | Elimina decimales sin redondear. |
| REDONDEAR(<n>) | Redondea al entero más cercano. |
22. Funciones de cadena
| FUNCIÓN | DESCRIPCIÓN |
| TEXTO(<n>) / NUMERO(<txt>) | Conversión entre número y texto. |
| LARGO(<txt>) | Cantidad de caracteres. |
| RECORTAR(<txt>) | Elimina espacios al inicio y final. |
| MAYUSCULA / MINUSCULA (<txt>) | Conversión de case. |
| BUSCAR(<txt>,<aguja>[,<desde>]) | Posición base-1 de la primera ocurrencia. |
| EXTRAER(<txt>,<desde>[,<largo>]) | Subcadena base-1. |
| CORTAR_IZQ / CORTAR_DER (<txt>,<n>) | Primeros / últimos n caracteres. |
| REEMPLAZAR(<txt>,<viejo>,<nuevo>) | Reemplaza todas las ocurrencias. |
| REPETIR(<txt>,<n>) | Repite el texto n veces. |
| CARACTER(<n>) | Carácter por código Unicode (CHR$). |
| CODIGO(<txt>) | Código Unicode del primer carácter (ASC). |