De Homero a Kirby

Usted está aquí

Palabras desde otro mundo

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

Tirando tinta 2018

Interrumpimos la programación habitual para informar a la audiencia de que ha comenzado el Inktober 2018.
Y empieza con malas noticias. Me entero de que hoy mismo nos deja el gran Carlos Ezquerra1, así que he decidido comenzar con un homenaje a su personaje más popular.
Como de costumbre, no estoy contento con el resultado y es ya tarde para corregirlo, pero es lo que tiene la tinta.
Más allá del casco y los detalles, no me gusta el mentón, pero claro, es que nadie dibuja los mentones como Ezquerra.
Mañana seguiré con un homenaje a Norm Breyfogle2 que nos dejó hace un par de semanas. Después de esto iré viendo las obras de qué autores voy a ir maltratando.

Podréis acceder a lo que vaya haciendo desde la galería de imágenes que he creado3. Algo que, si no la he cagado a la hora de entender cómo funciona el módulo que he instalado, se debería actualizar automáticamente en cuanto suba cualquier nueva imagen.

Más adelante, y si esto funciona como promete, ya veré cómo voy estructurando el histórico de mis dibujos para publicarlos por aquí.

Enlaces:

1. Carlos Equerra

2. Norm Breyfogle

3. Galería de Inktober 2018

Bajo un océano de bits, mes VIII

Lo que empezó siendo un único archivo de código, y el mes pasado se convirtió en tres, a día de hoy son ya más de media docena. Todo para conseguir hacer un poco menos de lo que hacía el primero.

Y, aun así, pese a seguir más o menos en las mismas, cada vez vamos logrando que sea un poco “más” que “menos” que el mes pasado.

La sensación general es la de que no hay avance. Seguimos tratando de terminar de pintar el menú, sólo que ahora con clases, constructores y objetos diversos. Pero sí que los hay. Es lo que tiene la perspectiva. Si miramos los resultados desde fuera, pueden parecen retrocesos, pero poquito a poco van las piezas van encajando. Hace falta tener al mismo tiempo la visión global y la de detalles para ver cómo ha cambiado todo.
Por supuesto, esto no evita que siga dando bandazos.

Voy avanzando en el análisis, comprensión y reescritura del código del juego de Antonio García Alba. Cogiendo pequeños pedazos de su código, adaptándolos a lo que busco de acuerdo a lo que entiendo de él, y dándome de cabezazos una y otra vez contra el muro de mi ignorancia.
Mas no importa1.

Sigo buscando webs y libros que me ayuden a aclarar los conceptos más básicos que me faltan2. Desde el tour llegué hasta el libro de Bjarne Stroustrup, el papi del C++, y empecé con él. Pero no era lo más adecuado para mí.
De ahí iba a pasar a los “Piensa en C++”, pero aparecieron en mi camino los textos de “Aprende como si estuvieses en primero” de la Universidad (Privada) de Navarra, que son con los que estoy ahora.

Una versión previa de estos textos ya me habían aparecido por otras partes, y están bastante extendidas, pero he preferido dejar el enlace a los últimos (que tampoco es que sean lo más moderno del mundo). Ambos tienen una marca de agua de su facultad, pero al César lo que es del César. La atribución se le tiene que hacer a quien corresponde.

Por supuesto esto no es lo único que he hecho durante este último mes a este respecto y sigo buscando información acerca de cómo integrar Git y GDB con VIM. Más adelante me meteré también con Make.

He encontrado un par de cosas a este respecto3 que aún no he probado, pero en algún momento me tendré que poner a ello. Cuanto más crezca el código más necesidad tendré de una herramienta para poder cazar bichos y errores. Por un lado, la opción de ponerme a insertar “std::cout” tras cada línea no es muy óptima para saber en qué momento está petando la cosa. Por otro, me dedico a mantener código comentado por todos lados para conservar las cosas que funcionaban antes de ponerme a separar las funciones, lo que no deja de ser otra guarrada que manda a paseo la legibilidad del código.

Pero si me meto con esto tengo claro que perderé mucho tiempo cacharreando. La investigación para hacerlo funcionar por primera vez es divertida pero, una vez superada esa fase, cada nuevo paso requiere de mucho más tiempo para entender realmente lo que estoy haciendo. No es que sea menos divertido, todo lo contrario, pero mientras dedico tiempo a eso (lo divertido) mi casi nulo avance se ralentiza aún más (porque el poder de la frustración es poderoso).

Supongo que me pondré a ello cuando termine con el menú, pero no voy a ponerme a hacer predicciones acerca de cuándo llegará ese momento, porque siempre he sido nefasto en esos menesteres.

También ha habido vida más allá del código. Pequeños momentos de ver cómo les ha ido esto a otros.
Cómo no, hemos tenido charlas de la GDC4 y ha aparecido algún que otro pequeño atisbo de desarrollo orientado a la accesibilidad5. No sé muy bien a través de quién (quizás gracias a las recomendaciones de mi página principal) llegué como por arte de magia hasta el canal de Youtube de Dan Root6 del que puedo sacar ideas para cuando llegue el momento de “mi” juego.
También sigo buscando cosas acerca de Hyper Light Drifter y Transistor7. Dos juegos que, si bien no encajan con lo que quiero que sea el mío, me parecen auténticas bellezas y obras de las que sí que puedo extraer lecciones acerca de narrativa dentro del juego.

Como no podía ser de otra manera, también he realizado infinidad de visitas a Stack-Overflow y otros foros similares, pero no veo que aporte demasiado el listar por aquí todas las indicaciones que me han ayudado a solventar problemas concretos que me van ido saliendo a lo largo del camino.

Y… no hay mucho más que contar.
Nos leemos de nuevo en cuatro semanas.

Enlaces:

1. Shen Comix me sigue representando (a veces)
- Hablando del Diablo
- Actitud positiva I
- Actitud positiva II
- El muro

2. El camino de C++ es complejo
- A Tour of C++
- Bjarne Stroustrup
- The C++ Programming Language
- Thinking in C++, Volume One: Introduction to Standard C++
- Thinking in C++, Vol. 2: Practical Programming
- Aprenda c++ como si estuviera en primero
- Básico
- Avanzado

3. Más cosas para Vim
- vim-fugitive
- Conque-GDB

4. GDC
- Tech Toolbox for Game Programmers
- Learning from Our Mistakes: A Postmortem of Guacamelee!
- Empowering the Player: Level Design in N++
- How We Created Mark of the Ninja Without (Totally) Losing Our Minds
- Cuphead's Animation Process and Philosophy
- Owlboy: The Evolving Art of a 10 Year Project
- Game a Week: Teaching Students to Prototype

5. La accesibilidad
- Serie de vídeos con consejos de diseño sobre accesibilidad en videojuegos
- Game Maker's Toolkit explores how devs can design for colorblindness

6. Dan Root
- Su canal
- The Importance of Key Frames // Run Cycles
- The Animation of Wonderboy: The Dragon's Trap
- Fez's Animated Environments

7. Hyper Light Drifter y Transistor
- Hyper Light Drifter - Trailer
- Hyper Light Drifter - Applying 3D Level Design Skills to a 2D World
- Hyper Light Drifter - From Kickstarter to Release
- Hyper Light Drifter - The Sound of
- Hyper Light Drifter - The Sound and Music
- Transistor - Launch Trailer
- Transistor - Reveal Trailer
- Jen Zee en DeviantArt
- Galería de imágenes de Transistor

Páginas

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer