Skip to content

AmstradGameDevChallenge/BASICvsC-RPG

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BASIC vs C: RPG

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 5: Game Design, modelo ECS y más #AGC05

Amstrad GameDev Challenge: BASIC vs C. Episodio 5. Game Design, modelo ECS y más. #AGC05 Fecha: Martes, 11 de septiembre de 2019, 21:00h

>> Vídeo <<

>> Código fuente << || >> Plantilla Doc. Diseño << || >> Game Design Doc. Template <<


>>> Contenidos detallados <<<
  • Noticias:
    • Taller de #AmstradGameDevChallenge en RetroZaragoza 2019 (28/09/2019 16:00h). Inscipciones abiertas. Se intentará emitir en directo.
    • Novedad en #AGC05: Cronómetro para las intervenciones del #TeamC y el #TeamBASIC. 15 minutos + 5 extra por intervención.
    • Acalaración respecto a #AGC y el #CPCRetroDev
  • Desarrollo:
    • BASIC:
      • Revisión de nuevo tipo de Memory Leak en BASIC:
      • Hay un problema al realizar SYMBOL AFTER. Se reserva nueva memoria para los UDGs donde esté en ese momento HIMEM.
      • Es importante realizar un SYMBOL AFTER 256 al inicio del programa para liberar la memoria reservada para UDGs antes de reservar nueva.
      • Observamos problemas que pueden ocurrir con el uso de SYMBOL AFTER y otros comandos que manejen HIMEM, como por ejemplo los CALL de inicialización (&BBFF y &BB4E)
      • Analizamos un problema importante de consumo de memoria en BASIC: el código que usamos para definir los UDG ocupa mucho espacio
      • Vemos como utilizar la orden CHAIN MERGE para tener 2 programas separados que se encadenan: uno inicializa todo (variables, UDGs, etc) y otro sólo ejecuta, pero solo tiene los datos, y no el código de inicialización, ahorrando memoria.
      • Solucionamos un problema de inicialización con DEFINT, que elimina todas las variables previamente definidas.
      • Nota importante: La opción CHAIN MERGE funciona bien con programas BASIC binarios. Sin embargo, con programas BASIC en formato ASCII no funciona bien en los 464 y 664: hay un bug en el firmware.
    • Game Design
      • Proponemos un formato de documento para Game Design con una estructura concreta ayudar a estructurar nuestras ideas de juego.
      • Revisamos el documento y sus apartados y vemos la utilidad y que significa cada uno de ellos.
      • Vemos los principios iniciales de Game Design de nuestro juego, Dungeon Castles.
      • Vemos bocetos y modelos a utilizar para el diseño y desarrollo del juego.
      • Hablamos de lo importante que es tener modelos de referencia en los que basarse para las mecánicas.
      • Vemos la historia de los castillos de Alicante, base de nuestro juego Dungeon Castles.
      • Revisamos los apartados del documento en el caso de nuestro juego y cómo los hemos rellenado inicialmente.
      • Entendemos cómo evitar el bloating (sobrecrecimiento) de características
      • Hablamos del mapeado en nuestro juego y ponemos ejemplos de algunos tipos de mapa en su diseño inicial.
      • Diseñamos unos tipos concretos de objetos que deben haber en nuestro juego y cómo funcionarán.
      • Seleccionamos unas mecánicas concretas de combate y debatimos sobre ellas
      • Vemos también como muy importante el diseño iterativo y cómo afrontar correctamente las iteraciones.
      • Explicamos lo que es el Mínimo producto viable (MVP en inglés) y cómo definirlo y trabajar en él para empezar.
      • Debatimos sobre cómo diseñar un MVP y cómo seleccionar mecánicas simples para que sea un produto completo
    • Technical Design (Diagramas y ECS)
      • Vemos por qué es importante realizar diagramas técnicos del funcionamiento de nuestro código
      • Conforme un programa crece es imposible mantener en la cabeza todo el código, lo que hace y cómo funciona
      • Explicamos que los diagramas no se elaboran como siempre se explica en ingeniería: primero el diagrama completo y luego pogramar. Esto no funciona habitualmente así.
      • Entendemos que los diagramas técnicos deben ser algo vivo, que se mantiene actualizado y que se usa para reflexionar, diseñar y para entender nuestro código al completo.
      • Vemos un ejemplo de diagrama de llamadas realizado con draw.io
      • Con el diagrama entendemos la estructura de llamadas entre las distintas partes del código y las dependencias que eso implica
      • Vemos que la estructura de nuestro juego se está complicando mucho y eso teniendo en cuenta que sólo hemos hecho unas pocas partes.
      • Para evitar que la estructura siga complicándose y el código llegue pronto a ser inmanejable, vemos otras posibles estructuras mejores
      • Hablamos del modelo Entidad-Componente-Sistema (ECS: Entity-Component-System).
      • Explicamos desde 0 cómo se estructura una aplicación siguiendo el modelo ECS y qué siginifican los distintos componentes.
      • Resolvemos dudas respecto al planteamiento del modelo y casos concretos.
      • Hablamos de las diferencias entre ECS y el modelo de Componentes de Unity3D y Unreal Engine: no son el mismo modelo
    • Migración a ECS
      • Intentamos migrar el código a Entity-Component-System
      • Vemos y analizamos las dificultades que surgen y lo que eso significa respecto a lo acoplado que estaba nuestro código anterior
      • Intentamos desacoplar el movimiento del jugador del código que pinta, comprueba colisiones y realiza ataques a otros personajes
      • Pese a intentarlo, se nos complica tanto que ni siquiera podemos llegar a probar lo que desarrollamos.
      • Con este ejemplo entendemos lo importante que es separar las responsabilidades y que cada sistema haga exclusivamente sus funciones sin acoplarse a lo que hace el resto del código.
      • Esto nos dejaver las ventajas de tener los sistemas separados a la hora de desarrollar nuestro juego.
    • C:
      • Explicamos el funcionamiento de los includes y su utilidad a la hora de tener cosas definidas en varios ficheros.
      • Entendemos la diferencia real entre ficheros de cabecera (.H) y unidades de traducción (.C): se trata de una convención útil
      • Empezamos a separar el código que tenemos en C en varios ficheros para poder tenerlo organizado.
      • Esto nos permitirá en el futuro modelo ECS tener todos los sistemas bien separados y organizados.
      • Vemos la diferencia entre usar comillas y mayor/menor a la hora de incluir ficheros.
      • Entendemos que el proceso de compilación se ocupa de ficheros uno a uno, por separado. Ningún fichero conoce lo que hay en los demás ficheros. Para eso utilizamos las declaraciones añadidas en los ficheros de cabecera.
      • Incidimos en la diferencia entre declaraciones y definiciones y su importancia.
      • Vemos el uso de extern para poder declarar variables sin definirlas.
      • Explicamos cómo usar include guards en C para evitar que un fichero de cabecera sea procesado más de una vez allá donde es incluído.

