De Homero a Kirby

Usted está aquí

Palabras desde otro mundo

Bajo un océano de bits, mes XVIII

Este ha sido un mes de esos de no avanzar demasiado. Uno de esos meses en los que la cabeza no da demasiado de sí y en los que no sabes hacia dónde tirar. Uno de esos en los que, como cada vez me veo sumergido en ellos, me limito a bucear bajito asomando mucho la cabeza. Uno de esos en los que, principalmente, me dedico a la parte más pasiva de este reto; a ver vídeos a tutiplén.

A ver si con el verano la cosa remonta.

Empecé con las clases de matemáticas del canal de Fran Gallego1. Unas clases que no están impartidas por él sino por uno de sus compañeros, y que no tratan de lo que esperaba sino que versan acerca de la lógica de primer orden2, Prolog y otros tema derivados de ambas dos.
Después de ver los primeros diez vídeos decidí dejar eso para más adelante. Había matices que se me escapaban y, como es de rigor, tenía la sensación de llegar a la sala con la película ya empezada. Tampoco tenía la cabeza como para ponerme a profundizar en ello, así que queda aparcado por el momento.
Pero volveré.

Después de eso volví hasta el profe titular3 y los vídeos que me faltan por ver de su canal. Ya falta menos para terminar con ellos… aunque tengo la impresión de que debería volver a darles otra vuelta cuando empiece a hacer algo en ensamblador. Los conceptos importantes están ahí, pero hasta que no me ensucie las manos con código no voy a ser capaz de determinar si he entendido realmente las cosas.

Este mes también ha sido la primera edición del Retro Madrid Academy4. Más allá de lo interesante de las ponencias, lo mejor que saqué de la visita fue el ver al amigo Multimaniaco5, y las conversaciones en el coche durante la ida y la vuelta hasta la capi. Es increíble lo que ayuda el tratar de verbalizar las cosas que crees haber entendido para terminar de asentar conceptos, o para darte cuenta de lo verdes que los tienes aún.
Necesito tener más conversaciones activas acerca de programación.

Tras largo tiempo en el dique seco, también he visto que se sigue hablando acerca del controlador adaptativo de Microsoft6 y la gente que le está dando uso para distintas terapias. Que no decaiga.

En mi pajarear en busca de conocimiento también he seguido con los temas de electrónica7 a través de los canales de Ben Eater y Element 14, pero sigo necesitando encontrarme centrado, pillar componentes, y cambiar mi estado de ánimo hacia algo un poco más activo (un poco menos vago) para empezar a llevar a la práctica algunas de las cosas que explican ahí.

Y, para terminar, y llenando huecos, como siempre, ahí estaban al rescate las charlas de las GDC8 y Dan Root9. Visionados ligeros que me permiten decir que ”técnicamente” no he incumplido el reto durante esos días. Actividades que no dejan de ser un poco placebo en cuanto a lo que se refiere al conocimiento puro. Eso no quiere decir que sean una pérdida de tiempo o que no sean interesantes, pero no dejan de ser tecnicismos con los que rellenar el expediente.

Muy mal.
Que no me pase nada ahora que empiezan los calores.

Enlaces:

1. Clases de Teoría de Matemáticas 1

2. Lógica y otras cosas
- Lógica de primer orden
- Prolog
- PL Man

3. Profesor Retroman

4. Despega RetroMadrid Academy

5. No tan locos giros de guión

6. Más sobre el mando adaptativo de la X-Box
- The Making of the Xbox Adaptive Controller
- Able Gamers
- Special Effect

7. Más electrónica
- How a transistor works
- Making logic gates from transistors
- SR latch
- How Integrated Circuits Work - The Learning Circuit

8. A tope con el GDC
- The Animation Process Of Ori & The Blind Forest
- Art Direction Bootcamp: Pantalones! Things I Wished I knew Prior to Becoming an Art Director
- Visual Effects Bootcamp: Artistic Principles of VFX
- Classic Game Postmortem: Panzer Dragoon, Panzer Dragoon Zwei, and Panzer Dragoon Saga
- Building a Living World from Ancient Ruins in Assassin's Creed Odyssey
- Classic Game Postmortem: Paperboy
- Why Fashion in (Most) Games Sucks, and Why You Should Care
- GDC Live Q&A: Lucas Pope and Return of the Obra Dinn

9. Y con Dan Root
- Alucard's Running Animation
- The Beauty of Parallax
- How to Animate a 2D Fighting Game [redux]
- Making Fluid and Powerful Animations For Skullgirls
- Animator's survival kit
- Fighters Generation
- Zweifuss, personajes de Street fighter y sus animaciones

Bajo un océano de bits, mes XVII

Este mes ha sido entretenido a la par que ilustrativo en lo referente a este reto. Pero no lo ha sido porque haya avanzado demasiado en el terreno de la programación, sino porque mi tiempo se ha centrado mayormente en buscar, probar y conocer las herramientas que se encuentran a mi disposición si quiero programar cosicas para el Commodore desde un entorno con arquitectura x86.

Podríamos decir que este mes se lo hemos dedicado a entender un poco mejor el legado de los chicos de Commodore Bussiness Machines1.

Un vez hecha esta introducción, vamos al turrón.

¿Qué herramientas tenemos a nuestra disposición?

Pues depende.

Si queremos programar en BASIC para el C642 la cosa es bien sencilla. Basta con tener el VICE y utilizar su “petcat” sobre cualquier archivo de texto plano en el que hayas introducido las líneas de código. Con esto te generará un archivo .prg que reconozca el emulador.
De premio, utilizando su comando c1541 puedes meter eso dentro de una imagen de disco .d64.
Es algo tan sencillo que ha sido lo que más me ha costado encontrar. Porque la Internet es asín.

También tenemos la opción de ejecutar “nativamente” en Linux o Windows comandos del BASIC de Commodore con CBM Basic, pero no tienes la posibilidad de usar pokes o sprites por hardware. Cosas de los sistemas operativos modernos

Si queremos ir al ensamblador3 el abanico se amplia. Sólo mirando las herramientas que aparecen en 6502.org la cosa puede llegar a ser abrumadora. Si ya vas a los foros de Lemon 64 o Commodoremania puedes perder un par de vidas tratando de hacer la criba.

Al final el tema de los ensabladores lo he dejado reducido a dos; ACME y CC65.
El primero por el nombre y porque he visto que hay varios tutoriales sobre él, y el segundo porque se encuentra en los repositorios de Ubuntu. Lo que ha terminado por decantar mi criba por ambos ha sido que existen resaltadores de sintaxis de los dos para VIM.

Si la gente no quiere liarse a “compilar el compilador de ensamblador” se puede descargar Kick Assembler, que está hecho en Java y le serviría para cualquier sistema operativo sin liarse demasiado la manta a la cabeza.
En caso de que busque algo aún más sencillo, también podría decantarse por alguno de los IDEs5 que tiene a su disposición por ahí.

Relaunch está hecho en Java, así que funcionaría tanto en Linux como en Windows o en Mac, y tanto C64 Studio como Kickass IDE funciona bajo Wine, así que tendría la papeleta solucionada en lo que respecta a cualquiera de los sistemas operativos mayoritarios sin necesidad de tener que compilar nada.
Eso sí, Relaunch no trae compilador “de serie”, pero lo puedes arrejuntar con Kick Assembler y asunto resuelto.

Porque la compilación. Vaya movida.
Si hay algo que me ha quedado claro últimamente es que no sólo tienes que aprender a programar en un lenguaje. Tienes que hacerlo pensando en el compilador que utilizarás y la arquitectura del procesador. De acuerdo a lo que he podido entender (seguramente de manera errónea) durante estas “investigación” esto es algo especialmente sensible en el caso de los compiladores cruzados.

