@ agnasg

Febrero de 2021

16-02-2021 9:11 AM

¿Motor gráfico?

Para mi próximo juego quiero trabajar 3d así que SDL no es una opción. Mi respuesta para esto desde hace años es Irlicht como se puede ver, pero quise revisar qué otras opciones hay hoy en día:

Unreal y Unity

La razón por la que los descarto es porque la descarga es de más de 10gb (20gb en el caso de Unreal). Estoy huyéndole a esos paquetes tan grandes, porque paquetes grandes son grandes problemas y ya yo tengo suficientes.

Godot

El lenguaje de scripting es GDNative, algo parecido a python. No se puede hacer juegos usando directamente C++ lo cual lo hace inviable para mi. Al parecer hay varias y sólidas razones para eso como dice aquí, y dice que usar C++ es posible pero preparar el ambiente y linkear las librerías necesarias es demasiado trabajo Sin embargo, el artículo de Wikipedia dice lo contrario, o no lo menciona, lo cual me parece bien raro. Como al parecer hay polémica al respecto mejor paso.

Urho3D

He estado revisando sus características y luce bien. El único detalle es que no parece ser popular. Para usar una engine casi desconocida tengo con Irrlicht. Pero yo no la descartaría. La voy a colocar como un quizás por ahora.

Conclusión

El “deber ser” es seguir la corriente y utilizar Unreal o Unity , pero como cualquiera de esas alternativas me va tomar demasiado tiempo (meses) voy a dejar estos planes en suspenso por ahora. Aunque /r/playmygame hay historias todos los días de personas que dicen más o menos algo como esto: “jamás he programado, nunca he estudiado matemática, soy un perfecto idiota, y luego de 7 meses trabajando con Unity aquí está mi primer juego“. Y entonces un video de un juego con calidad AAA, que parece hecho por Blizzard en su tiempo libre. Y hay 100 comentarios y 200 upvotes. Por ejemplo. Como odio ese tipo de mercadeo.

Noy hay cambio de planes entonces, sigo con khpx, y en el tiempo libre trabajaré la nueva versión de tilemovers y el juego nuevo que tentativamente se llamará Carrusel, es 2.5 d y tiene elementos de arcade, platformer y puzzle, y lo voy a hacer con irrlicht (por ahora).

¡Patéame las pelotas!

Finalmente flash dejó de existir luego de que en diciembre su mortífero creador (Adobe) lo descontinuara definitivamente. Ha habido anécdotas y chistes sobre el hecho, como aquéllos cuentos que solemos narrar en los velorios. Pero el mejor que he oído es esta nota en slashdot donde nos cuentan que el sistema ferroviario de una ciudad china (Dalian) dejó de funcionar porque estaba escrito en flash!. ¿La solución? Pues consiguieron una versión pirata y lo pusieron andar de nuevo. Enlace. (En los comentarios podemos leer: Mi nombre es Zhang Wei, me gusta que me peguen pinzas en los pezones y que me pateen los testículos pero sobretodo me gusta escribir sistemas ferroviarios en flash!)

Enumeraciones caóticas

¿Alguien se ha dado cuenta que Rayuela, de Julio Cortázar es una inmensa lista de enumeraciones caóticas?

bastoncillos de marfil, plumas de pájaro lira, monedas rituales, fósiles mágicos, estrellas de mar, pescados secos, fotografías de concubinas reales, ofrendas de cazadores, enormes escarabajos embalsamados

Las nubes aplastadas y rojas sobre el barrio latino de noche, el aire húmedo
con todavía algunas gotas de agua que un viento desganado tiraba contra la ventana malamente iluminada, los vidrios sucios, uno de ellos roto y arreglado con un pedazo de esparadrapo rosa

quién sabe si Jelly Roll iba a estar en ese andén, en ese piano, en esa hora”

Epílogo

Así que ese es el reporte, la explicación, los detalles de la situación, el estatus, el avance de los proyectos, las actividades, las líneas de pensamiento de este convulsionado, inquietante, pertubador 2021 que parece ser la continuación, el epílogo, la elegía de un nefasto, terrible y odioso 2020. Se cansa, se agota, se obstina uno.

Un cuento no tan gracioso

03-02-2021 6:28 AM

Cosas graciosas que se encuentran al azar en Github

Como Go estaba destinado a reemplazar a C++…“. Sic. Enlace.

Hablando de cosas graciosas

