Saltar al contenido principal

Módulo Display

Display abre la ventana de Windows o la pantalla de la placa y presenta en ella lo que pintas. También lleva el ritmo del juego (fps y dt), el fondo de cada fotograma y el view, la parte de la pantalla donde se pinta. Para pintar, usa el módulo Draw, que tienes en Display.draw.

Captura del módulo Display de JARU para abrir pantallas, configurar orientación y actualizar gráficos

use Display

Plataformas​

WindowsESP32 / ESP32-S3ESP32-P4ESP32-S31
Tamaño de la pantallaEl de open(ancho, alto)El del panel de la placa: open no usa sus argumentosEl del panel; open(ancho, alto) pone un view de ese tamaño en el centroComo en el P4
Colores con doble buffer (mode(2))24 bits por píxel8 bits por píxel: 256 colores16 bits por píxel16 bits por píxel
orientationSolo cuenta antes de open: 0 y 2 cambian el ancho por el altoGira el panel, después de openGira el panel y vuelve a centrar el viewComo en el P4
backlightNo hace nadaEnciende o apaga la luzEnciende o apaga la luzEnciende o apaga la luz
Tamaño de la ventanaDe x1 a x4, con Window Scale———
update()Atiende también la ventana: cerrarla acaba el programa—Presenta al ritmo de refresco del panelPresenta al ritmo de refresco del panel

El tamaño de cada panel, el view en el P4 y el S31 y cómo se ven los colores en cada placa están en Pantalla, sonido, SD y red y en Memoria y límites. Window Scale está en la configuración de Windows del proyecto.

Funciones​

FunciónQué haceDevuelve
open(ancho, alto)Abre la ventana o la pantallatrue
close()Cierra la pantalla y suelta lo cargadotrue
update()Presenta el fotograma y prepara el siguiente; con fps, esperatrue, o los pasos que tocan
mode() / mode(n)Lee o cambia el modo de dibujoEl modo / true
orientation(n)Gira la pantallatrue
backlight(encendida)Enciende o apaga la luz de la pantallatrue
loadBG(fichero)Carga la imagen de fondo de cada fotogramatrue
loadTFT(fichero) / loadTFT(x, y, fichero)Pinta una imagen fija fuera del doble buffer, como un marcotrue

Con un argumento de otro tipo, las funciones de Display no lanzan una excepción: devuelven un valor de error y no hacen nada (ver Errores y excepciones). Las pocas que sí lanzan lo dicen en su apartado.

open​

Abre la ventana (Windows) o la pantalla de la placa.

use Display

Display.open(320, 240)
println(Display.width, " x ", Display.height) // 320 x 240 en Windows
  • ancho y alto son enteros. Con decimales no abre: devuelve un valor de error.
  • En Windows, la ventana mide ancho × alto, o alto × ancho si antes has puesto orientation(0) o orientation(2). Con Window Scale en x2, x3 o x4, la ventana se ve más grande, pero el programa sigue viendo ancho × alto.
  • En el ESP32 y el S3, el tamaño es el del panel, que dice el perfil de la placa: los argumentos son obligatorios, pero no se usan.
  • En el P4 y el S31, el tamaño también es el del panel, y ancho × alto es el view, centrado en él (si no has puesto antes viewWidth y viewHeight).

Después de open, Display.width y Display.height dicen el tamaño de la pantalla, y viewWidth y viewHeight, el del view.

close​

Cierra la ventana o suelta la pantalla. Libera el doble buffer, la imagen de fondo y el marco de loadTFT, y vuelve a dejar showBG en false, autoClear en true y el view a 0.

Display.close()

Después puedes volver a abrirla con open. Si el programa sigue haciendo otras cosas, ciérrala para liberar esa memoria.

update​

Presenta lo que has pintado desde el update() anterior.

use Display

Display.open(320, 240)
Display.fps = 30 // el ritmo: 30 fotogramas por segundo
var draw = Display.draw