He bajado el código fuente de distintos juegos escritos en ensamblador para el C64 y cada uno sólo puede ser compilado con la herramienta para la que fue pensado. Amigüitos, no intentéis compilar algo hecho para ACME con CC65. Y no intentéis compilar nada de CBM Prg Studio con otro ensamblador.

Pasamos a la caza de bichos6 y la cosa se complica un poco más.
Vice tenía un compilador bastante apañado en su versión 3.1 para Windows (y sólo en esa), pero desapareció en la 3.3 (la última que ha salido), donde sólo ha quedado el Monitor que te permite consultar y modificar la memoria y registros desde la línea de comandos.

Si queremos tirar de herramientas gráficas, WinVICE 3.1 funcionan bajo Wine y sigue estando disponible para su, así que por ahí podríamos tener la cosa apañada, pero también existen otras alternativas.

C64 debugger tiene versión nativa tanto para Linux como para Windows y Mac, así que mejor os ahorráis el tratar de compilarlo desde su código fuente (yo no he sido capaz). De cualquier manera, lo que aparece en pantalla nada más arrancar es tan colorido y movido que asusta.

Step 6502 sólo está para Windows, pero funciona bajo Wine, así que se puede usar sin problemas en Linux. Por lo poco que lo he tocado me ha parecido un poco… especial. Hasta donde he podido entender, arranca un emulador en blanco y en estado de pausa. Eres tú quien se dedica a meter a mano los valores hexadecimales en memoria y a avanzar “paso a paso” los ciclos del reloj. Para los muy cafeteros.

Por lo que he podido leer de Vice PDB Monitor la cosa parece interesante, pero ni he conseguido compilarlo ni he logrado que funcione su binario en Windows, así que igual toca investigar un poco más.

Como herramientas para realizar distintas operaciones7 como pueda ser hacer gráficos y caracteres o gestionar el contenido de los archivos ,d64 tendríamos SpritePad, Vchar 64 y Droid D64. Las dos primeras sólo están dispobibles para Windows pero funcionan a la perfección en Wine y la tercera está hecha en Java, así que hasta ahí tendríamos la papeleta solucionada en Linux.
Más allá de esto SpritePad, entre otras cosas, también te permite extraer los gráficos de un snapshot de VICE y Droid D64 te permite desensamblar el contenido de los discos y verlo en formato hexadecimal o ensamblador.
Un par de joyicas ambos dos.

Si eres un usuario de Mac no preocuparse, porque ahí está Actraiser y su Dustlayer8. Este señor han preparado un entorno de desarrollo para la máquina de la manzanita y, de premio tienen varios tutoriales de ensamblador con ACME.

En lo referente al aprendizaje9 también tenemos bastante en lo que rascar más allá de Dustlayer, y a ese respecto CodeBase 64 promete especialmente.

Y con esto creo que terminaríamos este pequeño repaso. Ando tentado de meterme a hacer el equivalente a una CPCtelera para el Commodore con todo lo que he ido encontrando, pero aún estoy über verde como para meterme en un embolado de ese calibre. Tiempo al tiempo.

Más allá del mundo Commodore, este mes también he seguido viendo vídeo a cholón.
Por un lado, he terminado con los de teoría de redes de Ben Eater10 que comencé el mes pasado y he seguido con los que tiene de electrónica. Lo mola todo, pero si quiero entender estas cosa de verdad tendré para un rato largo.
Por otro, y como no podía faltar, también he seguido con los de Fran Gallego11 como si no hubiera un mañana.

También he encontrado una lista de reproducción de “Matemáticas para desarrolladores de vídeo juegos”12 a la que le hincaré el diente… algún día.

Y, ahora sí, yo diría que ya habéis tenido suficiente por hoy.

Enlaces:

1. La famiglia
- Gracias por todo, Jack
- Chuck Peddle, father of the personalcomputer
- Bil Herd

2. Basic de C64 en x86
- The Versatile Commodore Emulator
- Compilando Basic de Commodore gracias a VICE
- Manual de petcat
- Manual de c1541
- CBM Basic GitHub

3. Ensablador de 6502 en x86
- Herramientas para C64 - 6502.org
- Acme GitHub
- Vim Acme GitHub
- CC65 GitHub
- Vim CC65 GitHub
- Kick Assembler

5. IDEs:
- Commodore IDE for Windows 32 and Linux
- K2 Devel
- C64 Kickass IDE
- Relaunch 64
- Info en C64 Wiki
- Unity 8 Bits
- C64 Studio
- CBM Prg Studio
- C64 Kickass IDE

6. Debug de C64 en x86
- Using the Vice monitor
- C64 Debugger
- Step 6502 GitHub
- Step 6502 en CSDB
- Vice PDB Monitor GitHub
- Vice PDB Monitor en CSDB
- Debugging 6502 assembly doesn’t have to be awful

7. Más herramientas
- Sprites con SpritePad
- Droid D64
- VChar 64 en GitHub
- VChar 64en CSDB

8. Dustlayer

9. Más tutoriales
- CodeBase 64
-
C64 Brain
- A full C64 game in 2013
- The bear essentials developing a Commodore 64 game

10. Más Ben Eater

Terminamos lo de las redes
- Networking tutorial 08 of 13 - The Internet Protocol
- Networking tutorial 09 of 13 - ARP: Mapping between IP and Ethernet
- Networking tutorial 10 of 13 - Looking at ARP and ping packets
- Networking tutorial 11 of 13 - Hop-by-hop routing
- Networking tutorial 12 of 13 - TCP: Transmission control protocol
- Networking tutorial 13 of 13 - TCP connection walkthrough

Electrónica y semiconductores
- Digital electronics tutorial
- How semiconductors work
- Stepping through a program on the 8-bit breadboard computer
- Comparing C to machine language
- Programming Fibonacci on a breadboard computer
- Building an 8-bit breadboard computer

11. Más Profedor Retromán

Ensamblador Z80
- Cargadores de Casete Propios
- Creando un Micro-GameEngine 1
- Creando un Micro-GameEngine 2
- Entidades con comportamientos variables
- Controlando un personaje con teclado
- Múltiples ficheros fuente, includes, símbolos globales y macros

C++
- C++ - Rvalue references, move constructor & move assignment operator

General
- Replanificación y entrega de producto
- ¿Por qué enseñar a programar en ensamblador?
- Clases de Teoría de Matemáticas

12. Math for Game Developers

Bajo un océano de bits, mes XVI

Dispérsense, aquí no hay nada que ver.

Estoy en una de esas épocas. En una de esas temporadas en las que soy incapaz de concentrarme para poder leer algo de manera continuada. Uno de esos lapsos de tiempo que pueden llegar a durar años.
Aunque mucho me temo que el problema no es únicamente ese.

Reviso mi perfil de Goodreads1 y veo que en estos momentos tengo en curso la lectura de diecinueve libros, trece de los cuales han sido añadidos como apoyo para este reto.
Durante los primeros pasos de este reto leí cuatro libros, dos de los cuales sólo dos de ellos eran puramente técnicos. Ambos me costó un horror terminarlos y, una vez despachados, seguía sin tener las cosas demasiado claras.

Es increíble la cantidad de capas de abstracción que es necesario atravesar para llegar hasta los niveles de concreción que requiere un programa. Y el problema es igual de complejo en ambos extremos.

La cantidad de factores que debes tener presentes si quieres llegar hasta los niveles más concretos es abrumadora. Cuanto más profundizas en esos niveles todo es a la vez más abstracto y más concreto, y quiero llegar hasta esos el último de ellos.