Lo que me resulta gracioso de este juego, donde se debe jugar a través de los eventos del 2020, es que en las instrucciones, junto a los incendios de Australia y el Covid-19, aparece el ascenso de Tiktok. Clásico.

Un cuento no tan gracioso… para algunos

Lo que sucedió con las acciones de GameStop, el subreddit /r/wallstreebets y Robinhood es de antología. Es quizás uno de los eventos mas importante de los últimos meses en internet, por no decir de los últimos años. Mucha gente no le ha prestado atención basicamente porque no entienden de qué se trata. Inclusive si has visto las películas Wall Street (con Michael Douglas y Charlie Sheen) y El lobo de Wall Street (con Leonardo Di Caprio) todavía no vas entender nada. Lo explico rápidamente: dentro del arsenal de trucos de esta gente (la gente de Wall Street) hay un mecanismo que les permite vender acciones prestadas. Es decir, alguien, un banco por ejemplo, puede prestar acciones que tiene en su poder para que sean negociadas y con ello ganarse una comisión. Ey, esto es exactamente lo mismo que hacen los bancos con nuestro dinero, ellos prestan nuestro dinero se ganan una comisión y eso les permite sobrevivir. Así que prestar acciones no tiene nada de malo.

Ok, esas acciones prestadas entonces son vendidas digamos por $20, y deben ser devueltas en a lo sumo 2 semanas: aquí está el truco: los operadores de Wall Street escogen acciones que saben que van a perder valor, cuando llegan al precio que les conviene las compran, por ejemplo digamos $12, entonces regresan las acciones al banco y pagan una comisión de, digamos $1. Entonces al final de las 2 semanas cómo fueron las cuentas: vendí una acción en $20, las compré de nuevo por $12 y pagué $1 de comisión: $20 – $12 – $1 = $8 – $1 = $7. Me gané $7 sin hacer realmente nada. A este mecanismo se le llama short selling (compra corta).

Todo es una maravilla para los operadores de Wall Street (por ejemplo RobinHood, una compañía que tiene una aplicación mobile para compra y venta de acciones). Así que escogieron las acciones de Game Stop para hacer su short selling. Game Stop es una compañía al borde de la quiebra desde hace años porque básicamente se dedica a vender juegos usados o juegos en general en tiendas alrededor del mundo. Algo así como Blockbuster de los juegos, y así como Blockbuster debería estar quebrada, sobretodo después de un año de pandemia. ¿Quién va a ir a una tienda a comprar un juego hoy en día, si los juegos ahora se descargan o se pueden comprar online? Las acciones de esta compañía por supuesto que están bajando así que son ideales para un short selling.

Ups. El problema es que todas estas operaciones son públicas y están a la vista de todos así que cualquiera puede intervenir comprando las acciones. Los chicos de /r/wallstreebets (un subreddit de reddit) descubrieron la operación y comenzación a comprar las acciones de GameStop. ¿Se entiende cómo esto afecta la operación de short selling?. La clave es que el precio de la acción baje, pero si la gente comienza a comprar las acciones el precio sube. Ups. El grupo /r/wallstreebets tiene 4 millones de redditors. Doble ups. Subieron el precio de las acciones de $12 a $420.

Esta semana se cumplen las 2 semanas del short selling de las acciones y el resultado puede ser que los operadores de WallStreet pierdan millones (dicen que millardos) porque están obligados a comprar las acciones para devolverlas al banco. Por supuesto eso no va a suceder porque ellos hacen lo que les da la gana incluyendo forzar a los compradores a vender a un precio conveniente. Hoy 03-02-2021 el precio amaneció en $90. Y es de suponer que en el trascurso del día siga cayendo (o comience a subir de nuevo). El resultado seguramente será mixto, pérdidas y ganancias de ambos lados, y un buen susto para Wall Street. La próxima vez que traten de hacer un short selling con una acción demasiado visible lo van a pensar 2 veces.

Simplemente busca un Pet-rock proyect.

