Revisión pausada del Día 5 y 6, y correciones breves de otros Días

This commit is contained in:
jota 2022-01-13 19:18:41 -03:00
parent cc10cd9624
commit bb7925f997
7 changed files with 153 additions and 158 deletions

View File

@ -184,7 +184,7 @@ podemos escribirlo de la siguiente manera:
( programa principal )
|0100
( establecer colores del sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
@ -322,7 +322,7 @@ el programa completo se vería de la siguiente manera:
( programa principal )
|0100
( establecer colores del sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
@ -661,7 +661,7 @@ además, 5, 'a' y 'f' en el nibble bajo dibujarán los píxeles que están "ence
( programa principal )
|0100
( establecer colores del sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
@ -703,7 +703,7 @@ el siguiente código dibujará nuestro sprite cuadrado con las 16 combinaciones
( programa principal )
|0100
( establecer colores de sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
@ -934,7 +934,7 @@ el siguiente código mostrará nuestro sprite en las 16 diferentes combinaciones
( programa principal )
|0100
( establecer colores de sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2

View File

@ -91,7 +91,7 @@ este utiliza el procedimiento de dibujo de sprites que probamos el día anterior
( programa principal )
|0100
( establecer colores del sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
@ -640,7 +640,7 @@ observa el uso de las máscaras AND, los saltos condicionales y algunas operacio
( programa principal )
|0100
( establecer colores del sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2

View File

@ -2,7 +2,7 @@
esta es la quinta sección del {tutorial de uxn}! aquí introducimos el dispositivo de ratón varvara para explorar más posibles interacciones, y cubrimos los elementos restantes de uxntal y uxn: la pila de retorno, el modo de retorno y el modo mantener.
también discutimos posibles estructuras para crear bucles y programas más complejos utilizando estos recursos.
¡también discutimos posibles estructuras para crear bucles y programas más complejos utilizando estos recursos!
# el dispositivo del ratón
@ -20,7 +20,7 @@ vemos este dispositivo definido en uxntal de la siguiente manera:
el byte de estado codifica el estado de activación/desactivación de hasta 8 botones del ratón; uno por bit.
contando de derecha a izquierda, el primer bit corresponde al primer botón del ratón, el segundo al segundo, y así sucesivamente.
contando de derecha a izquierda, el primer bit corresponde al primer botón del ratón, el segundo bit al segundo botón del ratón, y así sucesivamente.
normalmente, en un ratón de tres botones, el primer botón es el izquierdo, el segundo el del medio y el tercero el derecho.
@ -38,9 +38,9 @@ nota que al igual que el dispositivo controlador, este sistema nos permite compr
* 06 cuando se pulsan el segundo y el tercer botón
* 07 cuando se pulsan los tres botones
recuerda que podemos utilizar las máscaras AND, tal y como se introdujo en {tutorial de uxn día 3}, para aislar y evaluar por separado cualquiera de estos bits.
recuerda que podemos utilizar las máscaras AND, tal y como se introdujo en el {tutorial de uxn día 3}, para aislar y evaluar por separado cualquiera de estos bits.
## shorts de desplazamiento
## cortos de desplazamiento
el dispositivo del ratón tiene un par de cortos para indicar si el ratón se está desplazando.
@ -55,6 +55,7 @@ del mismo modo, despx indicará un desplazamiento horizontal
* 0001 cuando se desplaza hacia la derecha
* ffff cuando se desplaza hacia la izquierda
* 0000 cuando no se desplaza
dependiendo del dispositivo, los valores pueden ser mayores que 0001 o menores que ffff dependiendo de la velocidad de desplazamiento.
## vector ratón
@ -73,7 +74,7 @@ el vector del ratón se disparará en cualquiera de los siguientes eventos:
el siguiente es un ejemplo simple que ilustra el uso de los siguientes elementos:
* vector del ratón
* coordenadas x e y del ratón
* coordenadas x e `y` del ratón
* estado del ratón (pulsado o no pulsado)
combinado con un condicional y el dibujo de un sprite.
@ -92,7 +93,7 @@ dibuja nuestro cuadrado en la posición del ratón, cambiando su color cuando se
( init )
|0100
( establecer colores del sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
@ -164,7 +165,7 @@ este es un programa que logra dibujar el puntero en la pantalla
( init )
|0100
( establecer colores del sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
@ -200,7 +201,7 @@ BRK
@puntero_icn [ 80c0 e0f0 f8e0 1000 ]
```
nótese que dibuja el puntero en primer plano, y que utiliza 'a' en el nibble bajo del byte del sprite: esto implica que utilizará el color 2 para dibujar la forma del puntero, y dibujará con transparencia el resto del tile. ( ver dibujar sprites de 1bpp en {tutorial de uxn día 2} )
nótese que dibuja el puntero en primer plano, y que utiliza 'a' en el nibble bajo del byte del sprite: esto implica que utilizará el color 2 para dibujar la forma del puntero, y dibujará con transparencia el resto del tile. ( ver dibujar sprites de 1bpp en el {tutorial de uxn día 2} )
este modo de mezcla te permitiría dibujar cosas en el plano de fondo y que el puntero las cubra sólo con su forma, y no con todo el cuadrado del tile.
@ -216,7 +217,7 @@ eso es aun mas cierto si consideramos que solo estamos dibujando el puntero, y n
crear una macro para todo este código podría ser posible, pero también poco práctico debido a la cantidad de código.
¿tal vez podríamos tener un JMP a otra sección del programa, que al final tiene otro JMP para volver a la posición correspondiente en la subrutina en-raton?
¿tal vez podríamos tener un JMP a otra sección del programa, que al final tiene otro JMP para c vnm a la posición correspondiente en la subrutina en-raton?
de hecho, eso es casi lo que haremos, pero con un elemento adicional de uxn: ¡su pila de retorno!
@ -298,12 +299,12 @@ o un salto absoluto:
BRK
```
la cosa es que si queremos que ocurra algo más después de dibujar el puntero dentro de en-raton, no podemos volver atrás fácilmente.
el detalle esta en que si queremos que ocurra algo más después de dibujar el puntero dentro de en-raton, no podemos atrás fácilmente.
al final de nuestra subrutina dibuja-puntero, necesitaríamos "saltar hacia atrás" así
al final de nuestra subrutina dibuja-puntero, necesitaríamos "saltar hacia atrás" así:
```
;en-raton/volver JMP2
;en-raton/retornar JMP2
```
funcionaría, pero no es la mejor forma.
@ -338,12 +339,11 @@ y en el caso de un salto absoluto:
@en-raton ( -> )
;dibuja-puntero JSR2
( algo más aquí )
BRK
```
## volviendo
## retornando
JSR está empujando la "dirección de retorno" hacia la pila de retorno.
@ -379,11 +379,11 @@ LIT2r 0102 ADDr
ahora volvamos a nuestros saltos :)
## saltando al retorno
## saltando a retorno
como ya hemos discutido, JMP nos permitirá saltar incondicionalmente a la dirección dada en la parte superior de la pila (de trabajo).
JSR o JSR2 empujan hacia abajo en la pila de retorno la dirección absoluta de la siguiente instrucción, un short, para que eventualmente podamos retornar allí.
JSR o JSR2 empujan hacia abajo en la pila de retorno la dirección absoluta de la siguiente instrucción, un corto, para que eventualmente podamos retornar allí.
¿cómo podemos saltar incondicionalmente a esa dirección absoluta que está presente en la pila de retorno?
@ -391,19 +391,19 @@ JSR o JSR2 empujan hacia abajo en la pila de retorno la dirección absoluta de l
¡activando el modo de retorno en la instrucción JMP!
adicionalmente, como las direcciones empujadas por JSR son shorts, necesitamos activar el modo short también:
adicionalmente, como las direcciones empujadas por JSR son cortos, necesitamos activar el modo corto también:
```
JMP2r ( saltar a la dirección absoluta en la parte superior de la pila de retorno )
```
en muchos programas uxntales verás esta instrucción escrita como una macro, RTN ( volver o "return" )
en muchos programas uxntal verás esta instrucción escrita como una macro, RTN ( retornar o "return" ):
```
%RTN { JMP2r }
```
podemos terminar una subrutina usando esta macro para "volver" a la posición en el programa después del JSR correspondiente.
podemos terminar una subrutina usando esta macro para "retornar" a la posición en el programa después del JSR correspondiente.
## ejemplo completo usando subrutinas
@ -426,7 +426,7 @@ este es el programa hola-puntero.tal, pero utilizando dibuja-puntero como subrut
( init )
|0100
( establecer colores del sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
@ -440,7 +440,7 @@ este es el programa hola-puntero.tal, pero utilizando dibuja-puntero como subrut
BRK
@en-raton ( -> )
;dibujar-puntero JSR2 ( o ,dibujar-puntero JSR )
;dibuja-puntero JSR2 ( o ,dibuja-puntero JSR )
( algo más )
BRK
@ -486,9 +486,9 @@ puede haber otros casos en los que el uso de "variables" tendría un sentido má
habiendo introducido la pila de retorno y el modo de retorno, se nos abre otro mundo de posibilidades: también podemos utilizar la pila de retorno como una pila adicional y temporal, para almacenar algunos valores mientras operamos con otros.
para lograr esto, uxn tiene una instrucción llamada STH, almacenar o "stash".
para lograr esto, uxn tiene una instrucción llamada STH, "stash" o almacenar.
¡esta es la última instrucción de uxn que teníamos que cubrir en esta serie de tutoriales! :)
¡esta es la última instrucción de uxn que teníamos en mente cubrir en esta serie de tutoriales! :)
## STH
@ -502,20 +502,20 @@ y, como habrás previsto, en el modo corto esta instrucción opera moviendo cort
el siguiente es un ejemplo de subrutina que muestra algunas posibilidades de la pila y el modo de retorno.
se trata de una subrutina que dibuja una línea horizontal de una longitud dada (de 1 a 255 píxeles, es decir, utilizando un byte), partiendo de una coordenada x dada (corto) y utilizando una coordenada y dada (corto).
se trata de una subrutina que dibuja una línea horizontal de una longitud dada (de 1 a 255 píxeles, es decir, utilizando un byte), partiendo de una coordenada x dada (corto) y utilizando una coordenada `y` dada (corto).
estos parámetros se dan como argumentos en la pila de trabajo.
la subrutina utiliza la pila de retorno para "almacenar" uno de estos argumentos mientras trabaja con los otros.
además, tiene un bucle de trabajo! escrito en una de las varias formas de implementarlo :)
además, ¡tiene un bucle de trabajo! escrito en una de las varias formas de implementarlo :)
el estado de las pilas de trabajo (pt) y de retorno (pr) se muestra en los comentarios después de casi cada paso. la parte superior de las pilas se encuentra a su derecha.
un signo de intercalación (^) después de un nombre de valor indica que corresponde a un cortocircuito.
un signo de intercalación (^) después de un nombre de valor indica que corresponde a un corto.
```
@dibujar-linea-horizontal ( x^ y^ longitud -- )
@dibuja-linea-horizontal ( x^ y^ longitud -- )
( inicio )
( pt: x^ y^ longitud / pr: )
@ -558,13 +558,13 @@ RTN
### llamando
para llamar a la subrutina, podrías hacer algo como lo siguiente
para llamar a la subrutina, podrías hacer algo como lo siguiente:
```
#0008 ( empujar x inicial )
.Pantalla/altura DEI2 MITAD2 ( empujar y )
#ff ( empujar longitud de la línea )
;dibujar-linea-horizontal JSR2 ( llamar subrutina )
;dibuja-linea-horizontal JSR2 ( llamar subrutina )
```
### notas
@ -578,13 +578,13 @@ sin embargo, muestra cómo podemos usar estas instrucciones para tener una pila
* hacer que la subrutina dibuje una línea hecha de sprites en lugar de píxeles individuales
* modificar la subrutina para que pueda recibir como argumento (en la pila de trabajo) el color de los sprites o píxeles
* modificar la subrutina para que pueda recibir como argumento (en la pila de trabajo) la dirección del sprite a dibujar
* reescribir la subrutina para que utilice una longitud de corto para la línea, en lugar de un byte.
* reescribir la subrutina para que utilice una longitud de pequeño tamaño para la línea, en lugar de un byte.
# el modo mantener
el último elemento básico de uxntal que nos queda por cubrir es su tercer modo para las instrucciones: el modo mantener o "keep".
el modo mantener se codifica en el 8º bit de un byte de instrucción, contando de derecha a izquierda.
el modo mantener se codifica en el 8vo bit de un byte de instrucción, contando de derecha a izquierda.
en uxntal, indicamos que queremos activar esta bandera añadiendo la letra 'k' al final de un mnemónico de instrucción.
@ -627,7 +627,7 @@ dije entonces que había un conjunto más optimizado, y que lo discutiríamos m
¡ahora es ese momento!
en primer lugar, analicemos lo que ocurre con MOD. está calculando lo que se escribiría en notación infija de la siguiente manera, suponiendo que la barra (/) indica una división entera
en primer lugar, analicemos lo que ocurre con MOD. está calculando lo que se escribiría en notación infija de la siguiente manera, suponiendo que la barra (/) indica una división entera:
```
a - ( a/b )*b
@ -643,10 +643,10 @@ en nuestra macro original, lo que ocurre es lo siguiente:
```
#07 #03 ( pt: 07 03 )
DUP2 ( pt: 07 03 07 03 )
DIV ( pt: 07 03 02 )
MUL ( pt: 07 06 )
SUB ( pt: 01 )
DUP2 ( pt: 07 03 07 03 )
DIV ( pt: 07 03 02 )
MUL ( pt: 07 06 )
SUB ( pt: 01 )
```
¿ves la posibilidad de introducir el modo mantener?
@ -661,9 +661,9 @@ DUP2 DIV es equivalente a... ¡DIVk! ¡una división que no pierde sus operandos
```
#07 #03 ( pt: 07 03 )
DIVk ( pt: 07 03 02 )
MUL ( pt: 07 06 )
SUB ( pt: 01 )
DIVk ( pt: 07 03 02 )
MUL ( pt: 07 06 )
SUB ( pt: 01 )
```
¡de esta manera, nuestra macro puede tener un byte menos!
@ -679,7 +679,7 @@ podemos generalizar este comportamiento para el modo corto, y obtener el conjunt
el modo mantener puede ser útil cuando hacemos comparaciones y no queremos perder los valores originales.
por ejemplo, en nuestra subrutina dibujar-línea-horizontal, teníamos el siguiente conjunto de líneas de código:
por ejemplo, en nuestra subrutina dibuja-línea-horizontal, teníamos el siguiente conjunto de líneas de código:
```
( duplicar longitud y el conteo, comparar, y saltar )
@ -754,7 +754,7 @@ ten en cuenta que puedes cambiar el vector de un dispositivo durante el tiempo d
básicamente, las puertas para las aplicaciones visuales interactivas en el ordenador varvara están completamente abiertas ahora para ti :)
¿crearás juegos? ¿pequeñas aplicaciones, útiles o no? ¿un instrumento para visuales en vivo? ¿programas dirigidos a dispositivos manuales específicos?
¿crearás juegos? ¿pequeñas aplicaciones, útiles o no? ¿un instrumento para visuales en vivo? ¿programas dirigidos a dispositivos de mano específicos?
algunas cosas pueden parecer difíciles de construir, pero afortunadamente, por ahora no hay nada más en el funcionamiento de la máquina que no hayamos cubierto ya.
@ -764,7 +764,7 @@ puedes ir poco a poco, paso a paso, practicando tu manejo de la pila y ejercitan
# instrucciones del día 5
estas son las instrucciones uxntales que hemos discutido hoy! con estas, las hemos cubierto todas!
¡estas son las instrucciones uxntal que hemos discutido hoy! ¡con estas, las hemos cubierto todas!
* JSR: salta incondicionalmente a la dirección de la pila de trabajo, empujando hacia abajo en la pila de retorno la dirección de la siguiente instrucción en memoria
* STH: toma un valor de la pila de trabajo y lo empuja hacia abajo en la pila de retorno. en el modo de retorno, hace lo contrario.
@ -779,8 +779,8 @@ además de utilizar estrategias y fragmentos de código anteriores, cubrimos est
primero, te invito a tomar un descanso!
después, sigue explorando y comparte tus descubrimientos!
después, ¡sigue explorando y comparte tus descubrimientos!
# apoyo
si te ha gustado este tutorial y te ha resultado útil, considera compartirlo y darle tu {apoyo} :)
si te ha gustado este tutorial y te ha resultado útil, considera compartirlo y darle tu {apoyo} :)

View File

@ -22,7 +22,7 @@ en el {tutorial de uxn día 5} hablamos de una forma de crear un bucle para repe
aquí ampliaremos ese procedimiento para que también se repita verticalmente en toda la pantalla.
## configuración
## configurando
empecemos con el siguiente programa como plantilla. incluye los datos para un sprite de 1bpp que consiste en líneas diagonales.
@ -107,7 +107,7 @@ integrando todo ello, podríamos obtener:
nótese el uso de DUP2 para evitar releer el valor de x.
esto debería funcionar ahora! pero vamos a discutir una forma más agradable de hacerlo :)
¡esto debería funcionar ahora! pero vamos a discutir una forma más agradable de hacerlo :)
### una segunda versión, usando la pila
@ -116,7 +116,7 @@ en lugar de leer el ancho de pantalla y la coordenada x cada vez, podríamos usa
después de establecer la dirección del tile, podemos empujar nuestro límite (el ancho de la pantalla) y el valor inicial hacia abajo en la pila:
```
.Pantalla/ancho DEI2 #0000 ( establecer límite y x inicial )
.Pantalla/ancho DEI2 #0000 ( establecer límite y `x` inicial )
```
usaremos ese valor en la parte superior de la pila como coordenada x.
@ -141,14 +141,14 @@ GTH2k ( ¿es ese ancho mayor que x?, o también, ¿es x menor que el ancho? )
,&bucle-x JCN ( salta si x es menor que el límite )
```
cuando terminamos el bucle, tenemos que hacer POP de ambos valores.
cuando terminamos el bucle, tenemos que hacer POP a ambos valores.
usando esta estrategia, obtendríamos el siguiente bucle:
```
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
.Pantalla/ancho DEI2 #0000 ( empujar límite y x inicial )
.Pantalla/ancho DEI2 #0000 ( empujar límite y `x` inicial )
&bucle-x
DUP2 .Pantalla/x DEO2 ( establecer coordenada x )
@ -192,7 +192,7 @@ lo siguiente muestra nuestro programa en contexto, llenando completamente la pri
( dibujar fondo )
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
.Pantalla/ancho DEI2 #0000 ( establecer límite y x inicial )
.Pantalla/ancho DEI2 #0000 ( establecer límite y `x` inicial )
&bucle-x
DUP2 .Pantalla/x DEO2 ( fijar coordenada x )
#03 .Pantalla/sprite DEO ( dibujar sprite de 1bpp con color 3 y 0 )
@ -207,7 +207,7 @@ BRK
## repitiendo 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?
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:
@ -223,9 +223,9 @@ para ilustrar un pequeño cambio, supongamos que queremos tener un margen en la
%MARGEN-PARED { #0010 } ( margen en la parte superior e inferior )
```
nuestra y inicial sería MARGEN-PARED, y nuestro límite sería la altura de la pantalla menos MARGEN-PARED.
nuestra `y` inicial sería MARGEN-PARED, y nuestro límite sería la altura de la pantalla menos MARGEN-PARED.
podemos usar la misma estructura que antes, pero usando y:
podemos usar la misma estructura que antes, pero usando `y`:
```
;tile-fondo .Pantalla/direc DEO2 ( establecer la dirección del tile )
@ -238,8 +238,8 @@ MARGEN-PARED ( establecer `y` inicial )
( - dibujar fila aquí - )
#0008 ADD2 ( )
GTH2k ( ¿es ese límite mayor que y? o también, ¿es `y` menor que el límite? )
#0008 ADD2 ( incrementa `y` )
GTH2k ( ¿es ese límite mayor que `y`? o también, ¿es `y` menor que el límite? )
,&bucle-y JCN ( salta si `y` es menor que el límite )
POP2 POP2 ( eliminar `y` y el límite )
```
@ -257,7 +257,7 @@ MARGEN-PARED ( establecer `y` inicial )
DUP2 .Pantalla/y DEO2 ( establecer coordenada y )
( dibujar fila )
.Pantalla/ancho DEI2 #0000 ( establecer límite y x inicial )
.Pantalla/ancho DEI2 #0000 ( establecer límite y `x` inicial )
&bucle-x
DUP2 .Pantalla/x DEO2 ( fijar coordenada x )
@ -269,7 +269,7 @@ MARGEN-PARED ( establecer `y` inicial )
,&bucle-x JCN ( salta si x es menor que el límite )
POP2 POP2 ( eliminar x y el límite )
#0008 ADD2 ( )
#0008 ADD2 ( incrementar y )
GTH2k ( ¿es ese límite mayor que y? o también, ¿es `y` menor que el límite? )
,&bucle-y JCN ( salta si `y` es menor que el límite )
POP2 POP2 ( eliminar `y` y el límite )
@ -291,7 +291,7 @@ ahora podemos envolver estos bucles anidados dentro de una subrutina:
DUP2 .Pantalla/y DEO2 ( establecer coordenada y )
( dibujar fila )
.Pantalla/ancho DEI2 #0000 ( establecer límite y x inicial )
.Pantalla/ancho DEI2 #0000 ( establecer límite y `x` inicial )
&bucle-x
DUP2 .Pantalla/x DEO2 ( establecer coordenada x )
@ -303,20 +303,20 @@ ahora podemos envolver estos bucles anidados dentro de una subrutina:
,&bucle-x JCN ( salta si x es menor que el límite )
POP2 POP2 ( eliminar x y el límite )
#0008 ADD2 ( )
GTH2k ( ¿es ese límite mayor que y? o también, ¿es `y` menor que el límite? )
#0008 ADD2 ( incrementar y )
GTH2k ( ¿es ese límite mayor que `y`? o también, ¿es `y` menor que el límite? )
,&bucle-y JCN ( salta si `y` es menor que el límite )
POP2 POP2 ( eliminar `y` y el límite )
RTN
```
que podemos llamar simplemente desde nuestra subrutina de inicialización:
que podemos llamar simplemente desde nuestra subrutina de iniciación:
```
;dibuja-fondo JSR2
```
=> ./img/screenshot_uxn-background-full.png captura de pantalla que muestra la pantalla de varvara cubierta de líneas diagonales excepto por un margen en la parte superior e inferior.
=> ./img/screenshot_uxn-background-full.png captura de pantalla que muestra la pantalla varvara cubierta de líneas diagonales excepto por un margen en la parte superior e inferior.
¡lindo!
@ -326,11 +326,11 @@ se habla de varias posibilidades para usar uxntal de esa manera abstracta: yo di
# las palas
podemos pensar en las dos palas del juego como dos rectángulos, cada uno con sus propias coordenadas x e y, y ambos con la misma anchura y altura.
podemos pensar en las dos palas del juego como dos rectángulos, cada uno con sus propias coordenadas x e `y`, y ambos con la misma anchura y altura.
la coordenada x de cada pala puede ser constante, y la coordenada y debe ser de seguro una variable.
la coordenada x de cada pala puede ser constante, y la coordenada `y` debe ser de seguro una variable.
en esta parte veremos como dibujar las palas en base a estos parámetros, y también recapitularemos como cambiar sus coordenadas `y` con el controlador.
en esta parte veremos cómo dibujar las palas en base a estos parámetros, y también recapitularemos cómo cambiar sus coordenadas `y` con el controlador.
## dibujar las palas multi-tile
@ -352,12 +352,12 @@ los datos resultantes son los siguientes:
```
@pala
&tile0 [ 3f 7f e7 c3 c3 c3 c3 00 00 18 3c 3c 3c 3c 3c ]
&tile1 [ fc fe ff ff ff ff ff 00 00 00 00 06 06 ]
&tile2 [ c3 c3 c3 e7 ff ff ff 3c 3c 3c 18 00 00 00 ]
&tile3 [ ff ff ff ff ff ff 06 06 06 06 06 06 ]
&tile4 [ ff ff ff ff ff 7f 3f 00 00 00 00 00 00 ]
&tile5 [ ff ff ff ff ff fe fc 06 06 06 06 1e 3c 00 ]
&tile0 [ 3f 7f e7 c3 c3 c3 c3 00 00 18 3c 3c 3c 3c 3c ]
&tile1 [ fc fe ff ff ff ff ff 00 00 00 00 00 00 06 06 ]
&tile2 [ c3 c3 c3 e7 ff ff ff 3c 3c 3c 3c 18 00 00 00 ]
&tile3 [ ff ff ff ff ff ff 06 06 06 06 06 06 06 06 06 ]
&tile4 [ ff ff ff ff ff 7f 3f 00 00 00 00 00 00 00 00 ]
&tile5 [ ff ff ff ff ff fe fc 06 06 06 06 06 1e 3c 00 ]
```
se pueden obtener estos números leyendo la notación hexadecimal en nasu en la parte superior derecha, primero la columna de la izquierda y luego la de la derecha, o utilizando una herramienta como hexdump con el archivo chr correspondiente:
@ -372,7 +372,7 @@ he dibujado el sprite usando el modo de mezcla 85 como indica nasu, pero lo camb
construyamos una subrutina que dibuje las 6 fichas de la pala en el orden correspondiente.
podríamos tener la subrutina recibiendo como argumentos la posición x e y de su esquina superior izquierda:
podríamos tener la subrutina recibiendo como argumentos la posición x e `y` de su esquina superior izquierda:
```
@dibuja-pala ( x^ y^ -- )
@ -386,9 +386,9 @@ pero añadamos también un byte de color para el byte del sprite:
recordemos 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)
por un lado esta segunda versión nos permitiría cambiar de color cuando, por ejemplo, le demos a la pelota, pero lo más importante es que esto nos permitirá limpiar la pala antes de moverla, como hemos hecho en días anteriores.
por un lado esta segunda versión nos permitiría cambiar de color cuando, por ejemplo, le demos a la pelota, pero lo más importante es que esto nos permitirá borrar la pala antes de moverla, como hemos hecho en días anteriores.
en principio la subrutina debería ser sencilla: tenemos que establecer las coordenadas x e y de cada una de las fichas, relativas a las coordenadas x e y dadas, y dibujarlas con el color dado.
en principio la subrutina debería ser directa: tenemos que establecer las coordenadas x e `y` de cada una de las fichas, relativas a las coordenadas x e `y` dadas, y dibujarlas con el color dado.
hay muchas maneras de hacerlo, dependiendo del gusto.
@ -404,15 +404,15 @@ podríamos por ejemplo dibujar los tiles en el siguiente orden, con las siguient
o podríamos hacerlo de forma más tradicional:
* dibujar el tile 0, luego añadir 8 a x
* dibujar el tile 1, luego restar 8 a x, y añadir 8 a y
* dibujar el tile 1, luego restar 8 a x, y añadir 8 a `y`
* dibujar el tile 2, luego añadir 8 a x
* dibujar el tile 3, luego restar 8 a x, y añadir 8 a y
* dibujar el tile 3, luego restar 8 a x, y añadir 8 a `y`
* dibujar el tile 4, luego añadir 8 a x
* dibujar el tile 5
en lugar de restar podríamos recuperar x de la pila de retorno, o de una variable relativa.
una posible ventaja de ir en orden es que podemos incrementar la dirección del sprite en 10 (16 en decimal) para llegar a la dirección del siguiente tile. para esto, y/o para los cambios de coordenadas, podemos aprovechar el auto byte de pantalla.
una posible ventaja de ir en orden es que podemos incrementar la dirección del sprite por 10 (16 en decimal) para llegar a la dirección del siguiente tile. para esto, y/o para los cambios de coordenadas, podemos aprovechar el byte auto de la pantalla.
sin embargo, en este caso voy a ir por la primera opción, y voy a establecer manualmente la dirección para cada tile.
@ -486,13 +486,13 @@ es posible considerar formas más eficientes de dibujarla. por ejemplo, podríam
@dibuja-sprite ( x^ y^ ancho alto direc* color )
```
crear eso podría ser un buen ejercicio para probar! en este caso me quedaré con el método manual.
crear eso podría ser un buen ejercicio para probar! en este caso me mantendré con el método manual.
lo bueno de que este proceso esté en una subrutina es que podemos "olvidarnos" de su funcionamiento interno y simplemente usarlo :)
## variables y constantes para las palas
reservemos un espacio en la página cero para las coordenadas x e y de cada pala.
reservemos un espacio en la página cero para las coordenadas x e `y` de cada pala.
```
( página cero )
@ -653,7 +653,7 @@ para borrarlos, podemos hacer lo mismo pero usando un byte del sprite correspond
donde COLOR-BORRAR en este caso sería:
```
%COLOR-BORRAR { #40 } ( limpiar el sprite del primer plano )
%COLOR-BORRAR { #40 } ( borrar el sprite del primer plano )
```
¡este es un buen recordatorio para revisar las tablas de los bytes de los sprites en el {tutorial de uxn día 2}!
@ -713,7 +713,7 @@ RTN
### procedimiento completo
integrando todo, nuestra subrutina en el marco se vería como lo siguiente.
integrando todo, nuestra subrutina en-cuadro se vería como lo siguiente.
¡ahora somos capaces de mover nuestras palas!
@ -740,7 +740,7 @@ te invito a que modifiques la subrutina actualiza-palas para que haya un límite
¡ahora vamos a poner la pelota en marcha!
aquí trabajaremos de nuevo con un sprite multi-tile dibujado en relación a las variables x e y para su esquina superior izquierda.
aquí trabajaremos de nuevo con un sprite multi-tile dibujado en relación a las variables x e `y` para su esquina superior izquierda.
adicionalmente, usaremos esta sección para hablar de las estrategias para la detección de colisiones, con las paredes y las palas.
@ -757,10 +757,10 @@ estos son sus datos:
```
@pelota-sprite
&tile0 [ 03 0f 1f 39 70 70 f9 ff 00 00 00 06 0f 0f 06 00 ]
&tile1 [ c0 f0 f8 fc fe ff ff 00 00 00 08 0c 06 06 ]
&tile2 [ ff ff 7f 7f 3f 1f 0f 03 00 00 00 00 18 0f 01 00 ]
&tile3 [ ff ff fe fc f8 f0 c0 06 06 0c 1c 38 f0 c0 00 ]
&tile0 [ 03 0f 1f 39 70 70 f9 ff 00 00 00 06 0f 0f 06 00 ]
&tile1 [ c0 f0 f8 fc fe fe ff ff 00 00 00 00 08 0c 06 06 ]
&tile2 [ ff ff 7f 7f 3f 1f 0f 03 00 00 00 00 18 0f 01 00 ]
&tile3 [ ff ff fe fe fc f8 f0 c0 06 06 0c 1c 38 f0 c0 00 ]
```
podemos definir un par de macros para referirse a sus parámetros:
@ -796,13 +796,13 @@ MITAD2
las coordenadas están listas, así que ahora podemos usarlas dentro de nuestra subrutina.
hagamos que la subrutina reciba el color como argumento, para poder limpiar la pelota como hacemos con las palas:
hagamos que la subrutina reciba el color como argumento, para poder borrar la pelota como hacemos con las palas:
```
@dibuja-pelota ( color -- )
( fijar x e y iniciales )
( fijar x e `y` iniciales )
.pelota/x LDZ2 .Pantalla/x DEO2
.pelota/y LDZ2 . pantalla/y DEO2
.pelota/y LDZ2 .Pantalla/y DEO2
( dibujar tile 0 )
;pelota-sprite/tile0 .Pantalla/direc DEO2
@ -845,11 +845,11 @@ COLOR-PELOTA ;dibuja-pelota JSR2
para el movimiento de la pelota, seguiremos la misma estructura que antes:
* despejar la pelota en la posición actual
* borrar la pelota en la posición actual
* actualizar su posición
* dibujar la pelota en la nueva posición
se vería algo como lo siguiente, y podría sentarse a lo largo de los procedimientos equivalentes para las palas dentro de la subrutina en-cuadro:
se vería algo como lo siguiente, y podría situarse a lo largo de los procedimientos equivalentes para las palas dentro de la subrutina en-cuadro:`
```
( dentro de en-cuadro )
@ -869,13 +869,13 @@ ahora vamos a discutir cómo construir esa subrutina actualiza-pelota :)
además de nuestras variables para llevar la cuenta de la posición de la pelota, deberíamos poder llevar la cuenta de la dirección por-eje en la que se mueve.
un enfoque podría ser tener una bandera para cada x e y que indique si debemos incrementarlos o disminuirlos.
un enfoque podría ser tener una bandera para cada x e `y` que indique si debemos incrementarlos o decrementarlos.
otro enfoque podría ser tener una variable de velocidad para cada x e y, que se cambia de acuerdo a la dirección que queremos que la pelota vaya.
otro enfoque podría ser tener una variable de velocidad para cada x e `y`, que se cambia de acuerdo a la dirección que queremos que la pelota vaya.
utilizaremos este último enfoque con la velocidad, ya que nos ayudará a discutir algunas ventajas de la aritmética de enteros sin signo.
incluimos estas variables en nuestra página cero, complementando las x e y que ya teníamos:
incluimos estas variables en nuestra página cero, complementando las x e `y` que ya teníamos:
```
@pelota [ &x $2 &y $2 &vel-x $2 &vel-y $2 ]
@ -883,7 +883,7 @@ incluimos estas variables en nuestra página cero, complementando las x e y que
### diferentes direcciones
si, por ejemplo, iniciamos vel-x con 1
si, por ejemplo, iniciamos vel-x con 1:
```
#0001 .pelota/vel-x STZ2
@ -895,7 +895,7 @@ podemos hacer que la pelota se mueva hacia la derecha haciendo:
( dentro de actualiza-pelota )
.pelota/vel-x LDZ2 ( obtener vel-x )
.pelota/x LDZ2 ( obtener x )
ADD2 ( sumar ambas cosas )
ADD2 ( sumar ambas )
.pelota/x STZ2 ( almacenar nueva x )
```
@ -952,11 +952,11 @@ para obtener otros "números negativos", observemos lo siguiente: si restamos 1
1 0000 0000 0000 0000: 0000
```
obtenemos 0! fffe funciona efectivamente como "-2"!
¡obtenemos 0! ¡fffe funciona efectivamente como "-2"!
podríamos continuar así obteniendo más y más números "negativos" que funcionan gracias al tamaño restringido de la memoria del ordenador.
volviendo a nuestro código, si inicializamos nuestra velocidad con:
volviendo a nuestro código, si iniciamos nuestra velocidad con:
```
#ffff .pelota/vel-x STZ2
@ -968,7 +968,7 @@ y luego usamos exactamente el mismo código para actualizar la posición:
( dentro de actualiza-pelota )
.pelota/vel-x LDZ2 ( obtener vel-x )
.pelota/x LDZ2 ( obtener x )
ADD2 ( sumar ambas cosas )
ADD2 ( sumar ambas )
.pelota/x STZ2 ( almacenar nueva x )
```
@ -983,18 +983,18 @@ podría tener sentido establecer estos valores como macros:
### implementando el movimiento de la pelota
basándonos en lo que acabamos de discutir, podemos empezar nuestra subrutina de actualización de la pelota con lo siguiente:
basándonos en lo que acabamos de discutir, podemos empezar nuestra subrutina actualiza-pelota con lo siguiente:
```
@actualiza-pelota ( -- )
( obtener velocidad-x y x )
( obtener velocidad-x y `x` )
.pelota/vel-x LDZ2 .pelota/x LDZ2
ADD2 ( sumar ambas cosas )
.pelota/x STZ2 ( guarda la nueva x )
( obtener velocidad-y e y )
( obtener velocidad-y e `y` )
.pelota/vel-y LDZ2 .pelota/y LDZ2
ADD2 ( sumar ambas cosas )
ADD2 ( sumar ambas )
.pelota/y STZ2 ( almacenar nueva y )
RTN
```
@ -1018,13 +1018,13 @@ woohoo! se mueve, pero de momento sale volando :)
## colisiones con las paredes
hemos definido la forma general de actualizar la posición de la pelota dada su velocidad en x e y.
hemos definido la forma general de actualizar la posición de la pelota dada su velocidad en x e `y`.
¡ahora veamos cómo implementar el clásico "rebote"!
primero, empecemos con las paredes en la parte superior e inferior de la pantalla; recordando que hay un margen (MARGEN-PARED) entre el borde real de la pantalla, y las paredes.
para realizar estas detecciones de colisión, tendríamos que comprobar sólo la coordenada y de la pelota.
para realizar estas detecciones de colisión, tendríamos que comprobar sólo la coordenada `y` de la pelota.
como siempre, hay muchas maneras de lograr esto. una podría ser:
@ -1046,7 +1046,7 @@ pista: mira de nuevo las máscaras a nivel de bit discutidas en el {tutorial de
### pared superior
si la pelota golpea la pared superior, significa que su coordenada y es menor que la coordenada y de la pared.
si la pelota golpea la pared superior, significa que su coordenada `y` es menor que la coordenada `y` de la pared.
considerando que hay un margen en la parte superior, podemos hacer esta comprobación de la siguiente manera:
@ -1069,12 +1069,12 @@ considerando que hay un margen en la parte superior, podemos hacer esta comproba
aquí el procedimiento sería similar, pero considerando el tamaño de la pelota.
queremos saber si la coordenada y, más el tamaño de la pelota, es mayor que la coordenada y de la pared inferior.
queremos saber si la coordenada `y`, más el tamaño de la pelota, es mayor que la coordenada `y` de la pared inferior.
la coordenada y de la pared inferior sería la altura de la pantalla, menos el margen de la pared:
la coordenada `y` de la pared inferior sería la altura de la pantalla, menos el margen de la pared:
```
(actualización del interior de la pelota )
(dentro de actualiza-pelota )
&verif-pared-inf
.pelota/y LDZ2 TAM-PELOTA ADD2 ( y + tamaño de la pelota )
.Pantalla/alto DEI2
@ -1088,9 +1088,9 @@ la coordenada y de la pared inferior sería la altura de la pantalla, menos el m
&continuar
```
### código de actualización de la pelota hasta ahora
### actualiza-pelota hasta ahora
nuestra subrutina de actualización de la pelota tiene el siguiente aspecto ahora mismo:
nuestra subrutina actualiza-pelota tiene el siguiente aspecto hasta el momento:
```
@actualiza-pelota ( -- )
@ -1101,7 +1101,7 @@ nuestra subrutina de actualización de la pelota tiene el siguiente aspecto ahor
.pelota/x STZ2 ( guardar la nueva x )
( actualizar y )
( obtener velocidad-y e y )
( obtener velocidad-y e `y` )
.pelota/vel-y LDZ2 .pelota/y LDZ2
ADD2 ( sumar ambas cosas )
.pelota/y STZ2 ( almacenar nueva y )
@ -1159,12 +1159,12 @@ para ello, podemos comprobar si x es menor que la suma del margen y el ancho de
&verif-pala-der
```
una vez que sabemos que eso es cierto, podemos ver si la pelota está dentro del alcance vertical de la pala; la coordenada y de la pelota tiene que estar dentro de un cierto rango relativo a la coordenada y de la pelota.
una vez que sabemos que eso es cierto, podemos ver si la pelota está dentro del alcance vertical de la pala; la coordenada `y` de la pelota tiene que estar dentro de un cierto rango relativo a la coordenada `y` de la pelota.
en especifico, si queremos que la pelota pueda rebotar cuando cualquier parte de la pelota golpee cualquier parte de la pala, la coordenada y de la pelota tiene que ser:
en especifico, si queremos que la pelota pueda rebotar cuando cualquier parte de la pelota golpee cualquier parte de la pala, la coordenada `y` de la pelota tiene que ser:
* mayor que la coordenada y de la pala menos la altura AND de la pelota
* menor que la coordenada y de la pala más la altura de la pala
* mayor que la coordenada `y` de la pala menos la altura AND de la pelota
* menor que la coordenada `y` de la pala más la altura de la pala
si esas dos condiciones se cumplen, entonces podemos establecer una velocidad positiva para x:
@ -1219,7 +1219,7 @@ todo el código x-en-izquierda terminaría pareciendo:
&verif-pala-der
```
fin sería una etiqueta al final de la subrutina, y reset es una subrutina de la que hablaremos más adelante.
"fin" sería una etiqueta al final de la subrutina, y "reset" es una subrutina de la cuálf hablaremos más adelante.
esta aproximación de comparar con 0000 es la más fácil, pero ten en cuenta que podría no funcionar si cambias la velocidad de la pelota: podría ocurrir que cruzara la pared pero con una coordenada x que nunca fuera igual a 0.
@ -1237,7 +1237,7 @@ para la pala derecha haremos lo mismo que arriba, pero cambiando las comparacion
&verif-pala-der
.pelota/x LDZ2 TAM-PELOTA ADD2 ( pelota-x + tamaño-pelota )
.Pantalla/ancho DEI2 MARGEN SUB2 ANCHO-PALA SUB2
GTH2 ( ¿es la coordenada derecha de la pelota mayor que el ancho de la pantalla - margen - ancho de la pala? )
GTH2 ( ¿es la coordenada derecha de la pelota mayor que el ancho de la pantalla - margen - ancho-palaf? )
,&x-en-derecha JCN
&fin JMP
@ -1267,7 +1267,7 @@ para la pala derecha haremos lo mismo que arriba, pero cambiando las comparacion
RTN
```
¡eso debería ser todo! ¡puedes encontrar la subrutina de actualización de la pelota completa a continuación!
¡eso debería ser todo! ¡puedes encontrar la subrutina actualiza-pelota completa a continuación!
¡para poder ensamblar y ejecutar el juego, vamos a definir la subrutina reset!
@ -1285,7 +1285,7 @@ aquí solo definiremos una subrutina de reinicio o "reset" que devuelva la pelot
RTN
```
sería interesante tener algún mecanismo para cambiar también la velocidad: tal vez basado en el conteo de cuadros, en la posición de las palas, o cualquier otra cosa que elijas.
sería interesante tener algún mecanismo para también cambiar la velocidad: tal vez basado en el cuentafotogramas, en la posición de las palas, o cualquier otra cosa que elijas.
# el programa completo
@ -1331,7 +1331,7 @@ aquí está todo el código que hemos escrito hoy:
( configuración )
|0100
@configuracion ( -> )
( establecer colores del sistema )
( establecer los colores del sistema )
#2ce9 .Sistema/r DEO2
#01c0 .Sistema/g DEO2
#2ce5 .Sistema/b DEO2
@ -1340,7 +1340,7 @@ aquí está todo el código que hemos escrito hoy:
;en-cuadro .Pantalla/vector DEO2
( dibujar fondo )
;dibujar fondo JSR2
;dibuja-fondo JSR2
( iniciar palas )
MARGEN .izquierda/x STZ2
@ -1389,7 +1389,6 @@ BRK
BRK
```
## reset
```
@ -1413,7 +1412,7 @@ RTN
ADD2 ( sumar ambas cosas )
.pelota/x STZ2 ( guardar la nueva x )
( obtener velocidad-y e y )
( obtener velocidad-y e `y` )
.pelota/vel-y LDZ2 .pelota/y LDZ2 ( obtener y )
ADD2 ( sumar ambas cosas )
.pelota/y STZ2 ( guardar la nueva y )
@ -1428,7 +1427,7 @@ RTN
&establecer-vel-pos
PELOTA-VEL-POS .pelota/vel-y STZ2
&continuar JMP
,&continuar JMP
&verif-pared-inf
.pelota/y LDZ2 TAM-PELOTA ADD2 ( y + tamaño-pelota )
@ -1474,7 +1473,7 @@ RTN
.Pantalla/ancho DEI2 MARGEN SUB2 ANCHO-PALA SUB2
GTH2 ( ¿es pelota-x + tamaño-pelota mayor que la anchura de la pantalla - margen - ancho-pala? )
,&x-en-derecha JCN
&fin JMP
,&fin JMP
&x-en-derecha
.pelota/y LDZ2 DUP2
@ -1505,7 +1504,7 @@ RTN
```
@dibuja-pelota ( color -- )
( fijar x e y iniciales )
( fijar x e `y` iniciales )
.pelota/x LDZ2 .Pantalla/x DEO2
.pelota/y LDZ2 .Pantalla/y DEO2
@ -1549,9 +1548,9 @@ RTN
DUP #10 AND ( comprobar bit para arriba )
,&izquierda-arriba JCN
DUP #20 AND ( comprobar bit para abajo )
&izquierda-abajo JCN
,&izquierda-abajo JCN
&derecha JMP ( salta si no se ha pulsado ninguno de los dos )
,&derecha JMP ( salta si no se ha pulsado ninguno de los dos )
&izquierda-arriba
.izquierda/y LDZ2 VEL-PALA SUB2 .izquierda/y STZ2
@ -1565,9 +1564,9 @@ RTN
DUP #01 AND ( comprobar bit para A )
,&derecha-arriba JCN
DUP #02 AND ( comprobar bit para B )
&derecha-abajo JCN
,&derecha-abajo JCN
&fin JMP ( salta si no se ha pulsado ninguno de los dos )
,&fin JMP ( salta si no se ha pulsado ninguno de los dos )
&derecha-arriba
.derecha/y LDZ2 VEL-PALA SUB2 .derecha/y STZ2
@ -1646,14 +1645,14 @@ RTN
DUP2 .Pantalla/y DEO2 ( establecer coordenada `y` )
( dibujar fila )
.Pantalla/ancho DEI2 #0000 ( establecer límite `y` x inicial )
.Pantalla/ancho DEI2 #0000 ( establecer límite y `x` inicial )
&bucle-x
DUP2 .Pantalla/x DEO2 ( fijar coordenada x )
#03 .Pantalla/sprite DEO ( dibujar sprite de 1bpp con color 3 y 0 )
#0008 ADD2 ( incrementar x )
GTH2k ( ¿es la anchura mayor que x? o también, ¿es x menor que la anchura? )
,&bucle-x JCN ( salta si x es menor que el límite )
POP2 POP2 ( eliminar x y el límite )
POP2 POP2 ( eliminar `x` y el límite )
#0008 ADD2 ( incrementar y )
GTH2k ( ¿es el límite mayor que `y`? o también, ¿es `y` menor que el límite? )
@ -1694,7 +1693,7 @@ aquí hay algunas posibilidades extra para que practiques y trates de implementa
* iniciar el juego cuando se pulsa un botón
* posición "aleatoria" inicial de la pelota
* velocidad variable de la pelota y/o de las palas
* etc!
* ¡etc!
¡comparte lo que termines creando en base a todo esto! :)

View File

@ -192,7 +192,7 @@ as you may recall, the zero page consists of the first 256 addresses of program
we can refer to any of the 256 addresses of the zero page using one byte only, instead of the two bytes that are needed for absolute addresses.
something importat to keep in mind is that the contents of the zero page are not present in uxn roms.
something important to keep in mind is that the contents of the zero page are not present in uxn roms.
this means that a caveat of using variables there, is that in order to initialize them we need to do it during runtime, by storing values from the stack into them.
@ -207,7 +207,6 @@ labels for the zero page would work the same as before; we only need to specify
in order to refer to them, we would use the dot (.) rune for literal zero page addresses, instead of the colon (;) rune for literal absolute addresses.
### instructions: LDZ, STZ
the instructions for loading (reading) and storing (writing) from and to the zero page are:
@ -266,7 +265,7 @@ BRK
note the use of the literal zero page address rune (.) to refer to the .pixel label.
also, note that in the case of .pixel the address is referring to the zero page, accessed with LDZ/STZ, and in the case of .Screen the address is referring to the i/o address space, accessed with DEO/DEI.
also, note that in the case of .pixel the address is referring to the zero page, accessed with LDZ/STZ, and in the case of .Screen the address is referring to the i/o address space, accessed with DEI/DEO.
### a little stack wrangling practice
@ -358,7 +357,7 @@ the use of "variables" will help us now in discussing three different ways of an
* autonomous change of position
* interactive change of position (with keyboard)
* autonomous change of drawn tile
* autonomous change of drawn tile
we will review them separately in order to keep the examples relatively simple and readable.
@ -920,12 +919,10 @@ we can use these macros to divide the frequency in our code:
.Screen/addr DEO2 ( set computed address )
```
=> ./img/screencap_uxn-animation-quarterspeed.gif animation of a diagonal stripe inside a pixelated square. the diagonal moves from bottom right to top left. it moves slower than the previous one.
ah, way better!
## not powers of two
note that if you want to divide the frequency to numbers that are not powers of 2, you might start to see some glitches approximately every 4 seconds: this is due to framecount overflowing and not giving a nice sequence of results for those divisors.
@ -936,7 +933,6 @@ the easiest workaround for these issues would be to use a short-sized framecount
you'd have to adapt the program to work with that size of framecount - nice exercise, i feel and think!
# instructions of day 4
these are all the uxntal instructions that we discussed today!

View File

@ -24,7 +24,8 @@ counting from right to left, the first bit corresponds to the first mouse button
usually, in a three-button mouse, the first button is the left one, the second button the middle one, and the third button the right one.
using a three-button mouse like this, we would have eight possible values for the state byte, for example:
using a three-button mouse like this, we would have eight possible values for the state byte, for example:
* 00 when none of the buttons are pressed
* 01 when only the first button is pressed
* 02 when only the second button is pressed
@ -35,7 +36,7 @@ note that similarly to the controller device, this system allows us to check for
* 03 when the first and second buttons are pressed
* 05 when the first and third buttons are pressed
* 06 when the second and third buttons are pressed
* 07 when the threee buttons are pressed
* 07 when the three buttons are pressed
remember that we can use AND masks, as introduced on {uxn tutorial day 3}, to isolate and evaluate separately any of these bits.
@ -257,6 +258,7 @@ first of all, let's move our pointer drawing subroutine to another label in our
#4a .Screen/sprite DEO
BRK
```
note that we could join the actions of updating the pointer position and sending it to the screen, using a pair of DUP2:
```
@ -273,7 +275,6 @@ this would leave our on-mouse subroutine empty:
BRK
```
### using normal jumps
with what we know already, and depending on the position of draw-pointer with respect to on-mouse, we could do a relative jump:
@ -396,7 +397,7 @@ additionally, as the addresses pushed by JSR are shorts, we need to activate the
JMP2r ( jump to the absolute address at the top of the return stack )
```
in many uxntal programs you will see this instruction written as a macro, RTN (return)
in many uxntal programs you will see this instruction written as a macro, RTN (return):
```
%RTN { JMP2r }
@ -626,7 +627,7 @@ i said then that there was a more optimized set, and that we'd discuss it later.
now is that moment!
first of all, let's analyze what's happening with MOD. it is calculating what would be written in infix notation as follows, assumming that the slash (/) indicates an integer division
first of all, let's analyze what's happening with MOD. it is calculating what would be written in infix notation as follows, assumming that the slash (/) indicates an integer division:
```
a - ( a/b )*b

View File

@ -45,7 +45,6 @@ let's start with the following program as a template. it includes the data for a
#01c0 .System/g DEO2
#2ce5 .System/b DEO2
BRK
@tile-background 1122 4488 1122 4488
@ -676,7 +675,7 @@ all of this can go inside its own subroutine for readability purposes:
```
@update-paddles ( -- )
&left
( left paddle: up and down buttons )
( left paddle: up and down buttons )
.Controller/button DEI
DUP #10 AND ( check bit for up )
,&left-up JCN
@ -1190,7 +1189,7 @@ where bounce-left would be:
and what happens if both conditions are not met at the same time?
we can let the ball keep moving, but checking that it hasn't crossed the left wall, by comparing with 0000.
we can let the ball keep moving, but checking that it hasn't crossed the left wall, by comparing with 0000.
the whole x-in-left code would end up looking like:
@ -1220,7 +1219,7 @@ the whole x-in-left code would end up looking like:
&check-right-paddle
```
finish would be a label at the end of the subroutine, and reset is a subroutine that we will discuss later.
"finish" would be a label at the end of the subroutine, and "reset" is a subroutine that we will discuss later.
this approach of comparing with 0000 is the easiest, but keep in mind that it might not work if you change the ball speed: it could happen that it crosses the wall but with an x coordinate that is never equal to 0.
@ -1303,7 +1302,7 @@ here's all of the code we wrote today!
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &auto $1 &pad $1
&x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|80 @Controller [ &vector $2 &button $1 &key $1 ]
|80 @Controller [ &vector $2 &button $1 &key $1 ]
( macros )
%RTN { JMP2r }