En estos momentos el juego es lo de menos, la programación sólo es un paso para entender lo que pasa dentro de la máquina. Quiero convertirme en un ingeniero sin hacer la carrera. Quiero un atajo para llegar hasta mi destino, pero para ciertos recorridos no hay un camino fácil.

Cada párrafo de cada uno de los libros que tengo empezados me ha hecho ir hasta sus fuentes, ir hacia un nivel anterior, aparcarlo y comenzar a leer otro libro que no tardo en dejar por otro. Y eso no tiene ningún sentido.
Necesito ir hasta el principio pero… ¿dónde está?.
Corrijo. La pregunta no es dónde está ese comienzo, sino dónde estoy yo. Si encontrar la respuesta a la segunda pregunta no puedo plantearme la primera.

Pero aquí hemos venido a hablar de mi plan. Sí, ese, y el otro, y el otro también.
Como decía el sabio, no existen planes perfectos, sólo intenciones perfectas.

Continúo con los vídeos del Fran Gallego2 y me parece que tengo la comprensión al alcance de la mano, a una interrupción sináptica de distancia, pero cuando trato de concretar sus palabras veo que realmente todo está mucho más lejos.
Bajo un nivel y veo a Ben Eater3. Todo se me hace más cercano y lejano al mismo tiempo, más concreto. Pero, a pesar de su tamaño de la circuitería, cuando trato de extrapolar lo que veo funcionando a la escala de las arquitecturas modernas, todo es abrumadoramente pequeño y se mueve a una velocidad tal que no soy capaz de visualizarlas.

Y, más allá de esto, para interiorizarlo todo, para terminar de encajar las piezas, tengo que mancharme las manos. Tengo que hacerlo yo de principio a fin. Y sé que en cuanto me ponga a ello encontraré nuevas carencias, que tendré que volver a bajar hasta otro nivel.

Voy bajando una y otra vez sólo para terminar regresando siempre hasta el punto de partida. Necesito ensuciarme las manos en algo que pueda terminar. En algo que pueda llevar a cabo en un periodo de tiempo concreto.

Así pues, una vez más, ¿cuál es el objetivo?
Supongo que el de siempre… ver hasta donde llego.
De acuerdo, reformularemos la pregunta:
¿Ensamblador, C++?
¿Qué camino vas a seguir?
¿Hacia dónde vas?

Por el momento seguiremos con ensamblador. En cuanto haga funcionar en Vim el resaltado de la sintaxis4 para x86, z80 y 6502 (y que no se pegue con el precompilador de YouCompleteMe) empezaré a meterme con los registros de esos cacharros.

A ver si con un poco de suerte la parada lectora termina y puedo continuar con alguno de los libros que tengo empezados.

Enlaces:

1. Mis lecturas en curso

2. Más profesor Retromán
Ensamblador
- Optimizando la Memoria en Amstrad CPC (Z80) #2
- Números pseudo-aleatorios en Amstrad CPC (Z80)
- Optimización del Compilador para Amstrad CPC (Z80)
- Físicas con coma fija en Amstrad CPC (Z80)
- Optimizando en Amstrad CPC (Z80) #3
- Optimizando la memoria en Amstrad CPC (Z80) #3
- Empezando con Ensamblador del Z80
- Empezando con Ensamblador del Z80 (II)
- Empezando con Ensamblador del Z80 (III)
- Depurando el salto del personaje en ensamblador de Z80
- Múltiples ficheros en ensamblador de Z80 con CPCtelera
- Obstáculos en movimiento en ensamblador Z80
- Teoría: Colisiones entre Bounding Boxes
- Tip: cómo optimizar detección de colisiones por frecuencias
- Revisión del proceso de ensamblado y ficheros
- Convertir y dibujar sprites en ensamblador con CPCtelera
- Convertir y dibujar mapas de tiles en ensamblador con CPCtelera
- Detección de colisiones en ensamblador Z80
- Estructuras de datos y objetos en ensamblador Z80 con IX #1
- Estructuras de datos y objetos en ensamblador Z80 con IX #2
- Estructuras de datos con macros en ensamblador Z80
- Reproduciendo música en ensamblador Z80 con CPCtelera
- Música por interrupciones en ensamblador Z80 con CPCtelera
- Revisión de dudas y Consejos en ensamblador Z80
- Efecto de scroll por software en ensamblador Z80
- Scroll por software + double buffer en ensamblador Z80
- Llamar a funciones en C desde ensamblador del Z80
- Revisión del Micro-GameEngine
C++
- C++: Sensores para Enemigos
- C++: Memoria dinámica, ejercicio de nivel intermedio 1
- C++: Memória dinámica, arrays y alineamiento
- C++: Profiling basico, optimización y caché
- C++: Gestión Avanzada de Memoria con Placement New
- C++: Ejercicio. Independizar el render
- C++: Strategy, pimpl y façade para independizar un renderer
- C++: Múltiples renderers. Análisis de código
Juegos de CPC para Android
- Crea videojuegos en Amstrad para millones de jugadores en 2019

3. Ben Eater
Redes
- Networking tutorial 01 of 13 - Sending digital information over a wire
- Networking tutorial 02 of 13 - Intro to fiber optics and RF encoding
- Networking tutorial 03 of 13 - Clock synchronization and Manchester coding
- Networking tutorial 04 of 13 - Analyzing actual Ethernet encoding
- Networking tutorial 05 of 13 - The importance of framing
- Networking tutorial 06 of 13 - Frame formats
- Networking tutorial 07 of 13 - Lower layers of the OSI model
Construyendo un ordenador de 8 Bits
- Learn how computers add numbers and build a 4 bit adder circuit
- Programming my 8-bit breadboard computer

4. Ensamblador para VIM
- Ensamblador de x86 para Vim
- Ensamblador de z80 para Vim
- Ensamblador de 6502 para Vim

Bajo un océano de bits, mes XV

Tras mucho demorarlo, finalmente, llegó el día.
Y quizás alguno se pregunte... ¿qué día? ¿el día de qué?.

A lo que respondería: El día en el que bajamos de nivel. Una respuesta que, en sí misma, tampoco es que diga gran cosa.

No, no voy a bajar el nivel de presión (algo que ya es de por sí bastante bajo). No voy a dejar esto.
Bueno, no voy a dejarlo… aunque sí.
Con esta respuesta tan intencionadamente ambigua lo que quiero decir es que abandonamos un nivel de abstracción para sumergirnos en la dirección de las simas más profundas. Bajamos un peldaño idiomático, nos dirigimos hacia las fosas abisales del ensamblador.
Un viaje de destino incierto y que veo complicado que finalice antes de que este reto llegue a su hipotético final.

Y la culpa de todo esto la tiene un hombre; Fran Gallego, el Profedor Retromán1
Como decía aquel, cada vez que veo uno de sus vídeos me doy cuenta de que no sé nada. No sé lo que sucede en la circuitería o en el procesador, no sé la cantidad de recursos que estoy consumiendo con cada comando, no sé en qué está convirtiendo el compilador las cosas que yo puedo considerar "ordenadas y claras".
No sé lo importante. No sé aquello con lo que tendría que haber empezado.

Así pues, toca cambiar de rumbo y profundizar, pero no a tontas y a locas. No voy a ponerme ahora a estudiar la arquitecturas de los procesadores x642, sino que me encuentro camino de algo mucho más básico y molón; Las tripas del MOS 65103, las entrañas del Commodore 64. Aunque, claro está, esto era algo que ya se veía venir de lejos.