Yo recomiendo ampliamente leer a dvasallo, desde el punto de vista de negocios, estamos claros, él tiene razón. “No pierdas tiempo en complicados proyectos que tarden meses, porque no sabes si al final va a tener éxito o no. Lo más probable es que no, así que mientras más tiempo le dediques, más tiempo vas a perder“. Es decir, debemos seguir las probabilidades, y probar proyectos de 2-3 semanas, no más, y hacer un buen mercadeo, y usar al máximo la audiencia que hemos acumulado (la audiencia que hemos acumulado, eso es vital). Lo cual significa que mi proyecto de 4 años, khpx, un mmo del espacio con exploración y conquista, simulador universal de imperios, es, en definitiva, una apuesta arriesgada. Mucho. Pero el problema de buscar proyectos simples es que lo inverso te lleva a Gary Dahl con su pet-rock, el empresario que comenzó a vender rocas como mascotas, en cajas con ventilación. Tengo un problema ético para hacer ese tipo de cosas. Por otro lado, Kenneth Cassel está vendiendo cursos de vi (vim), y está bien. Hay en algún sitio aquí un equilibrio. ¡Sorpresa! ¡Hay que conseguir el equilibrio! ¿Dónde he oido yo antes? La solución es conseguir el equilibrio en tu vida. Impactante revelación (- sarcasmo -).

¿Cómo se hizo tilemovers?

15-01-2021 3:04 PM

¿Por qué hacerlo fácil si lo podemos hacer difícil?
— típico programador sabelotodo

Sinópsis

tilemovers es un juego de sliding tiles (¡baldosas deslizantes!) donde el objetivo es mover un tile de la posición inicial a la final. Este tipo de juegos es como los “3 Chiflados”: el 50% de la gente los ama, y el 50% de la gente los odia. Para colmo, le he agregado 3 niveles: “Normal”, “Nightmare” y “Apocalypse”. Es decir, fácil, difícil y superdifícil. Pero para el que conoce este tipo de juegos debería ser divertido.

La diferencia con los otros 1000’s juegos similares es que los tiles vienen en 4 tamaños: 1×1, 1×2, 1×3 y el endiablado 2×2. La página oficial para descargar el juego es https://agnasg.itch.io/tilemovers, también hay un video (no apto para cardiacos) https://www.youtube.com/watch?v=wbcf3ICA2es.

El devlog en español está aquí https://www.micronosis.com/category/tilemovers/ y en inglés en tigsource https://forums.tigsource.com/index.php?topic=71419.0. Lo pueden jugar en windows (https://agnasg.itch.io/tilemovers) o en Android (https://play.google.com/store/apps/details…).

Módulos

tilemoves se puede descomponer en 4 módulos:

  • El sistema gráfico implementado en SDL2
  • La lógica del juego que implementa los movimientos de los tiles, sus tipos y los comandos que los gobiernan.
  • El módulo de bases de datos que usa una bd SQLite para almacenar y cargar la información del juego.
  • Un editor que permite crear los puzzles y los almacena en la base de datos.

En este post vamos a hablar de este último módulo, el editor de puzzles. Cuando entendí la necesidad de tener una herramienta para agregar, quitar, cambiar el tipo de tile, y guardar los cambios, me propuse los siguientes objetivos:

  • Facil de usar, es decir agregar y borrar los tiles debe ser rápido y fácil.
  • Fácil de cambiar el tipo de tile (estático, rápido, angel y humano)
  • Integrado al juego para repetir el ciclo de probar, cambiar, probar rápidamente.
  • Debe ser fácil de implementar

Para cumplir con todos estos requerimientos es invevitable que el panel de control quede congestionado sobretodo porque mi objetivo es que funcionara integrado al juego. Estuve viendo algunas ideas de cómo hacer el gui, incluyendo paneles como este:

DeadImgui Example

Para lo cual tendría que utilizar una tercera librería (ya el juego está usando SDL2 y SQLite) y eso no es bueno, al menos para este proyecto. Estoy pensando en planificar el estudio para analizar el posible uso de DearImgui para los gui de los siguientes juegos incluyendo el próximo juego (memory + arcade + platform, todavía sin nombre) y para khpx, pero no para tilemovers porque eso iba a agregarle más tiempo al ya abultado proyecto.

Por eso simplifiqué todo y me quedé con un panel incrustado con todos los botones:

