Historia de Tron 0xF
Descripción del contenido de la página
Historia del desarrollo de Tron 0xF, un juego escrito en Forth para ZX Spectrum.
2015-03
Inicio del proyecto, cuyo objetivo en principio es solo hacer un remozado del Tron de 1985.
Conversión del código fuente al formato fsb, para poder editarlo cómodamente con Vim y convertirlo en un fichero de bloques de Forth, en un fichero TAP listo para ser cargado por Abersoft Forth.
Muchos cambios y mejoras, de las cuales las principales son:
- Textos reescritos usando gráficos para los caracteres castellanos;
- instrucciones integradas en el código, no simplemente escritas en un bloque fuente y listadas como tal;
- créditos y pantalla de inicio;
- renombrado general de palabras, factorización de palabras y uso de constantes para hacer el código más claro;
- arreglo de la lectura de teclado (el método original de comprobación de los puertos no funcionaba en el emulador);
- simplificación y perfeccionamiento de varios algoritmos.
2015-03-23
El código ya no cabe en los diez bloques que ofrece Abersoft Forth en su disco RAM interno. Lo divido en tres ficheros y creo un Makefile que los convierte en un solo TAP del que Abersoft Forth los cargará de forma encadenada, automáticamente.
2015-03-24
Mejora: Los textos están también en inglés y esperanto (aunque aún no se pude cambiar de lengua).
Mejora: Es posible abandonar el juego con la tecla Break.
Mejora: Ya no es posible ir en sentido opuesto a la propia marcha, y por tanto tampoco chocarse con uno mismo...
El código sigue creciendo: ya ocupa cuatro ficheros de bloques.
Mejora: El marco de juego ahora se imprime instantáneamente.
2015-03-26
Varias mejoras y correcciones. Para asegurar la detección de choques con el borde inferior de la zona de juego ha habido que subir éste ocho puntos (debido a la línea de atributos que se usa para enmascar la línea límite), debido a que Abersoft Forth no permite acceder con PLOT
a coordenadas negativas, y hacer una excepción no merecía la pena.
2015-03-27
Gráficos con las letras propias del esperanto.
2015-03-29
Comienzo de la implementación del código para redefinir las teclas de los jugadores.
2015-03-30
Reorganización del código, para usar la biblioteca Afera en lugar de duplicar su contenido. Nuevo juego de caracteres, con gráficos para los caracteres propios del español y del esperanto. Primeras pruebas con la definición de teclas.
2015-03-31
Nuevo fichero fuente, para contener el código del menú principal del programa. Primera versión funcional del menú.
2015-04-01
Tras las novedades en la librería Afera, que permiten usar las dos líneas inferiores de la pantalla, cambio la disposición del escenario de juego, usando la zona inferior para las puntuaciones.
El juego pasa a llamarse Tron 0xF, para distinguirlo de su versión original.
2015-04-02
Retoques.
Pantallazos del estado actual del programa:
2015-04-06
Terminada la implementación de caracteres de doble altura para las puntuaciones.
Arreglo: Ya no se borra toda la pantalla al reiniciar cada partida.
2015-04-07
Mejora: El borrado de la zona de juego es instantáneo, gracias a una restauración de atributos previa al borrado real.
Nuevo: Código para desactivar y reactivar los sonidos del juego (aunque aún no se puede hacer el cambio desde el menú).
2015-04-15
Nuevo método de carga, debido a los cambios en la librería Afera: las fuentes ya no están encadenadas con RUNT
; una palabra las carga con un bucle.
2015-04-18
Se usa una nueva versión de INK
incorporada en la librería Afera. Así se evita el fallo de la versión original, aún no descubierto, que hace que PLOT
en la mayoría de los casos use un cero en lugar del atributo de color.
Mejora: ninguno de los dos jugadores obtiene puntuación si se chocan simultáneamente.
2015-04-19
Primeros cambios para añadir un tercer jugador.
2015-04-20
Las tablas de teclas de jugador son combinadas con la tabla de datos generales.
Primer boceto del piloto automático para los jugadores manejados por el programa.
2015-04-21
Primeros cambios poder utilizar todos los algoritmos con cualquier jugador, en lugar de repetir el código para cada uno.
2015-04-30
Cabecera gráfica con el título. Los autores y la licencia se muestran en la opción correspondiente del menú. La licencia se imprime interpretando bloques del disco RAM, para ahorrar memoria, pero es demasiado lento, lo que no resulta estético: lo modifico para imprimir con palabras compiladas.
2015-05-01
La opción de menú "About" muestra los autores y la licencia.
Primera versión práctica de AUTOPILOT
. Sin embargo, solo funciona para jugar contra un jugador robot. Si hay dos jugadores manejados por la máquina, se chocan. No sé por qué.
He escrito en la librería Afera una nueva versión de POINT
, más rápida que la palabra original. Ya está enlazada e incluida en Makefile, pero no está probada.
2015-05-04
Por primera vez el juego funciona con un humano y dos robots. Antes los dos robots chocaban entre sí. El problema era que el robot que empezaba subiendo cortaba el paso al que empezaba yendo de derecha a izquierda, justo un pixel delante. La detección de choques se hace dos pixeles por delante. La primera solución, cambiar la detección de choques a un pixel, producía un laberinto feo, porque las motos robot giraban pegadas a las paredes. La segunda solución fue mover un pixel a la izquierda la posición de partida del robot que empieza subiendo.
Además ya se usan las versiones rápidas de PLOT
y 1+
. Hay varias palabras del juego marcadas para ser reescritas en Z80.
2015-05-08
El cargador queda obsoleto. He creado una versión genérica para la librería Afera.
2015-05-10
La detección de choques vuelve a fallar. Quizá es por algún cambio en Afera.
2015-07-05
Modifico los títulos de crédito en las tres lenguas.
El módulo _color.fsb_ de Afera estaba desactivado en _Makefile_, lo que hacía que ocurriera el fallo original de Abersoft Forth con plot
e ink
.
point
tenía un fallo en Afera. Lo corrijo. El juego vuelve a funcionar bien.
Convierto las fuentes a minúsculas, mucho más cómodo para trabajar con el editor Vim. El módulo _caseins.fsb_ de Afera, necesario para esto, ya estaba incluido.
Convierto la variable lang
en un valor.
2015-07-06
Primeros cambios para añadir al menú de configuración la selección del tipo de piloto (humano o robot).
2015-07-09
Primera versión funcional del nuevo menú de configuración, que permite elegir el piloto (humano o robot) de cada jugador.
Mejora: pausa tras cada choque, hasta que se pulse una tecla.
2015-07-09
Mejoras y correcciones en los sonidos.
Primeros cambios para elegir el número de jugadores en el menú de configuración.
2015-07-11
Primera versión funcional del nuevo menú de configuración.
Mejora en el código de giro aleatorio de los jugadores robot.
2015-07-12
Más cambios en el menú de configuración.
2015-07-13
Mejoras en el menú de configuración.
Primeros cambios en el código para cambiar las condiciones de finalización de cada duelo. Hasta ahora el primer jugador que se chocaba hacía que el duelo terminara, aunque aún quedaran dos jugadores más.
2015-07-13
Avances en el nuevo código de control de duelos.
2015-07-14
Nuevos campos de datos para conservar las coordenadas e incrementos del inicio de cada duelo (independientes de las usadas durante el juego) y que deben ser fijadas al inicio de este.
Problema: Ya solo quedan unos 500 octetos libres.
Independizo la inicialización de las columnas de las puntuaciones; hasta ahora formaba parte de la inicialización de las posiciones iniciales, lo que era incorrecto, porque hay que hacer ambas operaciones en momentos diferentes.
La configuración del sonido por fin se hace en el menú de configuración, no en el menú principal. Primera versión funcional.
2015-07-15
Diversas mejoras. Consigo más memoria libre, revisando los módulos de Afera necesarios y dividiendo algunos.
2015-07-16
La tecla Caps Shift ya no es admitida en la configuración de las teclas de juego. El motivo es evitar pulsaciones accidentales de Break durante el mismo, que se usa para terminar la partida (aunque con confirmación).
Cuando todos los jugadores activos son robots, no se espera la pulsación de una tecla al inicio ni al final de cada duelo. El programa continúa por sí solo.
2015-07-17
Para aumentar la memoria libre (quedan 167 octetos), uso los espacios libres del disco RAM para guardar los gráficos de caracteres del esperanto y del español, como ya se hacía con la tipografía principal. Estos gráficos se guardaban hasta ahora en la zona de 1 KiB que Abersoft Forth no usa, salvo para los gráficos de usuario (que están en la misma dirección que en BASIC, ocupando los últimos 168 octetos de la memoria) por encima de HI
, es decir, justo sobre el disco RAM. Al liberar esa zona es posible unirla al diccionario, utilizando para ello los módulos
2015-07-18
Tras usar los susodichos módulos de Afera para mover el disco RAM hasta la parte más alta de la memoria, quedan 1020 octetos libres en el diccionario de Forth.
Aún sería posible ahorrar más memoria usando los espacios libres en el disco RAM para los datos de los jugadores. El problema es que estas zonas no podrían usarse hasta haber cargado el último disco RAM, igual que se hace con los gráficos, y esto exige hacer algunos cambios importantes.
Mejora: las pantallas de texto (instrucciones y acerca de) no tienen el título gráfico del menú, que ocupa ocho líneas de texto. Así se reduce el número de pantallas necesario para mostrar los textos.
Primeros cambios para ahorrar un octeto en cada definición de la tabla de teclas. Hasta ahora se usan dos octetos para guardar el nombre de la tecla, debido a las teclas con nombres especiales. Así, la estructura de cada registro en la tabla es como sigue:
\ Every element of the `keys` table
\ has the following structure:
\ +0 = port of the keyboard row (2 bytes)
\ +2 = bitmask of the key (2 bytes, but only the LSB is used)
\ +4 = key name (2 bytes): one letter (the second byte is
\ zero and will be ignored) or two letters.
Usando un gráfico que represente el nombre de esas teclas especiales en un solo carácter, ahorraremos 40 octetos. Con la máscara, que también usa dos octetos, podría hacerse algo parecido más adelante, a costa de una pequeña pérdida de velocidad durante el juego, probablemente inapreciable.
El código relacionado con los nombres de teclas es:
\ Convert two characters to a 16-bit number.
: special-key-name ( c1 c2 -- n ) 256 * + ;
: c>s ( c -- ca len )
\ Convert a character to a string.
pad c! pad 1 ;
: 2c>s ( n1 -- ca len )
\ Convert two characters to a string.
\ high byte of n1 = first character
\ low byte of n1 = second character
pad ! pad 2 ;
: key-name ( a -- ca len )
\ Convert a key identifier to its key name.
\ a = key address in the `keys` table
4 + @ dup 256 u< if c>s else 2c>s then ;
Con el nuevo sistema, el código se reduce a esto:
\ Convert a key identifier to its key name character.
\ Note: `graph-udg` must be used before printing it
\ (and `lang-udg` after) because some key names use UDG.
\ a = key address in the `keys` table
: key-name ( a -- c ) 4 + c@ ;
Primera versión de la opción de cambiar el color en el menú de configuración:
Tras unas cambios, se muestra un icono de color diferente para humanos y robots:
( Color )
\ Two versions (for humans and robots)
\ of the three UDG that form the color icon:
here: robot-color-icon 156 c, 157 c, 158 c,
here: human-color-icon 159 c, 160 c, 161 c,
\ Color icon selection table:
here: color-icons robot-color-icon , human-color-icon ,
\ Position the cursor on the color icon of the current
\ player.
: at-color ( -- ) color-line player-col at ;
\ String with the proper color icon, for humans or robots.
: color-icon$ ( -- ca len ) color-icons human? cells + @ 3 ;
: show-color ( -- )
\ Print the color icon of the current player.
player-color @ ink graph-udg
at-color color-icon$ type lang-udg white ink ;
\ Hide the color icon of the current player.
: hide-color ( -- ) at-color color-icon$ type-spaces ;
: color-option ( -- n )
\ Wait for a valid key press for a color option
\ and return its value.
\ n = 1..7 (color code)
begin akey s" 1234567" char-in-string? until 1+ ;
: change-color ( -- )
\ Change the color of the current player.
\ A digit key is regarded as its correspondent color (0..7);
\ a space can be used to change the current color to the
\ next one (7 changes to 0 in an endless loop).
color-help$ remark 1 flash show-color 0 flash
color-option player-color !
show-color color-help$ -remark ;
He reorganizado el uso del disco RAM como almacén de gráficos. La mayoría de las pantallas se usaban para guardar una copia de la imagen de pantalla, para restaurarla tras el mensaje de confirmación de final de partida, pero esto era un desperdicio porque el mensaje solo borraba una línea de la pantalla. Finalmente el mensaje se imprime en la barra de estado:
\ Ask "Do you want to stop?" in the current language
\ and return a flag with the answer (true=yes).
\ Erase the message at the end.
: do-stop? ( -- f )
white ink do-stop$ 2dup remark yes? >r -remark r> ;
: stop? ( -- f )
\ Check if the Break key has been pressed; if so, confirm it.
\ f = confirmed Break key?
false ?terminal 0= ?exit \ no Break key, exit
drop -status do-stop? \ ask for confirmation
dup 0= if status then ; \ restore the status bar
Esto libera 7 KiB del disco RAM, utilizables para guardar datos del juego y así liberar espacio de diccionario, necesario para añadir más código (solo quedan 745 octetos libres). De momento la ocupación del disco RAM tras la compilación del programa es la siguiente:
\ screen 7: copy of arena attributes (640 bytes)
\ 384 bytes free
\
\ screen 8: game font (768 bytes)
\ Esperanto characters (96 bytes)
\ Spanish characters (144 bytes)
\ 16 bytes free
\
\ screen 9: double height digits (160 bytes)
\ UDG (144 bytes)
\ 720 bytes free
\
\ screens 10 and 11: graphic title (2048 bytes)
2015-07-20
Muevo los datos de los jugadores, que ocupan 102 octetos, al disco RAM de Forth. Para ello ha habido que modificar las palabras que crean las variables de jugador, para que no las inicialicen con los valores predeterminados; y tampoco inicializar las teclas predeterminadas durante la creación de la tabla de teclado. Todas las operaciones hay que hacerlas al final, en el último disco RAM cargado:
( Init the players data )
players-data /players-data erase
robot pilot0 ! robot control0 ! yellow color0 !
human pilot1 ! human control1 ! cyan color1 !
robot pilot2 ! robot control2 ! yellow color2 !
\ Player 0 default keys: 1=left, 2=right, 3=up, 4=down
\ (Sinclair joystick)
0 key#>a left-k0 ! 1 key#>a right-k0 !
2 key#>a up-k0 ! 3 key#>a down-k0 !
\ Player 1 default keys: 5=left, 6=down, 7=up, 8=right
\ (cursor keys)
4 key#>a left-k1 ! 22 key#>a right-k1 !
23 key#>a up-k1 ! 24 key#>a down-k1 !
\ Player 2 default keys: K=left, B=up, M=down, X=right
32 key#>a left-k2 ! 17 key#>a right-k2 !
38 key#>a up-k2 ! 37 key#>a down-k2 !
El uso del disco RAM queda así:
\ screen 7: copy of arena attributes (640 bytes)
\ 282 bytes free
\ players data (102 bytes)
\
\ screen 8: game font (768 bytes)
\ Esperanto characters (96 bytes)
\ Spanish characters (144 bytes)
\ 16 bytes free
\
\ screen 9: double height digits (160 bytes)
\ UDG (144 bytes)
\ 720 bytes free
\
\ screens 10 and 11: graphic title (2048 bytes)
: .version ( -- )
\ Print the version number, stored as a double number.
version <# version-time 3 > if # # [char] : hold then
version-time 1 > if # # bl hold then
# # [char] - hold # # [char] - hold #s #> type ;
Muevo la tabla de teclado al disco RAM. Esto libera 200 octetos en el diccionario. Ahora la inicialización de la tabla debe hacerse al final de la compilación, en el último disco RAM cargado desde la cinta. La memoria libre es de 810 octetos.
Mejoro el sistema de selección de color en el menú de configuración: ahora se debe confirmar la selección con la tecla Enter, lo que permite probar los colores:
2015-07-27
Termino de mover los textos de las notas sobre las licencias al disco RAM. De otro modo no quedaba memoria para ampliar los textos de las instrucciones. Ahora las palabras que los imprimen compilan la dirección del texto en memoria; por ejemplo:
: en-license ( -- )
[ 5 disc-scr c/l + ] literal [ 11 c/l * ] literal type ;
En español y esperanto los textos están almacenados en dos partes; por ejemplo:
: eo-license ( -- )
[ 5 disc-scr c/l 12 * + ] literal [ 4 c/l * ] literal type
[ 6 disc-scr c/l + ] literal [ 6 c/l * ] literal type ;
Y el uso del disco RAM queda como sigue:
\ screen 5: license note in English
\ license note in Esperanto (part 1)
\ screen 6: license note in Esperanto (part 2)
\ license note in Spanish (part 1)
\ screen 7: copy of arena attributes (640 bytes)
\ 82 bytes free
\ keys table (200 bytes)
\ players data (102 bytes)
\
\ screen 8: game font (768 bytes)
\ Esperanto characters (96 bytes)
\ Spanish characters (144 bytes)
\ 16 bytes free
\
\ screen 9: double height digits (160 bytes)
\ UDG (144 bytes)
\ 528 bytes free
\ license note in Spanish (part 2) (192
\ bytes)
\
\ screens 10 and 11: graphic title (2048 bytes)
Añado un mensaje de ayuda que faltaba en menú de configuración, para informar de que se sale con la tecla Break.
2015-11-25
Reviso el código. Mejoro la detección de choques para los pilotos robot, haciendo el rango aleatorio (2 o 4 pixeles). Compruebo el efecto de ese y otros ajustes en que las puntuaciones de los robots están más o menos niveladas cuando juegan solos.
2016-03-02
Termino de crear un repositorio de Git a partir de las copias de respaldo, para facilitar ver la evolución de las fuentes. Lo subo a GitHub.
2016-03-03
Corrijo errata en el texto de la licencia GPL en esperanto. Mejoro y amplío el fichero README en las tres lenguas. Corrijo y modifico algunos textos de la interfaz.
Actualizo el número de versión a 0.1.1, empezando a usar el formato Semantic version.
2016-03-05
Amplío los tres ficheros README.
2020-02-11
Preparo la traducción en Interlingue/Occidental. Para que quepa en la memoria disponible habrá que usar :noname
para ahorrar los nombres de las palabras que contienen los textos de cada lengua. Esto exige reorganizar el código para unir todas las traducciones de cada texto, en lugar de mantener un fichero fuente separado con todas las traducciones en cada lengua.
2020-02-12
Completo la traducción en Interlingue.
2020-02-13
Reescribo con :noname
la definición de los textos en las cuatro lenguas, para ahorrar las cabeceras de las palabras. Ahora en lugar de haber un fichero fuente con los textos de cada lengua hay tres ficheros fuente en que se define un grupo de textos en todas las lenguas.
Primera versión funcional del programa con textos en Interlingue.
2020-02-14
Traduzco el fichero README en Interlingue. Corrijo fallo en la reimpresión de campos en el menú de configuración. Actualizo el estilo del código fuente.
2020-02-16 .. 2020-02-25
Mejoro la paginación de las licencias mostradas por el programa.
Hago que las coordenadas iniciales tengan un rango aleatorio de 4 píxeles.
Mejoro la documentación y las instrucciones.
Fin de la versión 0.2.0.