Por supuesto, tengo intención de volver más adelante al C++, pero antes quiero entender lo que sucede entre bambalinas. Quiero saber cuántos ciclos de reloj le cuesta a la máquina ejecutar una orden, cuántos bits ocupan mis artefactos, cómo hablan entre sí cada uno de los elementos del ordenador, y esto es algo que me va a ser imposible con las arquitecturas modernas, no sólo por su complejidad intrínseca, sino también por la capa de abstracción y ofuscación que supone el mismo sistema operativo.
Confío en que, una vez entienda este tipo de cosas, ese conocimiento me ayudará a comprender la información que me proporcionan herramientas4 como Valgrind, C++ Insights o Compiler Explorer. Seré capaz de entender la razón detrás de la “Regla de los tres” (y la de los cinco). No quiero limitarme a repetir sin criterio alguno lo que he leído en los libros o los tutoriales.

Y, sí, también, y por supuesto, tengo un plan.
... sí, otro. Ya sabéis cómo va esto.

Borrón y cuenta nueva.
He comenzado a leer los manuales oficiales que venían con el ordenador5. Empezaré por el “Commodore 64 Users Guide” y continuaré por el “Programmer's Reference Guide”. Después de eso ya veré por dónde sigo, porque documentación hay para aburrir.

También ha dado comienzo la parte divertida, la del acopio de herramientas6, el tema de entenderlas, realizar una criba y saber cómo, dónde y cuándo usar cada una de ellas ya es otro mundo.

En algún momento indeterminado del futuro, muy probablemente cuando termine con los dos primeros libros, volveré a los curros de ensamblador para CPC del señor Gallego y trataré de ir alternando y replicando los ejercicios que propone para el Z80 con el 6510. Tengo claro que sus arquitecturas no se parecen en mucho, pero ambos son procesadores sencillos. Si logro entender ambos no sólo tendré una parte del camino recorrida ante lo que quiero hacer, sino que me aportaría una base no sólo para plantearme proyectos para el CPC o el Commodore, sino también para Spectrum, MSX, NES, Game Boy y Master System.
Soñar es gratis y los planes tampoco cuestan dinero. El tiempo y mi capacidad para comprender y asimilar la información ya son otro asunto.

Así que aquí me tenéis, a mi edad, escribiendo programas en BASIC para hacer que una pelotita recorra la pantalla de un lado a otro parpadeando como una condenada.

Enlaces:

1. El culpable
- Optimizando en C para Z80 en Amstrad CPC #1
- Optimizando en C para Z80 en Amstrad CPC #2
- Optimizando la memoria en Amstrad CPC #1
- Renderizado Sincronizado en Amstrad CPC
- Interrupciones y música en Amstrad CPC
- Estructuras de datos y funciones en ensamblador Z80 (Amstrad CPC)
- Depurando programas en Amstrad CPC (Z80)
- Renderizado con Double Buffer en Amstrad CPC
- Tips rápidos de programación en ensamblador 1
- C++ : Optimizando accesos básicos a la memoria caché
- C++ : Entendiendo y optimizando std::vector
- C++ : La regla de los tres, constructores y copias
- C++ : Constructores Delegados
- C++ : Operador asignación con copy-and-swap idiom
- C++ : Entendiendo emplace_back y placement new
- C++ : Copy-elision y Return Value Optimization (NRVO / RVO)

2. Gritones de transistores

3. MOS 6510
- El cerebro
- La máquina

4. Herramientas para C++
- Compiler Explorer
- CPP Insights
- Valgrind - Cachegrind manual
- C++ rule of three

5. Los libros
- Commodore books.
- Commodore 64 User's Guide
- Commodore 64 Programmer's Reference Guide
- Anatomy of the Commodore 64
- Assembly Language Programming With The Commodore 64
- What's Really Inside the Commodore 64
-
Cómo programar en Ensamblador x86

6. Herramientas para el Commodore
- CodeBase 64
- A$$emble it!
- C64 Dev kit
- CC65
- CC65 Documentaci
- CC65 en GitHub
- Relaunch 64
- Relaunch 64 en Github
- Relaunch 64 binarios de la última versión
- XA (xa65)
- Awesome C64

Bajo un océano de bits, mes XIV

Dejamos esto hace cuatro semanas con los ánimos a tope y lo retomamos un poco de aquella manera.

Después de la última entrada la cosa continuó mejorando un poco. Encontré un “fuga de memoria”1 en la clase dedicada a dibujar las imágenes y fui capaz de corregirla. Me las prometía muy felices hasta que llegó el momento de gestionar los eventos2 y determinar cómo iban a ser las interacciones con la aplicación.

Hasta el momento había trabajado con el código que se encargaba de estas tareas que venía en el curso, pero a la hora de tratar de hacer cosas distintas de cambiar un valor por otro la cosa se empezó a torcer.

Me explico.

Mi bucle principal es muy sencillo:

1 - Miro todo lo que pasa en el sistema y, mientras el valor “Salir” no tenga un valor verdadero, hago lo que se encuentra definido en un bucle infinito.

Bucle principal

Recolección de eventos

2 - Pregunto si se ha pulsado alguna tecla.

Captura de estado del teclado

3 - Se cargan las músicas e imágenes del modo de juego que tenga seleccionado.

Modos des programa

4 - Se vuelca todo eso en la pantalla principal.
5 - Le digo que no se flipe demasiado y que no pase de las 100 pintadas por segundo.

Hasta ahora no me había hecho falta precisión alguna a la hora de controlar la respuesta del teclado. Con que al pulsar una tecla esta asignase a una variable un valor concreto me era suficiente

Acción a realizar al pulsar una tecla en la presentación
Pantalla de presentación

Sólo había un estado posible.

Pero ahora, al ir al menú en sí mismo, la cosa se complica. Tenemos tres estados posibles:

Acción a realizar al pulsar una tecla en el menú
Menú principal

Cada vez que pulso una tecla, el valor de “opcion” (sin tilde), tendría que aumentar o disminuir en uno. Sencillo, pero no hay manera.

Y no hay manera porque el procesador es muy rápido. Entre que pulso la tecla y la suelto pasan varios ciclos de reloj y la pantalla se ha redibujado más o menos entre 4 y 10 veces (acordaos que le he dicho que, como mucho, lo haga 100 veces por segundo, pero aún así es demasiado para esta manera de gestionar las cosas). Así que, cada golpe de teclado, implica que el valor de “opcion” se incremente o disminuya en ese número.

He hecho un apaño con la función “precision” (también sin tilde)… pero no es muy precisa que digamos y sigo atrapado en este punto desde el mes pasado.
La documentación de SDL a este respecto3 no me ha ayudado mucho, el código en el que me baso tampoco. La manera que tiene de controlar el movimiento del cursor no tiene nada que ver con la mía, y no quiero copiar tal cual la suya. Como suelo decir siempre por aquí, quiero entenderlo.

Y no deja de ser una pijada. A la hora de mover bichos por la pantalla esto no importa nada porque, a pesar de trabajar con la resolución de un Commodore 64, recorrer los 384 pixels de altura de la pantalla o los 272 de anchura es una tarea mucho más sencilla de gestionar, pero quiero que esto funcione de la manera en la que lo he decidido (o rehacerlo todo, pero que todo quede como yo decida en base a unas razones que considere razonadas y aceptables).

Por supuesto, podría buscar otras librerías para hacer esto, o podría ponerme a copiar a otros. Podría dedicarme a ver los vídeos de Jonathan Blow4 o Fran Gallego5. Podría mandarlo todo a paseo y meterme con Unity 8 Bits6. Mirar como afronta estos problemas un centenar de personas pero, por más cosas que me vayan descubriendo las píldoras de conocimiento que van soltando, quiero hacerlo a mi manera.

Y no hay mucho más que decir por ahora más allá de…
Continuará.

Enlaces:

1. Memorias a la fuga