La primera línea son operaciones con los tiles: intercambiar posición, cambiar su estatus, agregar nuevo tile, eliminar tile. Luego botones para guardar cambios, guardar como un nuevo puzzle, opciones para generar un puzzle en forma aleatoria (cuando estaba sin mucha inspiración). También opción para cambiar de nivel cuando su nivel de dificultad no era apropiado para su nivel actual. Finalmente botones para asignar el tipo de tile: faster (se mueve en todas direcciones), static (no se mueve), angel (se mueve verticalmente, human (se mueve horizontalmente).

Las operaciones de agregar y borrar tile se ven mejor en video:

Conclusión

No llevé contabilidad de cuánto tiempo le dediqué al editor específicamente, pero a grosso modo fue cercano a un mes (lo cual podríamos traducir en 24-30 horas, que es lo que yo le dedicaba mensualmente a este proyecto). En comparación al total de tiempo empleado podría decir que el editor ocupó un 20% del tiempo del proyecto. Creo que es el tiempo mejor empleado en todo el proyecto.

Cómo migrar una db implementada en Windows y SQLite a Android sin decir grocerías

06-01-2021 8:23 AM

Object-oriented no es el único patrón de diseño válido. A muchos programadores se les ha enseñado a pensar puramente en términos de objetos. Y, para ser justos, los objetos son a menudo una buena manera de descomponer un problema. Pero los objetos no son la única manera, y no siempre son la mejor manera de descomponer un problema. A veces el viejo y buen código de procedimientos es más fácil de escribir, más fácil de mantener y entender, y más rápido que el código orientado a objetos.

Por qué SQLite está programado en C

En el post anterior, describo mis peripecias migrando un juego desarrollado en C++ y SDL2 a Android.

El juego es tilemovers y ya está publicado en itch.io. Puedes echarle una mirada.

Versión Android en el Google Store. Por favor descarga la versión Android y enviame tus comentarios.

En este post describo cómo fue el proceso de migrar el código relacionado a SQLite y la base de datos. Por qué mi juego tilemovers requiere una base de datos, es tema de otro post, baste decir, por ahora, que la idea detrás de programar videojuegos es la diversión intrinseca en hacerlo, es decir, para mí tiene/debe ser divertido hacerlo, y no hay nada más divertido que programar juegos que usen complicadas bases de datos. Si alquien se divierte jugando el juego, es un extra maravilloso, pero no requerido.

Como explico en el post anterior, si es la primera vez que programas una aplicación para Android (y para mobile en general) hay muchas preguntas obvias cuya respuesta desconoces (aunque es algo que un programador de mobile sabe desde el prescolar y Plaza Sésamo).

¿Dónde se guardan los archivos, y en particular, la base de datos de SQLite?

Es un asset como cualquier otro y se declara en la carpeta assets dentro de la estructura de archivos de Android manejada por Android Studio (en adelante AS). Es decir,

\app\src\main\assets

pero no puedes escribir ahí, es decir, esos archivos son read-only. Tienes que moverla al área de datos de la aplicación (se dice fácil pero es una epopeya: leer más adelante)

¿Y hay que pedir permiso para escribir en la base de datos?

Como dice la documentación oficial, la aplicación no requiere autorización para leer o escribir en los directorios asignados para almacenamiento interno (de nuevo, no estamos hablando de la carpeta assets, donde solo se puede leer)

¿Por qué no se puede abrir un asset usando ifstream o apuntadores a archivos?

De acuerdo a esta respuesta en stackoverflow, porque no. Pero en el ámbito de esta respuesta, si se puede utilizar sqlite.c (es decir no hay que migrar SQLite a la versión java/kotlin) pero la base de datos tiene que estar en el área de datos de la aplicación. (¿por qué estoy repitiendo esto tantas veces? Porque un programador avezado y con experiencia en otras plataformas va a encontrar bien complicado de entender que una aplicación tiene al mismo tiempo 2 áreas de datos asignadas, una read only, y la otra read-write-has-lo-que-quieras).

Luego de mi investigación (que puede no estar completa, y puede contener errores). Las alternativas a la mano para trabajar con bases de datos o archivos de datos en una aplicación Android son las siguientes:

  1. Necesitas trabajar con AAssetManager, AssetManager_open, AAsset_read para acceder a la base de datos tal como se explica aquí. Esta es una solución implementada en C usando NDK. Se llama SQLite-NDK. No hice esto, aunque dejo abierta la posibilidad para otros juegos, ver abajo.
  2. La bases de datos almacenada en assets no se puede usar directamente, hay que instalarla en:
    “data/data/your-package-name/databases” (ver punto 5 abajo)
  3. Una idea es tener los datos en un archivo json o xml, crear la base de datos y luego cargar los datos (como se explica aquí).
  4. Otra sugerencia es usar el Content Provider
  5. Otra idea es utilizar una clase DataBaseHelper derivada de SQLiteOpenHelper para copiar la base de datos de assets al área de datos de la aplicación. Aquí se explica cómo es el proceso. Esta explicación al parecer es más clara. Este fue el procedimiento implementado.
  6. Para obtener la ubicación donde se va a ubicar la base de datos se debe utilizar:
    File dbFile = context.getDatabasePath(name_of_database_file);
    (ver aquí, y ver documentación en developer.android.com, hay que usar esta función o la aplicación puede fallar en algunos teléfonos inteligentes nuevos, por ejemplo, Huawei)

Hay varios retos para hacer que todo esto funcione. Primero hay que averiguar cómo llamar código escrito en java desde la aplicación desarrollada en C/SDL2 (sí, en cierto momento surge la pregunta de por qué no migrar completamente a kotlin (el lenguaje nativo de aplicaciones android) y la respuesta es que la idea desde el comienzo es migrar una aplicación desarrollada en C++, en Windows usando SDL2 a Android).

La solución es simple tal como se explica aquí. El siguiente paso es cómo integrar una clase java a una aplicación desarrollada usando NDK, dentro de Android Studio (lo inverso es fácil y aparece aquí, es decir, como usar NDK desde una aplicación desarrollada en kotlin).

Lo interesante es que viendo ese artículo recordé que Android Studio tiene menus, muchos menus, y entre ellos hay un “Add Java class”, el cual funciona pero no necesariamente sobre el nombre del proyecto (como mi intuición me indica) sino sobre la carpeta del paquete que en el caso de mi aplicación basada en sdl se llama org.libsdl.app

Al agregar la clase, Android Studio pregunta a cuál paquete lo vamos a agregar, indicamos org.libsdl.app. Copiamos el contenido de nuestra clase al archivo creado. Este archivo es almacenado en app\src\main\java\org\libsdl\app

Nuestro archivo java es basicamente una clase ( DataBaseHelper) que verifica que la base de datos existe. Si no existe la copia desde assets al área de datos. La soluión completa está aquí.

La declaración de la clase luce así:

public class DataBaseHelper extends SQLiteOpenHelper

Ahora, como dije antes todo parace simple siempre y cuando puedas hacer llamadas a java desde tu aplicación desarrollada en C.

Para ello, básicamente tienes que usar esta llamada

jclass dbhelper = env->FindClass(“org/libsdl/app/DataBaseHelper”);

donde estás declarando un apuntador (creo que en el universo java tiene otro nombre) a la clase (que debes identificar colocando el path completo)

El primer problema es cómo consigues inicializar la variable “env”. Si comienzas a buscar en stackoverflow quedas en un lazo infinito porque para inicializarla, necesitas hacer;

JNIEnv *env;
g_JavaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)

