598 lines
19 KiB
Plaintext
598 lines
19 KiB
Plaintext
# tutorial uxn apéndice a: repetir un tile dentro de un rectángulo
|
|
lang=es en->{uxn tutorial appendix a}
|
|
en la primera parte del {tutorial de uxn día 6} hablamos de cómo cubrir el fondo de la pantalla con un tile dado.
|
|
|
|
aquí generalizaremos un procedimiento similar en una subrutina dibuja-tiles que dibuje un rectángulo relleno con un tile dado. recibirá las coordenadas x,y de la esquina superior izquierda del rectángulo, su anchura y altura en píxeles y la dirección del tile:
|
|
|
|
```
|
|
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
|
|
```
|
|
|
|
un recordatorio de que estamos utilizando la convención de añadir un signo de intercalación (^) después del nombre de un valor para indicar que es un corto y un asterisco (*) para indicar que es un corto que funciona como un puntero (es decir, una dirección en la memoria del programa)
|
|
|
|
vamos a detallar cómo llegar a dos versiones de esta subrutina, una que se basa en una fuerte manipulación de la pila, y otra que utiliza variables. esto con el fin de comparar ambos enfoques y darnos una visión más amplia de las posibilidades dentro de uxntal.
|
|
|
|
# configuración
|
|
|
|
comencemos con el siguiente programa como plantilla. incluye los datos para un sprite de 1bpp compuesto por líneas diagonales.
|
|
|
|
```
|
|
( hola-fondo.tal )
|
|
|
|
( dispositivos )
|
|
|00 @Sistema [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|
|
|20 @Pantalla [ &vector $2 &ancho $2 &alto $2 &auto $1 &pad $1 &x $2 &y $2 &direc $2 &píxel $1 &sprite $1 ]
|
|
|
|
( macros )
|
|
%RTN { JMP2r }
|
|
|
|
( programa principal )
|
|
|0100
|
|
@configuracion
|
|
( establecer los colores del sistema )
|
|
#2ce9 .Sistema/r DEO2
|
|
#01c0 .Sistema/g DEO2
|
|
#2ce5 .Sistema/b DEO2
|
|
|
|
BRK
|
|
|
|
@tile-fondo 1122 4488 1122 4488
|
|
```
|
|
|
|
# repetir un tile en una fila
|
|
|
|
¿qué procedimiento podríamos seguir para repetir el dibujo de un tile empezando por x y terminando en un límite correspondiente a x+ancho?
|
|
|
|
una forma sería algo así como:
|
|
|
|
* dibujar tile en x
|
|
* añadir 8 (el tamaño del tile) a x
|
|
* ¿es x menor que el límite? si lo es, repite el procedimiento, si no, termina
|
|
|
|
## versión concreta
|
|
|
|
antes de abstraerlo, recomiendo que lo escribamos con números concretos.
|
|
|
|
digamos que nuestra x inicial es 0008, nuestro ancho es 0100 y el tile que estamos dibujando es tile-fondo.
|
|
|
|
el límite, x+ancho, sería 0108.
|
|
|
|
el primer paso, dibujar el tile en x sería:
|
|
|
|
```
|
|
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
|
|
#0008 .Pantalla/x DEO2 ( establecer la x inicial )
|
|
|
|
#03 .Pantalla/sprite DEO ( dibujar sprite de 1bpp con color 3 y 0 )
|
|
```
|
|
|
|
añadiendo 8 a x, ya sabemos:
|
|
|
|
```
|
|
.Pantalla/x DEI2 #0008 ADD2 ( añadir 8 a x )
|
|
.Pantalla/x DEO2 ( guardar la nueva x )
|
|
```
|
|
|
|
comprobar si x es menor que el límite, saltando si lo es, sería algo así:
|
|
|
|
```
|
|
.Pantalla/x DEI2
|
|
#0108 ( el límite )
|
|
LTH2 ,&bucle JCN ( saltar si x es menor que el límite )
|
|
```
|
|
|
|
integrando todo ello, podríamos obtener:
|
|
|
|
```
|
|
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
|
|
#0008 .Pantalla/x DEO2 ( establecer la x inicial )
|
|
|
|
&bucle-x
|
|
#03 .Pantalla/sprite DEO ( dibujar sprite de 1bpp con color 3 y 0 )
|
|
.Pantalla/x DEI2 #0008 ADD2 DUP2 ( añadir 8 a x )
|
|
.Pantalla/x DEO2 ( almacenar la nueva x )
|
|
#0108 LTH2 ,&bucle-x JCN ( salta si x es menor que el límite )
|
|
```
|
|
|
|
nótese el uso de DUP2 para evitar releer el valor de x.
|
|
|
|
## abstrayendo
|
|
|
|
ahora, digamos que queremos que el código anterior funcione con cualquier x inicial y ancho inicial dados, presentes en la pila antes de empezar.
|
|
|
|
podemos incluso pensar en ello como una subrutina por sí misma con la siguiente firma:
|
|
|
|
```
|
|
@dibuja-tiles-en-fila ( x^ ancho^ -- )
|
|
```
|
|
|
|
asumamos por el momento que la dirección del sprite ya fue establecida, para enfocarnos en `x` y en el ancho.
|
|
|
|
al iniciar la subrutina, el ancho está en la parte superior de la pila, seguido de la x inicial.
|
|
|
|
podemos utilizar estos dos valores para calcular el límite, que podemos almacenar en la pila de retorno.
|
|
|
|
una forma de conseguirlo, anotando el estado de la pila de trabajo después de cada instrucción, podría ser:
|
|
|
|
```
|
|
( estado inicial: ptra: x^ ancho^ )
|
|
OVR2 ( ptra: x^ ancho^ x^ )
|
|
ADD2 ( ptra: x^ límite^ )
|
|
STH2 ( ptra: x^ / pret: límite^ )
|
|
```
|
|
|
|
otra más:
|
|
|
|
```
|
|
( estado inicial: ptra: x^ ancho^ )
|
|
ADD2k ( ptra: x^ ancho^ límite^ )
|
|
STH2 ( ptra: x^ ancho^ / pret: límite^ )
|
|
POP2 ( ptra: x^ / pret: límite^ )
|
|
```
|
|
|
|
recuerda que estamos mostrando la parte superior de las pilas a su derecha.
|
|
|
|
después de estos pasos, la x inicial está en la parte superior de la pila, por lo que podemos enviarla directamente a la pantalla.
|
|
|
|
el último cambio que necesitaríamos es reemplazar nuestro límite codificado por una instrucción STH2kr (copiar el límite de la pila de retorno a la pila de trabajo) y terminar nuestra rutina con una POP2r (eliminar el límite de la pila de retorno).
|
|
|
|
nuestra subrutina se vería entonces de la siguiente manera:
|
|
|
|
```
|
|
@dibuja-tiles-en-fila ( x^ ancho^ -- )
|
|
( calcular y guardar el límite )
|
|
OVR2 ( ptra: x^ ancho^ x^ )
|
|
ADD2 ( ptra: x^ límite^ )
|
|
STH2 ( ptra: x^ / pret: límite^ )
|
|
.Pantalla/x DEO2 ( fijar x inicial )
|
|
|
|
&bucle-x
|
|
#03 .Pantalla/sprite DEO ( dibujar sprite con color 3 y 0 )
|
|
.Pantalla/x DEI2 #0008 ADD2 DUP2 ( añadir 8 a x )
|
|
.Pantalla/x DEO2 ( guardar la nueva x )
|
|
STH2kr ( copiar límite de pret en ptra )
|
|
LTH2 ,&bucle-x JCN ( saltar si x es menor que el límite )
|
|
POP2r ( hacer POP en límite de pret )
|
|
RTN
|
|
```
|
|
|
|
## programa completo
|
|
|
|
lo siguiente muestra nuestro programa en contexto, llenando completamente la primera fila de nuestra pantalla con nuestro tile:
|
|
|
|
=> ./img/screenshot_uxn-background-row.png captura de pantalla mostrando la primera fila de la pantalla varvara rellenada con líneas diagonales
|
|
|
|
```
|
|
( hola-fondo.tal )
|
|
|
|
( dispositivos )
|
|
|00 @Sistema [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|
|
|20 @Pantalla [ &vector $2 &ancho $2 &alto $2 &auto $1 &pad $1 &x $2 &y $2 &direc $2 &píxel $1 &sprite $1 ]
|
|
|
|
( macros )
|
|
%RTN { JMP2r }
|
|
|
|
( programa principal )
|
|
|0100
|
|
@configuracion
|
|
( establecer los colores del sistema )
|
|
#2ce9 .Sistema/r DEO2
|
|
#01c0 .Sistema/g DEO2
|
|
#2ce5 .Sistema/b DEO2
|
|
|
|
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
|
|
#0000 ( x inicial )
|
|
.Pantalla/ancho DEI2 ( obtener el ancho de la pantalla )
|
|
;dibuja-tiles-en-fila JSR2
|
|
BRK
|
|
|
|
@dibuja-tiles-en-fila ( x^ ancho^ -- )
|
|
OVR2 ( ptra: x^ límite^ x^ )
|
|
ADD2 ( ptra: x^ límite^ )
|
|
STH2 ( ptra: x^ / pret: límite^ )
|
|
.Pantalla/x DEO2 ( fijar x inicial )
|
|
|
|
&bucle-x
|
|
#03 .Pantalla/sprite DEO ( dibujar sprite con color 3 y 0 )
|
|
.Pantalla/x DEI2 #0008 ADD2 DUP2 ( añadir 8 a x )
|
|
.Pantalla/x DEO2 ( guarda la nueva x )
|
|
STH2kr ( copiar límite de pret en ptra )
|
|
LTH2 ,&bucle-x JCN ( saltar si x es menor que el límite )
|
|
POP2r ( sacar el límite de pret )
|
|
RTN
|
|
|
|
@tile-fondo 1122 4488 1122 4488
|
|
```
|
|
|
|
# repetir una fila
|
|
|
|
similar a lo que acabamos de hacer: ¿cuál es el procedimiento que podríamos seguir para repetir verticalmente una fila empezando por `y` y terminando en un límite correspondiente a y+altura?
|
|
|
|
siguiendo la misma estrategia, podríamos hacer:
|
|
|
|
* dibujar la fila en y
|
|
* añadir 8 (el tamaño del tile) a y
|
|
* ¿es `y` menor que el límite? si lo es, repetir el procedimiento, en caso contrario terminar
|
|
|
|
## versión concreta
|
|
|
|
utilicemos los mismos números que antes, suponiendo que nuestra `y` inicial es 0008, nuestra altura es 0100, y por tanto, nuestro límite siendo 0108.
|
|
|
|
en el caso de x, comencemos en 0000 y tengamos un ancho correspondiente al ancho de la pantalla.
|
|
|
|
como la dirección no cambiaría en el proceso, podemos establecerla al principio y olvidarnos de ella.
|
|
|
|
el siguiente código se basa en el bucle anterior de x, pero ahora dibuja una fila en una coordenada `y` dada, le suma 8 y luego comprueba si es menor que el límite:
|
|
|
|
```
|
|
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
|
|
|
|
#0008 .Pantalla/y ( establecer y inicial )
|
|
|
|
&bucle-y
|
|
( preparar y dibujar fila )
|
|
#0000 ( x inicial )
|
|
.Pantalla/ancho DEI2 ( obtener el ancho de la pantalla )
|
|
;dibuja-tiles-en-fila JSR2
|
|
|
|
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añade 8 a y )
|
|
.Pantalla/y DEO2 ( guardar la nueva y )
|
|
#0108 ( poner límite en la parte superior de la pila )
|
|
LTH2 ,&bucle-y JCN ( saltar si x es menor que el límite )
|
|
```
|
|
|
|
## versión abstracta
|
|
|
|
ahora, antes de saltar directamente a la emulación de la solución para dibujar la fila, vamos a notar que en este caso no es tan fácil.
|
|
|
|
¿por qué? porque la idea de nuestra subrutina dibuja-tiles es que debe ser capaz de recibir la x inicial y el ancho del rectángulo y ahora mismo estos valores están codificados dentro del bucle.
|
|
|
|
esta debería ser la firma de nuestra subrutina:
|
|
|
|
```
|
|
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
|
|
```
|
|
|
|
podemos abordar este problema bien con alguna "manipulación de la pila ", o bien con "variables ".
|
|
|
|
también hay que tener en cuenta que lo haremos porque estamos tratando de llegar a una subrutina generalizada.
|
|
|
|
si solo quisiéramos cubrir toda la pantalla con un sprite, ya tenemos todo el código necesario: solo tendríamos que adaptar el límite vertical del bucle para que se corresponda con la altura de la pantalla, ¡y ya está!
|
|
|
|
entonces podríamos pasar a la sección relativa de las paletas. sin embargo, lo que sigue puede ser interesante como una forma de ver un posible enfoque para escribir un código uxntal más complejo :)
|
|
|
|
## usando la manipulación de la pila
|
|
|
|
en principio podríamos simplemente manipular los elementos dados en la pila, almacenándolos cuando sea apropiado, para adaptar nuestra subrutina a su firma.
|
|
|
|
en primer lugar, la dirección del tile es el valor de la parte superior de la pila. podemos consumirlo y olvidarnos de él:
|
|
|
|
```
|
|
( ptra inicial: x^ y^ ancho^ alto^ direc* )
|
|
.Pantalla/direc DEO2 ( ptra: x^ y^ ancho^ alto^ )
|
|
```
|
|
|
|
pensando en el bucle vertical, necesitamos calcular su límite sumando la altura a `y` y necesitamos establecer la `y` inicial.
|
|
|
|
podríamos hacer lo siguiente:
|
|
|
|
```
|
|
ROT2 ( ptra: x^ ancho^ altura^ y^ )
|
|
DUP2 ( ptra: x^ ancho^ altura^ y^ y^ )
|
|
|
|
( establecer y inicial: )
|
|
.Pantalla/y DEO2 ( ptra: x^ ancho^ alto^ y^ )
|
|
|
|
( calcular y almacenar el límite vertical )
|
|
ADD2 ( ptra: x^ ancho^ limite-y^ )
|
|
STH2 ( ptra: x^ ancho^ / pret: limite-y^ )
|
|
```
|
|
|
|
ahora, podríamos también almacenar el ancho y `x`, ya que las necesitamos después en su orden original (primero x, luego el ancho )
|
|
|
|
```
|
|
STH2 ( ptra: x^ / pret: limite-y^ ancho^ )
|
|
STH2 ( ptra: / pret: limite-y^ ancho^ x^ )
|
|
```
|
|
|
|
en teoría, la primera parte de nuestra subrutina podría verse como:
|
|
|
|
```
|
|
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
|
|
( establecer la dirección del tile )
|
|
.Pantalla/direc DEO2 ( ptra: x^ y^ ancho^ alto^ )
|
|
|
|
ROT2 ( ptra: x^ ^ altura^ y^ )
|
|
DUP2 ( ptra: x^ ^ altura^ y^ )
|
|
|
|
( fijar `y` inicial )
|
|
.Pantalla/y DEO2 ( fijar `y` inicial, ptra: x^ ^ altura^ y^ )
|
|
|
|
( calcular y guardar limite-y )
|
|
ADD2 ( ptra: x^ ^ limite-y^ )
|
|
STH2 ( ptra: x^ ^ / pret: limite-y^ )
|
|
|
|
( almacenar ancho y `x` )
|
|
STH2 STH2 ( ptra: / pret: limite-y^ ancho^ x^ )
|
|
|
|
&bucle-y
|
|
( preparar y dibujar la fila )
|
|
( recuperar x )
|
|
STH2r ( ptra: x^ / pret: limite-y^ ancho^ )
|
|
|
|
( recuperar el ancho )
|
|
STH2r ( ptra: x^ ancho^ / pret: limite-y^ )
|
|
;dibuja-tiles-en-fila JSR2
|
|
```
|
|
|
|
el problema es que dentro del bucle, ambas instrucciones STH2r recuperan y consumen los valores de `x` y ancho de la pila de retorno. por tanto, en la siguiente iteración no podríamos volver a utilizarlos, ya que se perderían.
|
|
|
|
podemos pensar que podríamos reemplazar estas instrucciones con STH2kr:
|
|
|
|
```
|
|
&bucle-y
|
|
( preparar y dibujar la fila )
|
|
( recuperar x )
|
|
STH2kr ( ptra: x^ / pret: limite-y^ ancho^ x^ )
|
|
```
|
|
|
|
¡pero entonces no podemos recuperar el ancho porque la x sigue en la parte superior de la pila de retorno!
|
|
|
|
oh, muchas dificultades, pero por el bien del ejemplo de la pila, vamos a seguir resolviendo esto (?)
|
|
|
|
¿cómo podemos poner el ancho en la parte superior de la pila de retorno? tal vez con un intercambio aplicado a la pila de retorno:
|
|
|
|
```
|
|
SWP2r ( ptra: x^ / pret: limite-y^ x^ ancho^ )
|
|
```
|
|
|
|
entonces podemos recuperar el ancho y utilizarlo:
|
|
|
|
```
|
|
STH2kr ( ptra: x^ ancho^ / pret: limite-y^ x^ ancho^ )
|
|
;dibuja-tiles-en-fila JSR2 ( ptra: / pret: limite-y^ x^ ancho^ )
|
|
```
|
|
|
|
¿qué sigue? añadir 8 a `y` y comprobar si es menor que el límite. la primera parte va sin problemas:
|
|
|
|
```
|
|
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añade 8 a `y`; ptra: y^ y^ / pret: limite-y^ x^ ancho^ )
|
|
.Pantalla/y DEO2 ( almacenar nueva `y`; ptra: y^ / pret: limite-y^ x^ ancho^ )
|
|
```
|
|
|
|
para conseguir el límite en la pila de trabajo para la comparación, tenemos que girar la pila de retorno:
|
|
|
|
```
|
|
ROT2r ( ptra: y^ / pret: x^ ancho^ limite-y^ )
|
|
STH2kr ( ptra: y^ limite-y^ / pret: x^ ancho^ limite-y^ )
|
|
```
|
|
|
|
pero ah, antes de hacer la comparación y el salto, debemos reordenar la pila de retorno para que se corresponda con la ordenación que teníamos al principio del bucle:
|
|
|
|
```
|
|
SWP2r ( ptra: y^ limite-y^ / pret: x^ limite-y^ ancho^ )
|
|
ROT2r ( ptra: y^ limite-y^ / pret: limite-y^ ancho^ x^ )
|
|
```
|
|
|
|
ahora podemos hacer la comparación y saltar:
|
|
|
|
```
|
|
LTH2 ,&bucle-y JCN ( salta si x es menor que el límite )
|
|
```
|
|
|
|
después debemos limpiar la pila de retorno:
|
|
|
|
```
|
|
POP2r POP2r POP2r
|
|
```
|
|
|
|
después de todo esto, nuestra subrutina tendría el siguiente aspecto:
|
|
|
|
```
|
|
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
|
|
( establecer la dirección del tile )
|
|
.Pantalla/direc DEO2 ( ptra: x^ y^ ancho^ alto^ )
|
|
|
|
ROT2 ( ptra: x^ ^ altura^ y^ )
|
|
DUP2 ( ptra: x^ ^ altura^ y^ )
|
|
|
|
( fijar `y` inicial )
|
|
.Pantalla/y DEO2 ( fijar `y` inicial, ptra: x^ ^ altura^ y^ )
|
|
|
|
( calcular y almacenar limite-y )
|
|
ADD2 ( ptra: x^ ^ limite-y^ )
|
|
STH2 ( ptra: x^ ^ / pret: limite-y^ )
|
|
|
|
( almacenar ancho y `x` )
|
|
STH2 STH2 ( ptra: / pret: limite-y^ ancho^ x^ )
|
|
|
|
&bucle-y
|
|
( preparar y dibujar la fila )
|
|
( recuperar x )
|
|
STH2kr ( ptra: x^ / pret: limite-y^ ancho^ x^ )
|
|
|
|
( recuperar el ancho )
|
|
SWP2r ( ptra: x^ / pret: limite-y^ x^ ancho^ )
|
|
STH2kr ( ptra: x^ ancho^ / pret: limite-y^ x^ ancho^ )
|
|
;dibuja-tiles-en-fila JSR2 ( ptra: / pret: limite-y^ x^ ancho^ )
|
|
|
|
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añadir 8 a y )
|
|
.Pantalla/y DEO2 ( almacenar la nueva y )
|
|
|
|
( recuperar limite-y )
|
|
ROT2r ( ptra: y^ / pret: x^ ^ limite-y^ )
|
|
STH2kr ( ptra: y^ limite-y^ / pret: x^ ancho^ limite-y^ )
|
|
|
|
( reordenar la pila de retorno )
|
|
SWP2r ( ptra: y^ limite-y^ / pret: x^ limite-y^ ancho^ )
|
|
ROT2r ( ptra: y^ limite-y^ / pret: limite-y^ ancho^ x^ )
|
|
|
|
LTH2 ,&bucle-y JCN ( salta si x es menor que el límite )
|
|
|
|
POP2r POP2r POP2r ( limpiar la pila de retorno )
|
|
RTN
|
|
```
|
|
|
|
podemos entonces llamarlo de la siguiente manera para obtener un cuadrado de 256x256 lleno de tiles:
|
|
|
|
```
|
|
#0008 #0008 ( `x` y `y` )
|
|
#0100 #0100 ( ancho y alto )
|
|
;tile-fondo
|
|
;dibuja-tiles JSR2
|
|
```
|
|
|
|
=> ./img/screenshot_uxn-background-square.png captura de pantalla que muestra un gran cuadrado en la pantalla varvara compuesto por líneas diagonales
|
|
|
|
## usando variables
|
|
|
|
comparemos el enfoque anterior con el uso de variables relativas.
|
|
|
|
iremos "con todo" de una manera relativamente derrochadora, sin optimizar los procedimientos que podrían beneficiarse de la manipulación de la pila.
|
|
|
|
declararemos las siguientes etiquetas para nuestras variables, después del RTN que termina la subrutina:
|
|
|
|
```
|
|
( variables )
|
|
&alto $2 &ancho $2 &y $2 &x $2 &limite-y $2
|
|
```
|
|
|
|
ahora, iniciamos la subrutina de la misma manera que antes, estableciendo la dirección para nuestro sprite:
|
|
|
|
```
|
|
( ptra inicial: x^ y^ ancho^ alto^ direc* )
|
|
.Pantalla/direc DEO2 ( ptra: x^ y^ ancho^ alto^ )
|
|
```
|
|
|
|
entonces, simplemente almacenamos los siguientes valores en direcciones relativas:
|
|
|
|
```
|
|
,&alto STR2
|
|
,&ancho STR2
|
|
&y STR2
|
|
&x STR2
|
|
```
|
|
|
|
nótese que vamos en orden inverso.
|
|
|
|
después de estas operaciones las pilas están vacías.
|
|
|
|
entonces podemos fijar la `y` inicial y calcular el límite vertical, utilizando los valores almacenados en las variables:
|
|
|
|
```
|
|
( establecer `y` inicial )
|
|
,&y LDR2 DUP2 ( ptra: y^ y^ )
|
|
.Pantalla/y DEO2 ( ptra: y^ )
|
|
|
|
( calcular limite-y )
|
|
,&alto LDR2 ( ptra: y^ alto^ )
|
|
ADD2 ( ptra: limite-y^ )
|
|
,&limite-y STR2 ( ptra: )
|
|
```
|
|
|
|
nuestro bucle ahora tendría el siguiente aspecto:
|
|
|
|
```
|
|
&bucle-y
|
|
( recuperar `x` y ancho )
|
|
,&x LDR2
|
|
&ancho LDR2
|
|
( dibujar fila )
|
|
;dibuja-tiles-en-fila JSR2
|
|
|
|
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añade 8 a y )
|
|
.Pantalla/y DEO2 ( almacenar la nueva y )
|
|
|
|
( recuperar el límite vertical )
|
|
,&limite-y LDR2
|
|
|
|
LTH2 ,&bucle-y JCN ( saltar si x es menor que el límite )
|
|
```
|
|
|
|
¡y eso es todo!
|
|
|
|
compara esto con la versión "concreta" que desarrollamos anteriormente, ¡es muy similar en su estructura!
|
|
|
|
la subrutina completa tendría el siguiente aspecto:
|
|
|
|
```
|
|
@dibuja-tiles ( x^ y^ ancho^ alto^ direc* -- )
|
|
( establecer la dirección del tile )
|
|
.Pantalla/direc DEO2 ( ptra: x^ y^ ancho^ alto^ )
|
|
|
|
( almacenar valores )
|
|
,&altura STR2
|
|
,&ancho STR2
|
|
&y STR2
|
|
,&x STR2
|
|
|
|
( establecer `y` inicial )
|
|
,&y LDR2 DUP2 ( ptra: y^ y^ )
|
|
.Pantalla/y DEO2 ( ptra: y^ )
|
|
|
|
( calcular el límite vertical )
|
|
,&alto LDR2 ( ptra: y^ alto^ )
|
|
ADD2 ( ptra: limite-y^ )
|
|
,&limite-y STR2 ( ptra: )
|
|
|
|
&bucle-y
|
|
( recuperar `x` y ancho )
|
|
,&x LDR2
|
|
,&ancho LDR2
|
|
( dibujar fila )
|
|
;dibuja-tiles-en-fila JSR2
|
|
|
|
.Pantalla/y DEI2 #0008 ADD2 DUP2 ( añade 8 a y )
|
|
.Pantalla/y DEO2 ( almacenar la nueva y )
|
|
|
|
( recuperar el límite vertical )
|
|
,&limite-y LDR2
|
|
|
|
LTH2 ,&bucle-y JCN ( saltar si x es menor que el límite )
|
|
|
|
RTN
|
|
( variables )
|
|
&alto $2 &ancho $2 &y $2 &x $2 &limite-y $2
|
|
```
|
|
|
|
como he dicho antes, podemos encontrar aquí algunas oportunidades de optimización.
|
|
|
|
tal vez el límite vertical puede ser escondido en la pila de retorno como en el bucle dibuja-tiles-en-fila, o tal vez la variable para la altura y para la `y` inicial no son necesarios.
|
|
|
|
dejo que lo resuelvas :)
|
|
|
|
nota que esta subrutina tal como está requiere 24 bytes de memoria de programa más que la versión de la pila.
|
|
|
|
en nuestro caso eso no es un gran problema, pero es una buena manera de evaluar nuestras prioridades: código súper legible pero probablemente ineficiente (como esta última subrutina), código súper optimizado pero probablemente ilegible (código de solo escritura, dicen), o algo en el medio.
|
|
|
|
# dibuja-fondo
|
|
|
|
ahora que tenemos estas bonitas subrutinas, podemos simplemente envolverlas en otra que cubrirá todo el fondo con nuestro tile elegido.
|
|
|
|
por ejemplo:
|
|
|
|
```
|
|
@dibuja-fondo ( -- )
|
|
#0000 #0010 ( x e `y` iniciales )
|
|
.Pantalla/ancho DEI2
|
|
.Pantalla/alto DEI2 #0010 SUB2
|
|
;tile-fondo
|
|
;dibuja-tiles JSR2
|
|
RTN
|
|
```
|
|
|
|
que podemos llamar simplemente desde nuestra subrutina de iniciación:
|
|
|
|
```
|
|
;dibuja-fondo JSR2
|
|
;dibuja-fondo JSR2
|
|
```
|
|
|
|
=> ./img/screenshot_uxn-background-full.png captura de pantalla mostrando la pantalla varvara cubierta de líneas diagonales.
|
|
|
|
¡bonito! te recomiendo que te tomes un pequeño descanso; ¡esto ha sido pesado!
|
|
|
|
# apoyo
|
|
|
|
si te ha gustado este tutorial y te ha resultado útil, considera compartirlo y darle tu {apoyo} :)
|