2. Los eventos
- Event
- Event loop
- Event driven programming

3. SDL y los eventos
- SDL Events
- Handling the Keyboard

4. Jonathan Blow y sus Game Engina Programmng

5. Fran Gallego
- C++: Optimizando costes básicos de acceso a memoria
- Fuentes propias de texto y código absoluto
- Volatile
- Compiler Explorer/a>

6. Unity 8 Bits

Bajo un océano de bits, mes XIII

Podría decirse que hemos empezado bien el año en lo referente al C++.
Podríamos decirlo, claro, pero, de hecho, mentiríamos (al menos parcialmente).

Porque el año, en sí mismo, empezó regulero.

Habíamos dejado este tema, como de costumbre, con una mezcla de esperanza y frustración sumada a las dudas habituales. Con la lectura de un libro, Programming - Princples and Practice Using C++, que sigue ahí comienzo polvo virtual en su página doscientos (de 1312).

Terminé el año pasado con la moral a media asta y con la sensación de que “todo mal”, el reto, el código, mi comprensión lectora y mi capacidad para llevar esto hasta algún punto al que merezca la pena llegar. Pero bueno, el reto no era llegar hasta ningún lado concreto sino ver hasta dónde conseguimos llegar, así que… veamos.

Este último mes ha seguido la misma tónica que los anteriores; una sucesión de pequeñas alegrías, hostiazos de realidad y, con suerte, algo de aprendizaje y recapacitación.

Comencé consiguiendo hacer algo que había estado persiguiendo desde hace tiempo, una función que me permitiese invocar a los objetos almacenados en los vectores de recursos por su nombre y no por su identificador.
A la hora de determinar el funcionamiento de la aplicación no supone nada. Es más, probablemente suponga un pequeño incremento en el consumo de recursos del ordenador, pero tanto a mi como a cualquier hipotético usuario que pudiese haber de este “motor” que estoy haciendo, nos haría las cosa un poco más sencillas a la hora de invocar a esos recursos.
Tenía la solución en la periferia de mis neuronas desde hace meses pero no ha sido hasta hace un par de semanas que por fin logré agarrarla.
En el código de la aplicación en la que me estoy basando esto estaba solucionado con un enumerador1, pero esta solución no me servía si quería que la clase que se dedica a gestionar de los recursos fuese dinámica (o lo que es lo mismo, no tener que tocarla ni recompilarla cada vez que añado un recurso adicional).

Tras jugar con vectores que contuviesen objetos “mixtos” (conjuntos de datos de tipo cadena texto y objetos del tipo de objeto que quería devolver) juntados en un "struct"2, al final opté por tener dos vectores por por cada tipo de objeto; uno para los nombres y otro para los objetos en sí mismos.

Cargando los recursos

Con esto puedo tener una única función consultora a la que invocan aquellas que devuelven el tipo de objeto concreto (Imagen, Color, Fuente, Sonido, Canción, etc...).

Buscando a los recursos

Con esto no pierdo la posibilidad de llamar a los objetos de la manera anterior, pero sí que me ahorro el tener que mirar a qué número corresponde cada uno de ellos:

Invocando a los recursos

Mientras hacía esto también rehice por completo la clase que se dedicaba a pintar el texto. Aún tengo que ser capaz de lograr que me muestre cosas como tildes y otros caracteres especiales, pero esa parte la voy a dejar para un poco más adelante.

Y la tuve que rehacer porque había cometido un error muy gordo a la hora de interpretar qué significaba definir una variable como “static” y eso me había vuelto un poco loco.
Por culpa de esto las cosas empezaron a fallar cuando di comienzo a la creación de la siguiente clase, la que se encarga de gestionar la animación de los objetos.

Cuando esta clase era invocada por más de una animación pasaba olímpicamente de todo valor posterior posterior al primero. Poner diferentes variables “static” en un único archivo no daba problema, pero cuando quería crear más de una instancia de cualquiera de ellas el resultado no era bonito (generalmente un pete en ejecución, que no en compilación).

Tras mucho leer y no entender, en un foro de Arduino vi lo más parecido que encontré a una respuesta, pero no era capaz de aterrizar el código unitario que presentaban en una estructura de clases.
Después de volverme loco, de hacer mil pruebas y de rehacer doscientas veces las clase “Menu”, “Animacion” y “Texto” logré hacer funcionar aquello, pero seguía sin estar convencido de cómo había quedado, y con razón.
Serendipias de la vida, esa misma noche las piezas encajaron en mi cabeza. La cosa había funcionado, sí, pero había sido por casualidad.

Estoy convencido de que lo habré leído mil veces en todos los libros que me he echado encima, pero no fue hasta esa noche con la cabeza apoyada sobre la almohada que las piezas encajaron y entendí una más tanto el papel que cumplen la declaración de variables como privadas y la función del constructor3.

Al día siguiente cambié las tres clases y todo funcionó. Rehice todo aquello que funcionaba de chiripa y quité todos los “static” que sobraba y funcionó, volví a replantearme las clases principales… y falló, pero porque me equivoqué con la sintaxis, no por un error de comprensión.

Y así he llegado hasta hoy a tope de ánimo. No hay como el ser cabezón para se capaz de derribar las paredes de tu estupidez gracias a tu férrea determinación y tu sólida estructura craneal.

Enlaces:

1. Ha llegado el enumerador

2. Las estructuras y sus cosas

3. De constructores y objetos

Bajo un océano de bits, mes XII

Cuando estamos apunto de llegar al ecuador de esto, la cosa sigue sin avanzar demasiado.

La parte de mostrar texto en pantalla ya está casi finiquitada. Si alguien me llega a preguntar hace un año acerca de lo que creía que me iba a costar más, esta respuesta habría sido la última que me habría venido a la cabeza. Por supuesto, técnicamente apenas he empezado aún con esto, así que a ver cuánto me cuesta el editor en el momento en el que me ponga con él.

El mes pasado comentaba por aquí que había comenzado a leer el “Game Programming Patterns”, pues bien, ese libro también ha quedado en suspenso para mejor ocasión.
De la misma manera que llegué hasta él mientras leía los artículos de “Writing a Game Engine from Scratch”, su lectura me llevó hasta otro libro más; “Programming: Principles and Practice Using C++”1.
Otro libro más cuya lectura he dejado aparcada… por el momento.

Cada vez que hago una jugada de estas me invade el deja vu. Empezar a leer y tener miedo de no entender lo que he escrito cuando vuelva en “x” tiempo. No falla, cuando me encuentro con un problema no dejo de tener la sensación de que estoy remoloneando. De que en cuanto se cruz en mi camino algo que no soy capaz de solucionar de cabeza dejo que me gane la inseguridad y siento la necesidad de llenar huecos que muy probablemente no estén ahí. De buscar fuera soluciones que es muy posible que ya tenga.

Porque, al final del día, la cosa es que la idea para solucionar este caso en concreto (y otros tantos problemas indeterminados) estaba ahí. Lo podía ver vagando por los sectores periféricos de mi cabeza, pero cada vez que pensaba sobre él no veía la forma de aterrizarlo. No era capaz de encontrar el momento de ánimo necesario para concretarlo. De pillar papel y boli para plasmar el problema de una forma visual y trazar las posibles soluciones.

Aunque también puede ser que me encuentre cómodo con esto. Jugueteando una y otra vez con cosas cuya resolución sí que me veo capaz de llevar a cabo. Refinando y perfeccionando lo que ya tengo para que cumpla un ideal que no tiene demasiado sentido.
Seguramente será una suma de todo eso, no lo sé.
¿Dónde termina la pereza y empieza la inseguridad?, ¿Donde se traza la línea entre la depuración y el TOC?