EPISODIO 4: Especial Gráficos UDG #AGC04

Amstrad GameDev Challenge: BASIC vs C. Episodio 4. Especial Gráficos UDG. #AGC04 Fecha: Martes, 27 de agosto de 2019, 21:00h

>> Vídeo <<

>> 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?

AVANCE EPISODIO 4: Misterio Memory Leak en BASIC

Avance Amstrad GameDev Challenge: #TeamBASIC misterio memory leak

Fecha: Martes, 20 de agosto de 2019, 21:00h

>> Vídeo <<

>> Código fuente <<


>>> 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

Amstrad GameDev Challenge: BASIC vs C. Episodio 3. #AGC03

Fecha: Martes, 6 de agosto de 2019, 21:00h

>> Vídeo <<

>> Código fuente <<


>>> 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 carpeta obj/
    • ¿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 y OPENOUT 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

Amstrad GameDev Challenge: BASIC vs C. Episodio 2. #AGC02

Fecha: Martes, 23 de julio de 2019, 21:00h

>> Vídeo <<

>> Código fuente <<


>>> Contenidos detallados <<<
  • Noticias:
  • 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 y puts 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$ y STRING$ 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

Amstrad GameDev Challenge: BASIC vs C. Episodio 1. #AGC01

Fecha: Martes, 9 de julio de 2019, 21:00h

>> Vídeo <<

>> Código fuente <<


>>> 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

Materiales

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.