Desarrollo en directo de un juego de rol en BASIC y C para Amstrad CPC.
Seguidnos en Twitter: @FranGallegoBR, @Hec_Linares, #TeamBASIC, #TeamC, #AmstradGameDevChallenge
EPISODIO 4: Especial Gráficos UDG #AGC04
Fecha: Martes, 27 de agosto de 2019, 21:00h
>> Código fuente <<
|| >> UDG Designer <<
>>> Contenidos detallados <<<
- Noticias:
- 4ª edición de los premios de animación de la comunidad de Madrid, con premios de 2000€ y 1000€ a los mejores videojuegos culturales.
- Actualizaciones de CPCtelera
- cpct_rvm ahora soporta uso de nombres largos y modo warp en arranque.
- cpc2cdt permite importar ficheros ASCII en CDTs.
- cpct_pack permite la generación de ficheros binarios comprimidos.
- cpct_bin2sna permite crear snapshots de múltiples ficheros binarios.
- Nueva versión del emulador CPCEC de CNGSoft. Funciona en Windows y en Linux/Mac (con wine).
- Desarrollo:
- BASIC:
- Repaso del código BASIC: uso de fre("") y UNT()
- Reestructuración del código de gestión de enemigos y personaje principal
- Descarga directa y uso en línea de comando de la última versión del emulador de CNGSoft CPCEC (wget http://cngsoft.no-ip.org/cpcec-20190817.zip)
- Sustitución de mensajes por gráficos: usando subrutinas de dibujado para personaje y enemigos
- Uso de variables temporales para acortar el código y mejorar su legibilidad
- Introducción a los gráficos UDG: ¿Qué son? ¿Cómo se crean? Definición y uso de distinas bases numéricas.
- Uso de SYMBOL y SYMBOL AFTER.
- ¿Por qué es necesario SYMBOL AFTER? Uso de memoria de los UDGs. Modificación a mano de la memoria que define los UDGs.
- Presentación de hoja de cálculo para dibujado de UDGs.
- Soporte para que los enemigos puedan tener sus propios UDGs
- Más información sobre gráficos UDG en el blog de Fremos.
- Dibujado de sprites formados por múltiples caracteres y con varios colores: uso del modo transparente.
- Dibujando sprites multicolor y multicarácter usando cadenas y códigos de control: String Sprites
- Definición de String Sprites constantes en un array, accesibles por su índice: evitando copiar cadenas en tiempo de ejecución.
- Activación/Desactivación de modo transaparente usando cadenas y el código de control 22
- C:
- Problemas de SYMBOL AFTER en C:
- No hay SYMBOL AFTER en C ni en el firmware de Amstrad.
- En C se generan binarios, y al cargar un binario Amstrad desactiva los UDGs.
- El firmware almacena 3 variables en memoria para gestionar los UDG: Valor ASCII del primer UDG definible, Puntero a la matriz de UDGs y flag de activación.
- Las variables están en ubicaciones distintas en los firmwares 1.0 y 1.1.
- Implementación de SYMBOL AFTER en C.
- Detalle sobre el casting de direcciones de memoria absolutas a punteros.
- Implementación de SYMBOL en C usando el código de control 25.
- Entendiendo HIMEM, el firmware y la ROM, para saber dónde ubicar la tabla de definiciones de UDG para C.
- Problema: realizar un SYMBOL AFTER antes de la inicialización de texto y gráficos con los CALL 0xBBFF y call 0xBB4E (initMode()). Estas inicializaciones deshacen el SYMBOL AFTER.
- Detección de la versión del firmware actualmente en ejecución: Usando el final de la tabla de saltos (High jump-block) que es distinto en las 2 versiones.
- Problema en SDCC con múltiples comparaciones en una misma línea.
- Definición de múltiples caracteres en C sin usar SYMBOL: haciendo que el puntero de SYMBOL AFTER apunte a un array con los datos.
- Imprimiendo sprites de enemigos formados de varios carácteres.
- Creación manual de string sprites en arrays para dibujar enemigos multicaracter y multicolor.
- Dibujando enemigos con 2 caracteres de altura, 3 colores y 9 UDGs en total.
- Uso del modo transparencia con una función de activación/desactivación.
- Nuevos misterios y trabajo para casa:
- Nuevo problema de memory leak en BASIC: en cada nueva ejecución del juego desaparecen 48 bytes. ¿Por qué?
- Los UDG en BASIC nos ocupan doble: el código que genera los datos de los UDG, más los propios datos de los UDG.
- ¿Es posible tener en BASIC en memoria sólo los datos de los UDG, sin el código que los genera, como en C?
Fecha: Martes, 20 de agosto de 2019, 21:00h
>>> Contenidos detallados <<<
- Noticias:
- Actualización de #CPCtelera: añadido modificador -w para activar el modo Warp al inicio en RVM
- Misterio en BASIC:
- Recordatorio: al realizar varios ciclos de ejecución de nuestro juego, durante la ejecución, se pierden bytes de memoria
- Comentarios de usuarios que han investigado y se han planteado dudas
- Si la memoria se va perdiendo, ¿Se quedará nuestro programa al final sin memoria?
- Usuario comenta que parece pederse la memoria en los INPUTs, que parece un fallo del firmware del #Amstrad
- Revisión de la dirección de memoria &B08D que contiene datos del firmware: 'Final del espacio libre: byte antes de la zona de strings = HIMEM'
- Detalle importante: hay 2 firmwares de Amstrad CPC, el 1.0 y el 1.1. Las variables del firmware están en direcciones distintas según la versión del firmware
- Mapa básico de memoria del Amstrad CPC y definición de qué es HIMEM
- Funcionamiento de los bancos de memoria y las ROMs del CPC a nivel básico
- HIMEM: dirección más alta de espacio para el programa en BASIC (código y variables)
- La zona de memoria de BASIC está protegida por el intérprete: no nos permite escribir en ella desde fuera.
- La orden MEMORY sirve para cambiar HIMEM de posición: utilidades
- Vemos el valor de HIMEM desde BASIC, usamos HEX$ para convertirlo y vamos a esa zona de memoria a ver qué hay
- Cómo configurar el visor de memoria de RVM para mostrar contenido de RAM y ROM
- Ponemos a prueba la zona de strings de BASIC (en HIMEM) asignando valores a a$ y vemos cómo reacciona la memoria
- La zona de strings de BASIC almacena strings nuevos sin borrar antiguos: funciona como un Stack Allocator (un gestor de memoria tipo pila)
- Esto explica el misterio: en cada ciclo del programa metemos valores nuevos en los strings con nuestros INPUT.
- No es realmente un memory leak, sino una consecuencia del Stack Allocator, que funciona similar a lenguajes de script modernos.
- Es una estrategia óptima para la gestión dinámica de la memoria de strings.
- ¿Hace este comportamiento que se nos pueda acabar la memoria? Creamos un programa para ponerlo a prueba
- Cuando no queda memoria, BASIC libera la memoria de strings que ya no son usados, compactando los usados. Básicamente, recolecta la basura.
- Potenciales ventajas e inconvenientes del funcionamiento de la memoria de strings
- Controlar y liberar la memoria (recoger la basura) cuando nosotros queramos usando FRE("")
- Usando UNT para evitar tener que hacer PRINT de FRE("") y no causar Overflows
- añadiendo la recolección de basura a nuestro programa y poniéndolo a prueba
- Observando el comportamiento de la memoria cuando forzamos la liberación de strings
- Truquito en asignación de variables: uso de otras variables en lugar de valores inmediatos
- Resolución de dudas planteadas en el chat
EPISODIO 3 #AGC03
Fecha: Martes, 6 de agosto de 2019, 21:00h
>>> Contenidos detallados <<<
- Noticias:
- Actualización en CPCtelera 1.5 WIP: Inclusión de soporte para STDC getchar()
- #AmstradGameDevChallenge estará presente en RetroZaragoza 2019: grabaremos un episodio en directo en persona.
- Recomendación: temática para los juegos RPG sobre leyendas reales de Castillos, Monasterios, Pueblos o lugares de la geografía española.
- Preguntas y proyectos de los miembros del grupo:
- Problema con la inicialización de variables globales en SDCC: no se les asigna valor.
- Soluciones para variables globales: funciones de inicialización, valores constantes y punteros no constantes y copia de valores con
cpct_memcpy
- Sugerencia de uso de
grep
para eliminar los comentarios en BASIC. - Problema con
.gitignore
y la carpetaobj/
- ¿Cómo se puede hacer
SYMBOL AFTER
en C? - Apreciaciones sobre el uso de
cpct_setVideoMode
, el firmware y las funciones de CPCtelera. - Detalles a tener en cuenta en el uso de
OPENIN
yOPENOUT
en BASIC - Misterio en BASIC:
- Pérdidas de memoria en nuestro juego. ¿A qué se deben? Dos semanas para encontrar la respuesta.
- Desarrollo:
- Inicialización rápida y fácil de la pantalla, los colores y el módulo de texto sin tener que ajustarlo todo a mano.
- Llamadas a funciones del firmware con código ensamblador en línea: nota sobre potenciales problemas
- Creación y manejo de
structs
en C: ¿Qué son? ¿Cómo funcionan? - Introducción de espacio para múltiples enemigos usando un array de structs en C
- Importancia de los comentarios en BASIC: usarlos como referencia de variables y estructuras de memoria
- Simulación de structs en BASIC usando arrays y prefijos de nombre
- Uso de una referencia variable a un elemento para generalizar el código previo directamente
- Diseño básico de un gestor de enemigos: creación y destrucción
- Visualización de múltiples enemigos e interacción: problemas asociados
- Gestión del array de enemigos al eliminar uno de ellos: posibles alternativas
- Añadiendo color a los enemigos como forma de distinguirlos
EPISODIO 2 #AGC02
Fecha: Martes, 23 de julio de 2019, 21:00h
>>> Contenidos detallados <<<
- Noticias:
- Anuncio oficial del #CPCRetroDev 2019
- Revisión de proyectos en desarrollo de los miembros del #TeamC y el #TeamBASIC
- Desarrollo:
- Creación de un script bash para generar un DSK a partir del fichero .BAS
- Comentarios que no ocupan memoria en BASIC
- Reemplazo y uso de variables con nombre corto en BASIC
- Usando
LOCATE
desde C para dibujar personajes en una posición concreta - Uso de funciones y parámetros en C para reutilizar y simplificar el código
- Diferencias entre las funciones
printf
yputs
y uso del firmware - Análisis de estartegias más óptimas de programación en C usando el código ensamblador generado
- Uso de las funciones
CHR$
ySTRING$
en BASIC para pintar caracteres y repetirlos - Movimiento de los personajes en una dimensión y ataque por movimiento
- Uso de
GOSUB
y subrutinas en BASIC para modularizar el código - Dudas sobre paso de parámetros a funciones y subrutinas en BASIC y C
- Detalle sobre las comparaciones y asignaciones en C
- Introducción a los arrays en C y BASIC
- Funciones aleatorias simples para ataques variables en juegos de ROL
- Definición de funciones matemáticas en BASIC
- Cálculos enteros y reales y redondeos en BASIC y C
- Uso de
RANDOMIZE
para controlar las secuencias pseudoaleatorias
EPISODIO 1 #AGC01
Fecha: Martes, 9 de julio de 2019, 21:00h
>>> Contenidos detallados <<<
- Presentación de la serie
- Herramientas a utilizar y organización
- Implementado un esquema inicial muy básico de juego y bucle principal emergente, sin apenas estructurar.
- Primeros pasos con variables
- Player y enemigo con energía, ataque y defensa
- Player y enemigo atacan y defienden
- Hoja de cálculo para diseño de UDGs
- Solicitud de inscripción a la organización de Github
- CPCtelera
- CPCtelera 1.5 WIP
- CPCtelera Manual de Referencia
- Manual del usuario de Amstrad CPC 464 1987
- Manual del firmware del Amstrad CPC
Cread vuestros repositorios en AmstradGameDevChallenge y empezad vuestros propios RPG en BASIC y C. En el próximo episodio los analizaremos en directo y compartiremos las ideas de programación entre todos.