Y ahora tu problema es como inicializar la variable g_JavaVM, el apuntador a la máquina virtual. El cuento es largo y lo voy a omitir, al final la forma de hacerlo es inicializar la llamada en el momento de carga de JNI, lo que se hace a través de esta función:

JavaVM* g_JavaVM = NULL;
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) {

   g_JavaVM = vm;
   return JNI_VERSION_1_6;
}

Yo estuve varias horas tratando de utilizar Android_JNI_GetEnv(void); sin suerte, función que se encuentra declarada en SDL_android.h (en el código de la versión Android de SDL2) pero no funciona. La única forma que descubrí fue con la llamada JNI_OnLoad ().

Luego que tienes el apuntador a la clase debes crear una instancia de la clase (un objeto) lo que haces a través de lo siguiente:

jclass javaGlobalClass = reinterpret_cast<jclass>(env->NewGlobalRef(dbhelper));

jmethodID helperConstructor = env->GetMethodID(javaGlobalClass, “<init>”, “(Landroid/content/Context;)V”);

Con esto puedes hacer la llamada para la ejecución del constructor de la clase:

jmethodID helperConstructor = env->GetMethodID(javaGlobalClass, “<init>”, “(Landroid/content/Context;)V”);

Y con el contructor haces la llamada a createDataBase:

jmethodID createDataBaseMethod = env->GetMethodID(dbhelper, "createDataBase", "()V");
env->CallVoidMethod(obj, createDataBaseMethod);

Y con la base de datos, ya puedes acceder a ella utilizando las llamadas de SQLite de forma normal, tal como lo haces en cualquier programa C/C++ implementado con SDL2, que en nuestro caso es tilemovers.