new tables in pixel and 1bpp sprites

This commit is contained in:
sejo 2022-02-09 16:59:01 -06:00
parent 9fb05eb4dd
commit 03825d4288
2 changed files with 135 additions and 112 deletions

View File

@ -273,8 +273,8 @@ el envío de un único byte a .Pantalla/píxel realizará el dibujo en la pantal
el nibble alto de ese byte, es decir, el dígito hexadecimal de la izquierda, determinará la capa en la que dibujaremos:
* 0: dibujar un solo píxel en el fondo
* 4: dibujar un solo píxel en el primer plano
* 0: dibujar un solo píxel en el fondo (fn)
* 4: dibujar un solo píxel en el primer plano (pp)
el nibble inferior del byte, es decir, el dígito hexadecimal de la derecha, determinará su color.
@ -282,21 +282,21 @@ las 8 posibles combinaciones del byte 'píxel' que tenemos para dibujar un píxe
+ <table>
+ <tr><th>píxel</th><th>color</th><th>capa</th></tr>
+ <tr><td>00</td><td>0</td><td>fondo</td></tr>
+ <tr><td>01</td><td>1</td><td></td></tr>
+ <tr><td>02</td><td>2</td><td></td></tr>
+ <tr><td>03</td><td>3</td><td></td></tr>
+ <tr><td>40</td><td>0</td><td>primer plano</td></tr>
+ <tr><td>41</td><td>1</td><td></td></tr>
+ <tr><td>42</td><td>2</td><td></td></tr>
+ <tr><td>43</td><td>3</td><td></td></tr>
+ <tr><td class="num">00</td><td class="num">0</td><td>fn</td></tr>
+ <tr><td class="num">01</td><td class="num">1</td><td></td></tr>
+ <tr><td class="num">02</td><td class="num">2</td><td></td></tr>
+ <tr><td class="num">03</td><td class="num">3</td><td></td></tr>
+ <tr><td class="num">40</td><td class="num">0</td><td>pp</td></tr>
+ <tr><td class="num">41</td><td class="num">1</td><td></td></tr>
+ <tr><td class="num">42</td><td class="num">2</td><td></td></tr>
+ <tr><td class="num">43</td><td class="num">3</td><td></td></tr>
+ </table>
& capa del fondo:
& * 00: dibujar el píxel con el color 0
& * 01: dibujar un píxel con el color 1
& * 02: dibujar el píxel con el color 2
& * 03: dibujar el píxel con el color 3
&
&
& capa del primer plano:
& * 40: dibujar un píxel con el color 0
& * 41: dibujar el píxel con el color 1
@ -541,6 +541,8 @@ tengamos en cuenta que aquí no estamos utilizando la runa hexadecimal literal (
para asegurarse de que estos bytes no son leídos como instrucciones por la cpu uxn, es una buena práctica precederlos con la instrucción BRK: esto interrumpirá la ejecución del programa antes de llegar aquí, dejando a uxn en un estado en el que está esperando entradas.
un poco más adelante revisaremos dónde colocar este código.
## configurando la dirección
para dibujar el sprite, necesitamos enviar su dirección en memoria al dispositivo de pantalla y necesitamos asignar un byte de sprite apropiado.
@ -561,73 +563,79 @@ como la dirección es de 2 bytes, la imprimimos con DEO2.
de forma similar a lo que ya vimos con el píxel, el envío de un byte a .Pantalla/sprite realizará el dibujo en la pantalla.
### sprite de nibble alto para 1bpp
### nibble alto de sprite para 1bpp
el nibble alto del byte 'sprite' determinará la capa en la que dibujaremos, igual que cuando dibujábamos usando el byte 'píxel'.
sin embargo, en este caso tendremos otras posibilidades: podemos rotar el sprite en el eje horizontal (x) o en el vertical (y).
sin embargo, en este caso tendremos otras posibilidades: podemos invertir el sprite en el eje horizontal (x) o en el vertical (y).
los ocho valores posibles de este nibble alto, utilizados para dibujar un sprite de 1bpp, son:
los ocho valores posibles de este nibble alto de 'sprite', utilizados para dibujar un sprite de 1bpp, son:
+ <table>
+ <tr><th>nibble alto</th><th>capa</th><th>rotar-y</th><th>rotar-x</th></tr>
+ <tr><td>0</td><td>plano de fondo</td><td>no</td><td>no</td></tr>
+ <tr><td>1</td><td>plano de fondo</td><td>no</td><td>sí</td></tr>
+ <tr><td>2</td><td>plano de fondo</td><td>sí</td><td>no</td></tr>
+ <tr><td>3</td><td>plano de fondo</td><td></td><td>sí</td></tr>
+ <tr><td>4</td><td>primer plano</td><td>no</td><td>no</td></tr>
+ <tr><td>5</td><td>primero plano</td><td>no</td><td>sí</td></tr>
+ <tr><td>6</td><td>primero plano</td><td>sí</td><td>no</td></tr>
+ <tr><td>7</td><td>primero plano</td><td></td><td>sí</td></tr>
+ <tr><th>sprite alto</th><th>capa</th><th>inv-y</th><th>inv-x</th></tr>
+ <tr><td class="num">0</td><td>fn</td><td>no</td><td>no</td></tr>
+ <tr><td class="num">1</td><td></td><td></td><td>sí</td></tr>
+ <tr><td class="num">2</td><td></td><td>sí</td><td>no</td></tr>
+ <tr><td class="num">3</td><td></td><td></td><td>sí</td></tr>
+ <tr><td class="num">4</td><td>pp</td><td>no</td><td>no</td></tr>
+ <tr><td class="num">5</td><td></td><td></td><td>sí</td></tr>
+ <tr><td class="num">6</td><td></td><td>sí</td><td>no</td></tr>
+ <tr><td class="num">7</td><td></td><td></td><td>sí</td></tr>
+ </table>
& * 0: dibujar un sprite de 1bpp en el fondo, con la orientación original
& * 1: dibujar un sprite de 1bpp en el fondo, rotado horizontalmente
& * 2: dibujar un sprite de 1bpp en el fondo, rotado verticalmente
& * 3: dibujar un sprite de 1bpp en el fondo, rotado horizontalmente y verticalmente
& * 4: dibujar un sprite de 1bpp en primer plano, con la orientación original
& * 5: dibujar un sprite de 1bpp en primer plano, rotado horizontalmente
& * 6: dibujar un sprite de 1bpp en primer plano, rotado verticalmente
& * 7: dibujar un sprite de 1bpp en primer plano, rotado horizontalmente y verticalmente
& fondo:
& * 0: dibujar un sprite de 1bpp, con la orientación original
& * 1: dibujar un sprite de 1bpp, rotado horizontalmente
& * 2: dibujar un sprite de 1bpp, rotado verticalmente
& * 3: dibujar un sprite de 1bpp, rotado horizontalmente y verticalmente
&
& primer plano:
& * 4: dibujar un sprite de 1bpp, con la orientación original
& * 5: dibujar un sprite de 1bpp, rotado horizontalmente
& * 6: dibujar un sprite de 1bpp, rotado verticalmente
& * 7: dibujar un sprite de 1bpp, rotado horizontalmente y verticalmente
si se observa con atención, se puede ver algún patrón: cada bit del nibble alto del byte del sprite corresponde a un aspecto diferente de este comportamiento.
lo siguiente muestra el significado de cada uno de estos bits en el nibble alto, suponiendo que estamos contando los bits del byte de derecha a izquierda y de 0 a 7:
+ <table>
+ <tr><th>bit 7</th><th>bit 6</th><th>bit 5</th><th>bit 4</th></tr>
+ <tr><td>modo (0 es 1bpp, 1 es 2bpp)</td><td>capa (0 es plano de fondo, 1 es primer plano)</td><td>rotar verticalmente (0 es no, 1 es sí)</td><td>rotar horizontalmente (0 es no, 1 es sí)</td></tr>
+ <tr><th>bit</th><th>bandera</th><th>0</th><th>1</th></tr>
+ <tr><td class="num">7</td><td>modo</td><td>1bpp</td><td>2bpp</td></tr>
+ <tr><td class="num">6</td><td>capa</td><td>fn</td><td>pp</td></tr>
+ <tr><td class="num">5</td><td>inv-y</td><td>no</td><td>sí</td></tr>
+ <tr><td class="num">4</td><td>inv-x</td><td>no</td><td>sí</td></tr>
+ </table>
& * bit 4: rotación-x
& * bit 5: rotación-y
& * bit 6: capa (0 es plano de fondo, 1 es primer plano)
& * bit 7: modo (0 es 1bpp, 1 es 2bpp)
& * bit 6: capa (0 es plano de fondo, 1 es primer plano)
& * bit 5: inversión-y
& * bit 4: inversión-x
como por ejemplo, cuando el nibble alto del 'sprite' es 0, que en binario es 0000, significa que todas las banderas están apagadas: por eso dibuja un sprite de 1bpp (0) en el fondo (0), que no esta rotado ni verticalmente (0) ni horizontalmente (0).
como por ejemplo, cuando el nibble alto del 'sprite' es 0, que en binario es 0000, significa que todas las banderas están apagadas: por eso dibuja un sprite de 1bpp (0) en el fondo (0), que no esta invertido ni verticalmente (0) ni horizontalmente (0).
un nibble alto de 1, es decir, 0001 en binario, tiene la última bandera encendida, por eso se rota horizontalmente, y así sucesivamente.
un nibble alto de 1, es decir, 0001 en binario, tiene la última bandera encendida, por eso se invierte horizontalmente, y así sucesivamente.
### sprite de nibble bajo para 1bpp
### nibble bajo de sprite para 1bpp
el nibble bajo del byte 'sprite' determinará los colores que se utilizan para dibujar los píxeles "encendido" y "apagado" de los tiles.
el nibble bajo del byte 'sprite' determinará los colores que se utilizan para dibujar los píxeles "encendido" (1) y "apagado" (0) de los tiles.
+ <table>
+ <tr><th>nibble bajo</th><th>color "encendido"</th><th>color "apagado"</th></tr>
+ <tr><td>0</td><td>borrar</td><td>borrar</td></tr>
+ <tr><td>1</td><td>1</td><td>0</td></tr>
+ <tr><td>2</td><td>2</td><td>0</td></tr>
+ <tr><td>3</td><td>3</td><td>0</td></tr>
+ <tr><td>4</td><td>0</td><td>1</td></tr>
+ <tr><td>5</td><td>1</td><td>nada</td></tr>
+ <tr><td>6</td><td>2</td><td>1</td></tr>
+ <tr><td>7</td><td>3</td><td>1</td></tr>
+ <tr><td>8</td><td>0</td><td>2</td></tr>
+ <tr><td>9</td><td>1</td><td>2</td></tr>
+ <tr><td>a</td><td>2</td><td>nada</td></tr>
+ <tr><td>b</td><td>3</td><td>2</td></tr>
+ <tr><td>c</td><td>0</td><td>3</td></tr>
+ <tr><td>d</td><td>1</td><td>3</td></tr>
+ <tr><td>e</td><td>2</td><td>3</td></tr>
+ <tr><td>f</td><td>3</td><td>nada</td></tr>
+ <tr><th>sprite bajo</th><th>color 1</th><th>color 0</th></tr>
+ <tr><td class="num">0</td><td>borrar</td><td>borrar</td></tr>
+ <tr><td class="num">1</td><td>1</td><td>0</td></tr>
+ <tr><td class="num">2</td><td>2</td><td>0</td></tr>
+ <tr><td class="num">3</td><td>3</td><td>0</td></tr>
+ <tr><td class="num">4</td><td>0</td><td>1</td></tr>
+ <tr><td class="num">5</td><td>1</td><td>nada</td></tr>
+ <tr><td class="num">6</td><td>2</td><td>1</td></tr>
+ <tr><td class="num">7</td><td>3</td><td>1</td></tr>
+ <tr><td class="num">8</td><td>0</td><td>2</td></tr>
+ <tr><td class="num">9</td><td>1</td><td>2</td></tr>
+ <tr><td class="num">a</td><td>2</td><td>nada</td></tr>
+ <tr><td class="num">b</td><td>3</td><td>2</td></tr>
+ <tr><td class="num">c</td><td>0</td><td>3</td></tr>
+ <tr><td class="num">d</td><td>1</td><td>3</td></tr>
+ <tr><td class="num">e</td><td>2</td><td>3</td></tr>
+ <tr><td class="num">f</td><td>3</td><td>nada</td></tr>
+ </table>
& * 0: borrar tile
& * 1: "encendido" con el color 1, "apagado" con el color 0
@ -646,13 +654,17 @@ el nibble bajo del byte 'sprite' determinará los colores que se utilizan para d
& * e: "encendido" con el color 2, "apagado" con el color 3
& * f: "encendido" con el color 3, "apagado" sin color
notemos que un 0 en el nibble inferior borrará el tile.
por ejemplo, esto significa que si establecemos el nibble bajo de 'sprite' con el valor de 6, varvara dibujará el sprite utilizando el color 2 para los pixeles "encendidos" y el color 1 para los pixeles "apagados".
notemos que un 0 en el este nibble borrará el tile.
además, 5, 'a' y 'f' en el nibble bajo dibujarán los píxeles que están "encendidos" pero dejarán los que están "apagados" como están: esto le permitirá dibujar sobre algo que ha sido dibujado antes, sin borrarlo completamente.
no te preocupes si esto no está teniendo mucho sentido, ¡veamos un ejemplo!
## hola sprite
¡hagámoslo! el siguiente programa dibujará nuestro sprite una vez:
el siguiente programa dibujará nuestro sprite una vez:
```
( hola-sprite.tal )

View File

@ -273,8 +273,8 @@ sending a single byte to .Screen/pixel will perform the drawing in the screen.
the high nibble of that byte, i.e. the hexadecimal digit at the left, will determine the layer in which we'll draw:
* 0: draw a single pixel in the background
* 4: draw a single pixel in the foreground
* 0: draw a single pixel in the background (bg)
* 4: draw a single pixel in the foreground (fg)
the low nibble of the byte, i.e. the hexadecimal digit at the right, will determine its color.
@ -282,14 +282,14 @@ the 8 possible combinations of the 'pixel' byte that we have for drawing a pixel
+ <table>
+ <tr><th>pixel</th><th>color</th><th>layer</th></tr>
+ <tr><td>00</td><td>0</td><td>background</td></tr>
+ <tr><td>01</td><td>1</td><td></td></tr>
+ <tr><td>02</td><td>2</td><td></td></tr>
+ <tr><td>03</td><td>3</td><td></td></tr>
+ <tr><td>40</td><td>0</td><td>foreground</td></tr>
+ <tr><td>41</td><td>1</td><td></td></tr>
+ <tr><td>42</td><td>2</td><td></td></tr>
+ <tr><td>43</td><td>3</td><td></td></tr>
+ <tr><td class="num">00</td><td class="num">0</td><td>bg</td></tr>
+ <tr><td class="num">01</td><td class="num">1</td><td></td></tr>
+ <tr><td class="num">02</td><td class="num">2</td><td></td></tr>
+ <tr><td class="num">03</td><td class="num">3</td><td></td></tr>
+ <tr><td class="num">40</td><td class="num">0</td><td>fg</td></tr>
+ <tr><td class="num">41</td><td class="num">1</td><td></td></tr>
+ <tr><td class="num">42</td><td class="num">2</td><td></td></tr>
+ <tr><td class="num">43</td><td class="num">3</td><td></td></tr>
+ </table>
& background layer:
& * 00: draw pixel with color 0
@ -541,6 +541,8 @@ note that we are not using the literal hex (#) rune here: we want to use the raw
to make sure that these bytes are not read as instructions by the uxn cpu, it's a good practice to precede them with the BRK instruction: this will interrupt the execution of the program before arriving here, leaving uxn in a state where it's waiting for inputs.
we'll see in a moment where to write this code.
## setting the address
in order to draw the sprite, we need to send its address in memory to the screen device, and we need to assign an appropriate sprite byte.
@ -567,41 +569,46 @@ the high nibble of the 'sprite' byte will determine the layer in which we'll dra
however, in this case we'll have other possibilities: we can flip the sprite in the horizontal (x) and/or the vertical (y) axis.
the eight possible values of this high nibble, used for drawing a 1bpp sprite, are:
the eight possible values of the sprite high nibble, used for drawing a 1bpp sprite, are:
+ <table>
+ <tr><th>high nibble</th><th>layer</th><th>flip-y</th><th>flip-x</th></tr>
+ <tr><td>0</td><td>background</td><td>no</td><td>no</td></tr>
+ <tr><td>1</td><td>background</td><td>no</td><td>yes</td></tr>
+ <tr><td>2</td><td>background</td><td>yes</td><td>no</td></tr>
+ <tr><td>3</td><td>background</td><td>yes</td><td>yes</td></tr>
+ <tr><td>4</td><td>foreground</td><td>no</td><td>no</td></tr>
+ <tr><td>5</td><td>foreground</td><td>no</td><td>yes</td></tr>
+ <tr><td>6</td><td>foreground</td><td>yes</td><td>no</td></tr>
+ <tr><td>7</td><td>foreground</td><td>yes</td><td>yes</td></tr>
+ <tr><th>sprite high</th><th>layer</th><th>flip-y</th><th>flip-x</th></tr>
+ <tr><td class="num">0</td><td>bg</td><td>no</td><td>no</td></tr>
+ <tr><td class="num">1</td><td></td><td></td><td>yes</td></tr>
+ <tr><td class="num">2</td><td></td><td>yes</td><td>no</td></tr>
+ <tr><td class="num">3</td><td></td><td></td><td>yes</td></tr>
+ <tr><td class="num">4</td><td>fg</td><td>no</td><td>no</td></tr>
+ <tr><td class="num">5</td><td></td><td></td><td>yes</td></tr>
+ <tr><td class="num">6</td><td></td><td>yes</td><td>no</td></tr>
+ <tr><td class="num">7</td><td></td><td></td><td>yes</td></tr>
+ </table>
& * 0: draw a 1bpp sprite in the background, original orientation
& * 1: draw a 1bpp sprite in the background, flipped horizontally
& * 2: draw a 1bpp sprite in the background, flipped vertically
& * 3: draw a 1bpp sprite in the background, flipped horizontally and vertically
& * 4: draw a 1bpp sprite in the foreground, original orientation
& * 5: draw a 1bpp sprite in the foreground, flipped horizontally
& * 6: draw a 1bpp sprite in the foreground, flipped vertically
& * 7: draw a 1bpp sprite in the foreground, flipped horizontally and vertically
& background:
& * 0: draw a 1bpp sprite, original orientation
& * 1: draw a 1bpp sprite, flipped horizontally
& * 2: draw a 1bpp sprite, flipped vertically
& * 3: draw a 1bpp sprite, flipped horizontally and vertically
&
& foreground:
& * 4: draw a 1bpp sprite, original orientation
& * 5: draw a 1bpp sprite, flipped horizontally
& * 6: draw a 1bpp sprite, flipped vertically
& * 7: draw a 1bpp sprite, flipped horizontally and vertically
if you observe carefully, you might see some pattern: each bit in the high nibble of the sprite byte corresponds to a different aspect of this behavior.
the following shows the meaning of each of these bits in the high nibble, assuming that we are counting the byte bits from right to left, and from 0 to 7:
+ <table>
+ <tr><th>bit 7</th><th>bit 6</th><th>bit 5</th><th>bit 4</th></tr>
+ <tr><td>mode (0 is 1bpp, 1 is 2bpp)</td><td>layer (0 is background, 1 is foreground)</td><td>flip vertically (0 is no, 1 is yes)</td><td>flip horizontally (0 is no, 1 is yes)</td></tr>
+ <tr><th>bit</th><th>flag</th><th>0</th><th>1</th></tr>
+ <tr><td class="num">7</td><td>mode</td><td>1bpp</td><td>2bpp</td></tr>
+ <tr><td class="num">6</td><td>layer</td><td>bg</td><td>fg</td></tr>
+ <tr><td class="num">5</td><td>flip-y</td><td>no</td><td>yes</td></tr>
+ <tr><td class="num">4</td><td>flip-x</td><td>no</td><td>yes</td></tr>
+ </table>
& * bit 4: flip-x
& * bit 5: flip-y
& * bit 6: layer (0 is background, 1 is foreground)
& * bit 7: mode (0 is 1bpp, 1 is 2bpp)
& * bit 6: layer (0 is background, 1 is foreground)
& * bit 5: flip-y
& * bit 4: flip-x
as an example, when the 'sprite' high nibble is 0, that in binary is 0000, it means that all the flags are off: that's why it draws a 1bpp (0) sprite in the background (0), not flipped neither vertically (0) nor horizontally (0).
@ -609,26 +616,26 @@ a high nible of 1, i.e. 0001 in binary, has the last flag on, so that's why it's
### sprite low nibble for 1bpp
the low nibble of the 'sprite' byte will determine the colors that are used to draw the "on" and "off" pixels of the tiles.
the low nibble of the 'sprite' byte will determine the colors that are used to draw the "on" (1) and "off"(0) pixels of the tiles.
+ <table>
+ <tr><th>low nibble</th><th>"on" color</th><th>"off" color</th></tr>
+ <tr><td>0</td><td>clear</td><td>clear</td></tr>
+ <tr><td>1</td><td>1</td><td>0</td></tr>
+ <tr><td>2</td><td>2</td><td>0</td></tr>
+ <tr><td>3</td><td>3</td><td>0</td></tr>
+ <tr><td>4</td><td>0</td><td>1</td></tr>
+ <tr><td>5</td><td>1</td><td>none</td></tr>
+ <tr><td>6</td><td>2</td><td>1</td></tr>
+ <tr><td>7</td><td>3</td><td>1</td></tr>
+ <tr><td>8</td><td>0</td><td>2</td></tr>
+ <tr><td>9</td><td>1</td><td>2</td></tr>
+ <tr><td>a</td><td>2</td><td>none</td></tr>
+ <tr><td>b</td><td>3</td><td>2</td></tr>
+ <tr><td>c</td><td>0</td><td>3</td></tr>
+ <tr><td>d</td><td>1</td><td>3</td></tr>
+ <tr><td>e</td><td>2</td><td>3</td></tr>
+ <tr><td>f</td><td>3</td><td>none</td></tr>
+ <tr><th>sprite low</th><th>color 1</th><th>color 0</th></tr>
+ <tr><td class="num">0</td><td>clear</td><td>clear</td></tr>
+ <tr><td class="num">1</td><td>1</td><td>0</td></tr>
+ <tr><td class="num">2</td><td>2</td><td>0</td></tr>
+ <tr><td class="num">3</td><td>3</td><td>0</td></tr>
+ <tr><td class="num">4</td><td>0</td><td>1</td></tr>
+ <tr><td class="num">5</td><td>1</td><td>none</td></tr>
+ <tr><td class="num">6</td><td>2</td><td>1</td></tr>
+ <tr><td class="num">7</td><td>3</td><td>1</td></tr>
+ <tr><td class="num">8</td><td>0</td><td>2</td></tr>
+ <tr><td class="num">9</td><td>1</td><td>2</td></tr>
+ <tr><td class="num">a</td><td>2</td><td>none</td></tr>
+ <tr><td class="num">b</td><td>3</td><td>2</td></tr>
+ <tr><td class="num">c</td><td>0</td><td>3</td></tr>
+ <tr><td class="num">d</td><td>1</td><td>3</td></tr>
+ <tr><td class="num">e</td><td>2</td><td>3</td></tr>
+ <tr><td class="num">f</td><td>3</td><td>none</td></tr>
+ </table>
& * 0: clear tile
& * 1: "on" with color 1, "off" with color 0
@ -647,13 +654,17 @@ the low nibble of the 'sprite' byte will determine the colors that are used to d
& * e: "on" with color 2, "off" with color 3
& * f: "on" with color 3, "off" with no color
as an example, this means that setting the sprite low nibble to 6 will draw the sprite with color 2 in the "on" pixels, and color 1 in the "off" pixels.
note that 0 in the low nibble will clear the tile.
additionally, 5, 'a' and 'f' in the low nibble will draw the pixels that are "on" but will leave the ones that are "off" as is: this will allow you to draw over something that has been drawn before, without erasing it completely.
don't worry if this is not making a lot of sense: let's see an example!
## hello sprite
let's do this! the following program will draw our sprite once:
the following program will draw our sprite once:
```
( hello-sprite.tal )