for (var i = 0; i < 90; i++) // 3 segundos
draw.circle(160, 120, 10 + i)
Display.update() // presenta, borra el view y espera
end
Display.close()
  • En el modo de doble buffer (el de serie), update() presenta el fotograma y prepara el siguiente: lo borra con el color de fondo (si autoClear está activo) y pinta la imagen de fondo (si showBG lo está). Cada fotograma empieza limpio: no hace falta llamar a draw.cls().
  • En el modo directo (mode(1)), lo pintado ya está en la pantalla, y update() no borra nada.
  • Con un ritmo (Display.fps = N), update() espera hasta que toca el siguiente paso y devuelve cuántos pasos tocan: 1 si el fotograma ha cabido en su tiempo, 2 o más si ha llegado tarde (ver fps). Sin ritmo, devuelve true.
  • Mide el tiempo entre un update() y el siguiente: es Display.dt, y también el reloj con el que avanzan las animaciones de los sprites y la física de las escenas.
  • En Windows, update() atiende además la ventana: si la cierras, el programa termina ahí. Un programa que no llama a update() no se puede cerrar con la ventana.

Con argumentos no hace nada y devuelve un valor de error.

mode​

Lee o cambia el modo de dibujo.

var modo = Display.mode()    // 2, el de serie
Display.mode(1) // pintar directo en la pantalla
ModoQué hace
0No lo uses: cambia según la plataforma (en Windows, hace lo mismo que el 2).
1Directo. Cada función de Draw pinta en la pantalla al momento. update() no borra nada ni pinta el fondo. Lo que se mueve parpadea.
2Doble buffer (de serie). Pintas en un fotograma que no se ve, y update() lo presenta de una vez. Después prepara el siguiente con autoClear y showBG.

El doble buffer es lo que conviene para un juego. En el ESP32 y el S3 ocupa memoria (un byte por píxel del view) y tiene menos colores; el modo directo no gasta esa memoria. Un valor fuera de 0–2 no cambia el modo: devuelve un valor de error.

orientation​

Gira la pantalla.

Display.orientation(1)    // apaisada
ValorGiroEn Windows
00 gradosVertical: la ventana mide alto × ancho
190 gradosApaisada (la de serie)
2180 gradosVertical
3270 gradosApaisada
  • Solo cuentan los dos bits de abajo: 4 es 0, 5 es 1…
  • En Windows, solo cuenta antes de open, para elegir entre una ventana vertical o apaisada. No gira lo que pintas.
  • En placa, gira el panel, y Display.width y Display.height cambian con él. Llámala después de open: antes no hace nada, y la pantalla arranca con el giro que dice el perfil de la placa. En el P4 y el S31, además, vuelve a centrar el view.

backlight​

Enciende o apaga la luz de la pantalla.

Display.backlight(false)  // apaga la luz
Display.backlight(true) // la enciende

Acepta true, false o un número: 0 apaga, y cualquier otro número enciende. En placa no regula el brillo: la luz va al máximo o apagada. En Windows no hace nada. Depende de que el perfil de la placa diga qué pin controla la luz.

loadBG​

Carga una imagen BMP como fondo. Con showBG en true, update() la pinta al empezar cada fotograma, en la posición posBG del view.

Display.loadBG("Images/fondo.bmp")
Display.showBG = true // sin esto, el fondo no se pinta
Display.posBG = [0, 0]
  • La ruta es la del proyecto, como en Bitmap.load: la imagen tiene que llegar al juego (Include in Build en el editor de imágenes). Lee los mismos formatos que Bitmap.
  • Solo se pinta en el modo de doble buffer.
  • Si no encuentra la imagen, devuelve false, escribe el error en la consola (en la placa, en el monitor serie) y deja como estaba el fondo de antes.

loadTFT​

Pinta una imagen BMP directamente en la pantalla, fuera del doble buffer. Sirve para un marco o un decorado fijo alrededor del view: como update() solo vuelve a pintar el view, lo de fuera se queda.

// Un marco en (0, 0)
Display.loadTFT("Images/marco.bmp")