Lo que tengo claro es que no me gusta cómo se “lee” mi código. Líneas muy largas para terminar escribiendo cuatro variables. Vueltas que se me hacen muy rocambolescas para hacer cosas que en mi cabeza parecen sencillas. La forma en la que estructuro mi modelo de datos hace que el acceso a ellos sea un poco ortopédico, pero si simplifico una parte la otra se vuelve más confusa.
Igual es así como “tiene que ser”, pero me cuesta horrores llegar a un consenso conmigo mismo y conseguir decidir cuál de mis partes es la que tiene que ceder. La historia de mi vida.

En fin. Como empezaba diciendo, la clase que dibuja el texto ya (casi) está. Y digo casi porque ya está la parte dedicada “renderizarlo” ajustado a izquierda, derecha y centrado en la pantalla, pero no la que se encargaría de centrar el texto en algún recuadro concreto que no ocupe todo el ancho. Algo que por ahora no necesito, pero que quiero tener listo.

Aparte de esto, también tengo que extraer de ella (y de la que se encarga de pintar los gráficos) el componente que se encarga de controlar el ciclo de rotación de los textos y sprites; la “animación estática”. Un código que ahora mismo tengo en ambas clases, ergo, está duplicado, por lo que se puede (y debe) sacar de ahí.

Y básicamente para esto es para lo que ha dado este mes.
Por supuesto, también ha habido unos cuantos GDCs2, ha salido esa preciosidad de los barceloneses Nomada Studio que es Gris3, el señor Benjamin Heckendorn ha desmontado el mando “adaptativo” de Microsoft4, la gente de Casual Bits ha sacado con un año de retraso su Battle Princess Madelyn5 y yo los odio a todos muy fuerte

Enlaces:

1. Programming: Principles and Practice Using C++

2. Los GeDeCes del mes
- What Wikipedia Doesn't Know Can Hurt You: Writer Research Skills
- Classic Game Postmortem: Sid Meier's Civilization
- Classic Studio Postmortem: Lucasfilm Games
- Classic Game Postmortem: LucasFilm Games' Loom
- The Living World of The Witcher 3: The Wild Hunt
- Classic Game Postmortem: Deus Ex

3. Gris
- Nomada Studio
- GRIS - Launch Trailer
- The Animation of Gris

4. What's Inside the Microsoft Adaptive Controller

5. Battle Princess Madelyn

Bajo un océano de bits, mes XI

El mes pasado dejábamos esto con una duda: ¿fuentes o testing?.
Y, la respuesta a esta pregunta es, como de costumbre, ninguna de las anteriores.

En su lugar me puse a mirar patrones de programación en C++ orientados a la creación de vídeo juegos.

Regresando a una de esas entradas que tenía empezadas desde hace años1 llegué hasta otros textos. Más concretamente hasta un libro2 que puedes comprar, leer online, o descargarte desde GitHub.

El libro está escrito en un tono desenfadado pero tengo con él el mismo problema que con otros tantos: No soy capaz de entender por completo los ejemplos de código que muestra.
Los textos que preceden a los ejemplos son interesantes, y puede entrever más o menos lo que se pretende con las muestras, pero no veo cómo integrarlos en mi código. Aparte de esto, no sólo se dedican a defender a lo suyo, sino que también hablan de las filias y fobias de su autor, algo que he visto que es muy común también en las entradas dedicadas a este tipo de temas en Wikipedia. Dependiendo de a quién leas cualquier cosa es buena o es una mierda.

Tras terminar con el tercero de los patrones que mencionaba este libro decidí seguir buscando más lectura acerca de aquel asunto fuera del este texto. Por un lado, el tema del encolado de eventos era algo sobre lo que ya había leído un poco, aunque de buenas a primeras se me hacía un tanto complejo de hacer con mi nivel actual. Por otro, creo que va a ser lo que me va a hacer falta a la hora de actualizar ciertas variables cuando implemente la pantalla de configuración, o a la hora de actualizar los datos de la clasificación de jugadores.

El concepto del Sujeto/Observadores se me hacía algo más sencillo que las colas de eventos, así que decidí profundizar un poco más… en ambos3.

Porque sólo con los ejemplos del libro se me veía capaz de terminar de entenderlo. Así pues, me puse a buscar otras implementaciones… sin erótico resultado. Aún estoy muy verde en esto.

Casi todas entradas hablan acerca de las bondades del polimorfismo y las clases virtuales4. Temas de C++ en los que aún no he profundizado y que me hacen pensar si debería retomar el libro de Stroustrup sobre la última versión de este lenguje.

Al final la decisión fue… lo habéis adivinado: No hacer ninguna de estas cosas.
Quizás cuando termine con el menú. Algo para lo que me queda ¿poco?.
No. No me queda poco.

Las últimas dos semanas me he dedicado a crear la clase que dibujará los textos en pantalla. Algo que parecía ser sencillo pero que no lo es. Creía tenerlo cuando me encontré con ciertas particularidades de las variables estáticas dentro de las clases a la hora de trabajar con Superficies de SDL (o, al menos, con SDL 1.2).

Si declaro la superficie de origen (donde “cargo” el texto antes de que sea pintado en pantalla) como estática, no se actualiza aunque el en el siguiente ciclo le envíe un texto distinto. Si no la declaro como estática el programa se autoinmola al rato como ya me hacía en su momento la animación del menú. La misma característica que me salvó en un caso me putea en el otro.
Una vez con esto claro, tengo que replantearme la manera en la que iba a almacenar el texto dentro de mis archivos JSON. De ser líneas independientes tengo que planteármelas como si todo el texto que va a ir rotando en pantalla fuese una única imagen. Un mural del que voy ir mostrando a recuadro a recuadro. Esto, claro está, siempre que no utilice otra biblioteca de funciones que no sea SDL6 para el pintado del texto.
Pero esto es algo que, por el momento, quiero evitar. Vamos a la vía dura.

Así pues, la cosa sigue más o menos como el mes pasado. Bueno, miento.

Ya he creado la pequeña clase que se encargará de pintar la pantalla de presentación previa al menú, la que se dedica a gestionar en qué modo de juego nos encontramos, y la dedicada a gestionar la reproducir de la música.
Estas tres clases no me costó demasiado hacerlas y todas ellas funcionan correctamente, aunque aún tengo que conseguir que se pase desde la presentación hasta el menú cuando se pulse cualquier tecla, botón del pad, o se mueva el ratón.

A pesar de que en las últimas entradas no he puesto nada a este respecto, también he seguido viendo vídeos de las GDC7, al igual que alguna que otra charla curiosa8 (que siguen haciendo que quiera ponerme a aprender ensamblador).

Esta semana también ha salido otro uso para el controlador de Microsoft para gente con discapacidades. En este caso para usarlo en la Switch9. Parece que aunque los grandes no se mueven demasiado se puede confiar en la comunidad.

Y más o menos esto es todo. A ver por qué derroteros me estoy moviendo cuando llegue la última entrada de este primer año para el reto computacional.

Enlaces:

1. Writing a Game Engine from Scratch I

2. Game Programming Patterns
- La web del libro
- Su ficha en goodreads
- Y su Github

3. Observador o colas de mensajes
- El observador (no confundir con el personaje de mis relatos)
- En Wikipedia
- Powerful C messaging/
- How to implement and use a message queue in your game
- Game programming tutorial messaging systems in C
- Publish–subscribe pattern
- Understanding and Implementing Observer Pattern
- Setting up msysmingw build system for compiling sdlopengl applications

4. Más cosas de C++
- Polymorphism
- https://en.wikipedia.org/wiki/Virtual_class>Clases virtuales

5. Estatismo del malo

6. GUI Without Extravagant Nonsense

7. GDC
- GDC 2018: Classic Game Postmortem: 'The Bard's Tale I and II'
- Classic Game Postmortem: Gauntlet
- GDC Classic Postmortem: Warren Robinett's Adventure
- The Journey to Creating SHANK
- Yars' Revenge: Classic Game Postmortem
- The Shapes in Your Story: Narrative Mapping Frameworks
- Girl Games of the 1990s: A Retrospective
- Classic Game Postmortem: Alone in the Dark
- Classic Game Postmortem - Raid On Bungeling Bay

8. Y amigos
- Renderizando tilemaps con scroll por software [GameDev asm Z80][5.4][2018]
- How we fit an NES game into 40 Kilobytes

9. Nintendo joins the limited-mobility club with Xbox Adaptive Controller (unofficially)

Bajo un océano de bits, mes X

Seguimos avanzando sin movernos del mismo lugar, cambiándolo todo sin que sea apreciable desde el exterior.

Datos. Necesito datos1.

Durante este mes me he centrado en sacar todos los valores que puedan ser utilizados en mas de un lugar fuera del código. Aparte de eso, el “contenedor maestro” que había creado para abarcar a todos los objetos se ha visto separado en cinco. Todo eso y poco más en esta edición de “Bajo un océano de bits” en su entrada más ¿técnica?.

Aún estoy dando pasos de bebé en esto de la programación en general, y el C++ en particular, pero estoy comenzando a “entender” estos lenguajes. Me estoy dedicando a jugar con ellos. Porque, por mayor que sea el misticismo que le queramos dar, la programación no deja de ser eso, otro idioma que tenemos que aprender a hablar, leer y escribir. Otra manera de describir las cosas.

Cuanto más profundizo, más claro tengo que es una cuestión de tiempo, práctica, paciencia, inventiva y objetivos acotables. Cuanto más básico es el nivel del código que leo, más me doy cuenta de que… tiene sentido. Que “eso habría sabido hacerlo yo”.
Si con el dibujo los engranajes de mi cabeza aún no han hecho “click”, parece que estos sí que van cogiendo velocidad.

Y es entonces cuando pienso que me estoy perdiendo algo. Que no puede ser tan sencillo. La historia de mi vida.

Pero la cosa es que muevo y reescribo, retuerzo las líneas en otro sitio y siguen funcionando. Que siguen haciendo lo que tenían que hacer (o al menos lo mismo que hacían cuando las describí de otra manera). Y eso hace que me sienta bien.

No dudo de que, hasta cierto punto, este no-avanzar de los últimos meses se debe a que he encontrado algo similar a una zona de confort, pero creo que lo que estoy haciendo tiene sentido. Tardaré más en ver resultados en la pantalla, pero tengo claro que los pasos llevan la dirección correcta.

Y claro, luego me pongo a leer más cosas y me doy cuenta de que, si quiero hacer las cosas bien desde el principio, voy a tener que esperar mucho más hasta que lleguen esos resultados y sean “visibles” (o jugables). No quiero empezar con pasos apresurados y darme cuenta a medio camino de que tenía que haber hecho algo distinto desde el principio.
No sé cuántas veces me han dicho que estoy tomando el camino difícil, pero yo no he venido hasta aquí a hacer sólo las cosas fáciles.

Quizás por deformación de mi trabajo en el día a día, sigo pensando en la arquitectura del programa a alto nivel. En tratar de desglosar los componentes de la forma más general, abstracta y óptima posible. De decidir a qué capa correspondería cada uno de ellos. En que todo lo que haga ahora sea reutilizable para cualquier cosa que pueda hacer después.

Dentro del nivel más básico de esta arquitectura que voy improvisando con cada nueva revisión, he situado los datos en crudo; lo que quiero que esté fuera del código. Un contenedor al que, en un alarde de originalidad, he dado en llamar “Datos”.

Para ello he creado una clase central a la que he llamado (redoble de tambores) “Acceso_datos”. Una clase que se basa en archivos de texto plano en el que iré insertando los valores que usará el programa y para cuya estructura he decidido utilizar JSON2

Por el momento Acceso_datos sólo tiene una función llamada “Leer”, que me devuelve los valores guardados en los archivos y los convierte en variables a utilizar por el código. Cosas de un amplio espectro que abarcan desde el idioma hasta la anchura de un rectángulo en el que voy a dibujar un sprite o la clasificación de los jugadores. Más adelante tendré que crear los métodos “Actualizar”, “Crear” y “Reiniciar”.

Nada más arrancar el programa, lo primero que hace es inicializar este contenedor, con lo que leerá cuatro archivos JSON con nombres tan genéricos como “datos_globales”, “datos_recursos”, “datos_controles” y “datos_clasificacion”.

Tras la creación de “Datos” le llega el turno al segundo elemento central que he creado. Algo que, en un nuevo alarde de originalidad, he bautizado como “Sistemas”. Este contenedor se encarga de albergar los objetos que hablan con los dispositivos de entrada y salida. Por el momento, dentro de “Sistemas” se instancian los objetos de otras dos clases; Pantalla y Controles.

Como ya digo, es el segundo objeto que se crea en el arranque del programa y, tras leer los valores que le proporciona “Datos”, inicializa los objetos “pantalla_principal” y “controles”.

Una vez hecho esto, procedemos a pasar al tercer gran contenedor; “Recursos”. En él, en estos momentos, sólo se inicializa el objeto “LOGO” de la clase “Imagen”, pero más adelante (cuando existan) será el encargado de albergar objetos de las clases “Fuentes”, “Sonidos”, “Música”.

Cada uno de estos objetos estará almacenado en vectores3 que se crearán dinámicamente a partir de la información del archivo “datos_recursos.json”. Con esto, una vez que tenga creadas todas las clases que aglutina, para meter un nuevo “recurso” no tendré que tocar para nada el código de este contenedor.

Para terminar tenemos el contenedor “Modos” (al que igual termino llamando “Presentacion” para que suene más parecido a la capa OSI que sería su homóloga). Los miembros de este contenedor utilizarán los objetos instanciados en los anteriores y, a su vez, instanciarán objetos de las clases “Presentacion”, ”Menu”, “Juego”, “Editor” y “Configuracion”.

De las clases que debe albergar “Modos” por ahora sólo existe “Menu” y aún se encuentra en un estado casi embrionario. Cuando cree la clase “Juego” también tendré que crear otra clase hijo a la que llamaré “Nivel”, pero aún no sé en que consistirá ninguna de las dos, así que tiempo al tiempo.

Aún me queda por definir el último contenedor que se debería crear. El que he dado en llamar “Motor” y que se ocupará de cosas como las físicas, detección de colisiones, animación (y otro montón de cosas con las que me pegaré cuanto toque).

Todo un berenjenal.

Últimamente tengo abiertos todos los archivos pertenecientes a las clases mencionadas y los archivos de datos que les corresponden. Esto significa que mis editores tienen abiertos de manera permanente cerca de treinta archivos entre los que navego. Cada vez que toco uno de ellos tengo que andar modificando alguno de alguno de los restantes, así que hay momentos en los que hago sufrir mucho al compilador con mis descuidos.

Hasta este mes no existía la parte de acceso a datos, y todos los demás contenedores se encontraban apretados dentro de uno que había denominado “Nucleo”. A priori esto resulta más sencillo, sólo tendría que tocar un archivo tocho, pero he preferido separarlos para que su estructura se parezca a algo que tenga un poco más de orden, sentido y estructura en mi cabeza. Hoy “Nucleo” era manejable, de aquí a un tiempo se habría convertido en un infierno (y en algo menos reutilizable).