// Una imagen en una posición
Display.loadTFT(50, 100, "Images/logo.bmp")
  • x e y son enteros: la esquina de arriba a la izquierda, en coordenadas de la pantalla (no del view). Sin ellos, la imagen va en (0, 0).
  • Con argumentos que no valen, lanza ERR_TYPE_MISMATCH o ERR_INVALID_ARG_NUMBER. Si no puede cargar la imagen, en placa lanza ERR_FILE_READ_FAIL, y en Windows devuelve un valor de error.
En Windows, la imagen ocupa toda la ventana

En Windows, loadTFT no usa x ni y: estira la imagen a toda la ventana. Para que se vea igual que en la placa, haz el marco del tamaño de la pantalla.

Propiedades​

PropiedadTipoDe serieLectura / escritura
width, heightentero320 y 240 hasta open; después, el tamaño de la pantallaSolo lectura
viewWidth, viewHeightentero0 hasta open; después, el tamaño del viewLas dos (asígnalas antes de open)
fpsentero, de 0 a 10000: sin ritmoLas dos
dtdecimal, en segundos0Solo lectura
showBGsí/nofalseLas dos
autoClearsí/notrueLas dos
posBGlista [x, y][0, 0]Solo escritura
drawel módulo Draw—Solo lectura

Las propiedades se asignan con =: Display.fps = 30. Llamarlas como una función (Display.fps(30)) lanza ERR_INVALID_OPERATION, y asignar width, height o draw lanza ERR_ATTRIBUTE_NOT_FOUND.

posBG​

La posición de la imagen de fondo dentro del view, como una lista [x, y]. Los decimales se truncan.

Display.posBG = [10, 20]

Es solo de escritura: leer Display.posBG no devuelve la posición, sino un valor de error.

showBG​

Si es true, update() pinta la imagen de loadBG al preparar cada fotograma. De serie vale false.

Display.showBG = true

autoClear​

Si es true, update() borra cada fotograma nuevo con el color de fondo, draw.colorBG. De serie vale true.

Display.autoClear = false   // lo pintado se queda de un fotograma al siguiente

Con false, lo que has pintado sigue ahí en el fotograma siguiente: sirve para un programa que solo repinta lo que cambia. showBG y autoClear solo cuentan en el modo de doble buffer (2); en el modo directo, update() no pinta ningún fondo.

Con autoClear y showBG, update() borra primero y pinta después la imagen de fondo: lo que la imagen no tapa queda con el color de fondo.

viewWidth​

El ancho del view: la parte de la pantalla donde pinta Draw. Las coordenadas de Draw empiezan en la esquina de arriba a la izquierda del view, y lo que cae fuera no se ve. El view va centrado en la pantalla.

use Display

// Un view de 240 x 160 en una ventana de 320 x 240
Display.viewWidth = 240
Display.viewHeight = 160
Display.open(320, 240)
println(Display.viewWidth) // 240
  • Asígnalo antes de open. Hasta entonces vale 0, y open lo pone al tamaño de la pantalla si no le has dado otro.
  • En Windows, el ESP32 y el S3, asignarlo después de open cambia lo que lees, pero no el view. En el P4 y el S31 el view sí cambia, y se vuelve a centrar.
  • Sirve para dejar un marco alrededor del juego (con loadTFT), o para que un juego hecho para una pantalla pequeña se vea igual en una grande.
  • En Windows, algunas funciones de Draw no cuentan desde el view: mira las trampas de Draw.

viewHeight​

El alto del view. Funciona igual que viewWidth.

Display.viewHeight = 160

fps​

La propiedad fps fija el ritmo del juego: cuántos pasos de lógica por segundo da, sea cual sea la placa y cueste lo que cueste cada fotograma. Es un entero de 0 a 1000; con 0 (el valor por defecto) no hay ritmo y Display.update() no espera nunca.

Con Display.fps = N, cada Display.update() no vuelve hasta que toca el siguiente paso (1/N de segundo después del anterior) y devuelve cuántos pasos tocan. Un juego que mueve una cantidad fija por fotograma deja así de ir más deprisa cuando la placa pinta más rápido (por ejemplo, cuando no hay scroll).

Display.fps = 30          // 30 pasos por segundo en todas las placas

Si la placa no llega a pintar N fotogramas por segundo, el juego que solo pone Display.fps va más lento ese rato. Para que no pierda velocidad, puede dar los pasos que faltan sin pintar, con lo que devuelve update():

Display.fps = 30
var pasos = 1
while (true)
while (pasos > 1) // los pasos que faltan, sin pintar
Logica()
pasos = pasos - 1
end
Logica()
Pintar()
pasos = Display.update() // 1, o 2 o más si el fotograma llegó tarde
end
  • Un valor fuera de 0–1000 se queda en el límite, y los decimales se truncan. Con algo que no es un número, lanza ERR_TYPE_MISMATCH.
Retrasos largos

Con más de 150 ms de retraso (una carga, una pausa) no se recupera: la cuenta vuelve a empezar en ese momento, para que el juego no salga disparado. Al asignar fps, la cuenta también empieza de nuevo.

ESP32-P4 y ESP32-S31

Estas placas presentan cada fotograma al ritmo de refresco de su panel. La velocidad del juego es la de fps igualmente, pero el movimiento solo sale regular si fps divide el refresco del panel (en un panel de 60 Hz, 30 o 60).

dt​

La propiedad dt (solo lectura) da los segundos que han pasado entre el Display.update() anterior y el último, medidos por la VM en microsegundos (después de la espera de fps, si la hay). Sirve para los juegos que mueven multiplicando por el tiempo, en lugar de calcularlo con clock().

var dt = Display.dt
nave.x = nave.x + velocidad * dt

Vale 0 hasta el segundo update(), y tras una carga o una pausa vale como mucho 0.15. Con Display.fps = N y el fotograma a tiempo, vale aproximadamente 1/N: a 30 fps, unos 0.0333. Asignarle un valor lanza ERR_INVALID_OPERATION.

width​

El ancho de la pantalla en píxeles (solo lectura).

var ancho = Display.width
println("Ancho de pantalla: ", ancho)

Vale 320 hasta open. Después, el ancho de la ventana o del panel, y cambia con orientation en placa.

height​

El alto de la pantalla en píxeles (solo lectura).

var alto = Display.height
println("Alto de pantalla: ", alto)

Vale 240 hasta open. Después, el alto de la ventana o del panel.

draw​

El módulo Draw, con el que se pinta.

var draw = Display.draw
draw.color = 0xFF0000
draw.circle(100, 100, 50, true)

Es el mismo módulo que tienes con use Draw.

Ejemplo completo​

Un cuadrado cruza un view de 240 × 160 centrado en la ventana, a 80 píxeles por segundo, en todas las placas igual.

use Display

// Un view de 240 x 160 en el centro de una ventana de 320 x 240
Display.viewWidth = 240
Display.viewHeight = 160
Display.open(320, 240)
Display.fps = 30 // 30 pasos por segundo, en Windows y en las placas

var draw = Display.draw
draw.colorBG = 0x102040 // el color con el que update() borra el view

var x = 0.0
var velocidad = 80 // píxeles por segundo
for (var i = 0; i < 300; i++) // 10 segundos
draw.color = 0xFFCC00
draw.rect(x, 70, 20, 20, true)
Display.update() // presenta, borra el view y espera al siguiente paso
x = x + velocidad * Display.dt
if (x > Display.viewWidth) then
x = -20.0
end
end
Display.close()

Trampas y problemas conocidos​

  • En Windows, el view no recorta hasta el primer update(). Lo que pintas fuera del view antes del primer update() se ve.
  • En placa, open puede no abrir la pantalla. Si el perfil de la placa no describe bien su pantalla, open escribe «Display: Invalid panel/bus configuration from boot.cfg.» en el monitor serie y devuelve un valor de error. Revisa el perfil: Perfiles de placa.
  • En Windows, draw.line, draw.circle, draw.polygon y draw.getPixel no cuentan desde el view. Con un view más pequeño que la pantalla, salen desplazados. Mira Draw.
  • En Windows, loadTFT estira la imagen a toda la ventana (ver loadTFT).

Todos los problemas conocidos de JARU, juntos, están en Problemas conocidos.