El sacar los datos a los archivos JSON también me ha supuesto algún que otro problema adicional. En los archivos de cabecera podía definir los datos con el tipo que me de la gana, pero al importarlos desde fuera todos son cadenas de texto. Con ciertos valores, como las opciones de inicialización de la ventana la cosa se complica. Este valor, que en código puede ser una cadena de texto, por detrás hacía una conversión a hexadecimal, algo que no se puede (o no he conseguido) hacer directamente.
Tras analizar un poco el código de SDL he visto que donde yo ponía “SDL_HWSURFACE | SDL_RESIZABLE | SDL_DOUBLEBUF”, él hacía tres sustituciones:

#define SDL_HWSURFACE 0x00000001 /**
#define SDL_RESIZABLE 0x00000010 /**
#define SDL_DOUBLEBUF 0x40000000 /**

Así pues, al final la cosa se quedaba como la suma de esos tres valores, ergo: 0x40000011 (que es el valor que ha quedado en el archivo de configuración).
A saber con cuántas más de estas me voy a encontrar.

Otra parte que me ha consumido bastante tiempo ha sido la generación dinámica de los vectores de “Recursos”. Algo que, si bien no era un requerimiento ahora mismo, sí que me facilitarás las cosas de cara a futuro.

Por otro lado, la parte de una posible traducción de los textos que aparezcan en pantalla, por el contrario, ha sido una de las más sencillas de implementar. Ahora sólo falta que no me olvide de poner los valores correctos donde toca en cada nueva clase.

Una vez conseguido todo esto, se me abren varios caminos. Podría plantearme el meterme en serio con las fuentes de creación propia4 o que empiece a mirar maneras ágiles de probar las cosas que hago5.
Cualquiera de las dos cosas me va a llevar bastante tiempo. Aunque creo que la primera será más rápida de solventar, la segunda me va a a aportar más en el largo recorrido y este es un buen momento para ponerme a ello.

No sé. Mañana me podré con ello.

Enlaces:

1. Más datos

2. JSON
- JSON en la Wikipedia
- Jsoncpp en Github
- Jsoncpp en WikiBooks
- Json Parser 1
- Json Parser 2

3. Vector

4. Dibujando texto y fuentes
- Text Imput
- Getting String Input (SDL1)
- Introducción de texto con SDL (SDL2)
- Text Input And Clipboard Handling (SDL2)
- SDL_ttf
- Ejemplo de implementación de SDL_ttf
- Bitmap Font Generator
- Bitfont Maker 2
- Unicode

5. Probando que es gerundio
- Test-driven development and unit testing with examples in C++
- Ten C++ Testing Tools for Developers to Consider
- CppUnit
- Google Test
- Boost.Test
- Catch2
- Bandit
- Cpputest
- TUT (C++ Template Unit Test Framework)

Bajo un océano de bits, mes IX

Y sin embargo se mueve...

Pues sí, tras cerca de tres meses de no ver por dónde me venían los golpes, parece que comienzo a ver la luz. Por supuesto, aún me queda mucho camino por recorrer, pero la salida de este túnel en concreto parece más cercana.

Ya tengo la animación del menú en funcionamiento, he logrado pintar un texto sobre una parte concreta de la pantalla y he conseguido cambiar el color de fondo de ese rectángulo cuando pulso una par de teclas concretas.

Lo sé, todo eso ya os suena, pero la novedad es que ese proceso ya no se come toda la memoria de mi máquina en cuanto lo arranco.

Desde el principio la parte de los constructores de clases se me habían atragantado, y tampoco terminaba de ubicar el estado de cada uno de sus miembros, pero esto es algo a lo que (creo que) ya les he pillado el punto.

Al final y, como de costumbre, contradiciendo a mis vaticinios del mes pasado me puse a mirar cómo se "debugea". Gracias a esto (y a Insight1) logré dar con la parte concreta del bucle en el que la memoria se me iba de madre.

Cómo no, aún estoy muy verde como para ser capaz de interpretar en su totalidad la información que me muestra el debugger, pero tiempo al tiempo.

Por otro lado, el solucionar el tema de la memoria no solventó otra clase de problemas que también estaban teniendo lugar en un segundo plano. Tras corregir esa parte el menú se me autoinmolaba cuando el bucle se repetía por vez número 1019.
La razón exacta detrás de este comportamiento concreto (el por qué funcionaba hasta ese momento) sigo sin saberla, pero sí que localicé el punto en el que se producía el error y lo corregí.

Gracias a los libros de “Aprende como si estuvieses en primero” he conseguido centrar algún que otro concepto que tenía difuso, y ha sido gracias a leerme cosa de cuatro veces la parte dedicada a los constructores que he obtenido la sensación de que voy entendiendo su función y funcionamiento.
Para tratar de confirmar mis teorías he dividido el programa aún en más archivos, cambiando de sitio objetos, punteros y funciones, y todo parece indicar que sí. Que sí que lo tengo.
Bien por mi.

Ahora ando dándole vuelas al pensamiento desacoplado y los patrones de programación. Esto es algo acerca de lo que supe hace tiempo en alguno de los vídeos las clases de programación en C++ del Profesor Retromán2 y que creo que ha llegado el momento de afrontar.
Gracias a esos vídeos también supe que puedo compilar una aplicación para Windows desde Linux3. Una cosa más sobre la que tengo que mirar, y otra capacidad más hacia la que evolucionar mi script de compilación.

Más allá de la teoría pura acerca de los patrones que puedes encontrar en Wikipedia4 hay bastante literatura a este respecto por ahí5, pero aún tengo que terminar decidirme por una lectura básica en concreto por la que comenzar.

Otra predicción incumplida fue la de Git. Ya tengo integrado Vim con el control de versiones, y también he logrado descifrar cómo configurar la parte servidora (algo con lo que comencé a pelearme hace mucho). No es que lo haya usado para gran cosa, pero es una cosa menos que tengo pendiente.

Por supuesto, este mes también he visto unas cuantas charlas de la GDC6, por donde han aparecido una conferencia que dio la gente detrás del Ultima Online (incluido Richard Garriott con su corona) contando un poco de su intrahistoria.

Tengo un poco abandonado el tema de la accesibilidad, y tampoco ha aparecido por mis blogs habituales nada relevante a este respecto. Menos mal que tengo amigas que se acuerdan de mi cuando leen sobre estas cosas. Si cuando leí sobre el mando adaptativo de X-box no terminaba de ver muy claro su valor, parece que hay gente que lo entendió bastante mejor que yo7.

Más sobre lo que leer, más sobre lo que investigar. Pero eso ya para la próxima entrada.

Enlaces:

1. insight
- Insight
- Insight FAQ
- Script para instalar Insight
- GCC - Options for Debugging Your Program
- Working with Insight, the Debugger Interface
- Cgdb

2. Clases de Programación en C++

3. Compilación en/para Winows
- MinGW: A native Windows port of the GNU Compiler Collection (GCC)
- GCC Mingw

4. Patrones de diseño
- Design pattern
- Abstraction layers
- Facade (fachada)
- Abstract factory
- Singleton
- RAII (Resource acquisition is initialization)

5. C++ Programming (Wikibooks)
- Versión Wiki
- Versión PDF
- C++ Programming: Code patterns design
- Repaso a C++11 en Genbeta
- L-Values y R-Values
- Referencias a un R-Value
- Moviendo objetos no copiables
- Tipos automáticos
- El principio RAII y los cuatro miembros implícitos

6. GDC
- How to Find and Engage a Great Artist: A Non-Artist Primer
- Designers Are from Saturn, Programmers Are from Uranus
- Classic Game Postmortem: Ultima Online

7. El controlador de X-box en acción

Páginas

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer