Antes de empezar, debo aclarar que no puedo considerarme un juez imparcial en este tema. Quizás no lo he dicho por las claras con anterioridad, pero Fallout ejerció sobre mí una gran influencia. Siempre que me preguntan el tipo de juego que quiero hacer, o cuando intento describir el proyecto actual, acabo mencionando Fallout. En primer lugar, mayormente, y por supuesto, me refiero al 2, no a las mierdas esas que hizo Bethesda (exceptuando New Vegas).
Una vez aclarado esto, vayamos al tajo. La serie basada en la saga Fallout tal vez no se gane un Oscar (o lo que sea), pero es una digna adaptación. Tal parece que todas las buenas series de los últimos tiempos son basadas en videojuegos. Ya desde los primeros segundos del primer capítulo sentí un pelín de emoción: ¡estoy viendo una serie de Fallout! ¡Y encima, se ve y se siente tan… Fallout! No hay destrozos al lore, no hay guionistas mediocres tomándose libertades indebidas y pasándose el contenido original por el forro de los cojones. Solo humor negro y gente destripada, como debe ser. ¡Es el Yermo, carajo, se supone que esté lleno de gente mentirosa, traicionera, criminal, e hijos de puta de toda clase!
Tengo una hipótesis al respecto, quizás sea un disparate, pero quizás no ande muy desencaminada. Al ser las franquicias de videojuegos adaptados a la TV propiedad de empresas que facturan cientos de millones, los estudios no pueden simplemente tratarlos como hacen con los autores de novelas exitosas. No pueden arrojarles un cheque de un mísero milloncejo, violarse el contenido original y esperar que los autores se lo agradezcan, o que al menos, se queden en silencio ante el desmadre perpetrado por guionistas que a veces ni siquiera respetan la obra que sirve de base a su trabajo.
La serie ha logrado ampliar el lore con detalles interesantes que se ajustan a lo que cabría esperar del universo Fallout, que no mencionaré para no spoilear. Se aprecia también un cuidado en la escenografía y vestuario, el guión tiene ese humor negro del que les hablaba, que podría ser predecible en ocasiones, al menos para mí, pero es que en esas ocasiones he tenido que admitir que eso era justamente lo que correspondía. O por lo menos, yo también lo hubiese escrito así.
Habrá que esperar próximas temporadas a ver si no la cagan. Que haya un buen equipo a cargo no es garantía de nada, eso ya lo sabemos.
Mostrando entradas con la etiqueta elymuria. Mostrar todas las entradas
Mostrando entradas con la etiqueta elymuria. Mostrar todas las entradas
Nuevo cliente
Hace unos días decidí tirar todo lo que había hecho con el cliente y comenzar desde cero. Muchos experimentos acumulados y errores de diseño. Por supuesto que la nueva versión no estará libre de problemas, pero algo he aprendido con el anterior trabajo. Por el momento no habrá nada que mostrar, estoy trabajando en el sistema de estados, y me quedaré ahí hasta que encuentre algo flexible. Entonces pasaré a la segunda etapa, que es la integración de ETM, un rederizador de terrenos cuya principal ventaja es que permite la edición de la geometría.
Aunque no me interesa dar tal característica en el juego, en cambio sí la necesito para el editor de mapas y por ende, necesito ETM para mostrar el resultado en el cliente. Además ETM permite crear programáticamente el terreno de forma muy fácil, así que sería trivial ahorrarme el .cfg y definir lo necesario en una sección del actual formato xml que estoy diseñando para los mapas.
Aunque no me interesa dar tal característica en el juego, en cambio sí la necesito para el editor de mapas y por ende, necesito ETM para mostrar el resultado en el cliente. Además ETM permite crear programáticamente el terreno de forma muy fácil, así que sería trivial ahorrarme el .cfg y definir lo necesario en una sección del actual formato xml que estoy diseñando para los mapas.
Server y CB
Me ha tomado todo el día, pero al fin lo he conseguido. El proyecto de Code::Blocks ya está a punto: compila y ejecuta. Tuve que recompilar Lua, Tolua, ogg y vorbis. Pero por suerte Postgresql trae libpq en versiones para MSVC y Mingw, eso me ahorro trabajo. Me encontré con el infame error de undefined reference to Winmain@16, pero luego de investigar un poco lo resolví, simplemente reordené las opciones de enlace de forma que queden más o menos así: -lmingw32 -lSDLmain -lSDL.
No me pregunten cómo trabaja SDL_net, ni siquiera tengo idea de dónde gcc la está sacando para compilar y enlazar. Faltan por pulir algunos detalles, reorganizar el entorno de trabajo y familiarizarme con CB y Mingw, pero eso solo puede lograrse con tiempo.
Mañana es el turno del cliente. Ya tengo el SDK de Ogre para CB, veremos cómo me va.
No me pregunten cómo trabaja SDL_net, ni siquiera tengo idea de dónde gcc la está sacando para compilar y enlazar. Faltan por pulir algunos detalles, reorganizar el entorno de trabajo y familiarizarme con CB y Mingw, pero eso solo puede lograrse con tiempo.
Mañana es el turno del cliente. Ya tengo el SDK de Ogre para CB, veremos cómo me va.
Nuevas opciones en el proyecto
Dentro de mis planes de realizar el proyecto Elymuria con la mayor cantidad de software libre posible, venía dándole vueltas a la idea de usar DevCpp+gcc para la compilación en Windows. Mis experiencias anteriores con gcc en Windows no fueron buenas. A veces faltan paquetes, el ejecutable generado es mucho más grande que el que produce VC y en una ocasión lo que funcionaba bien con VC producía un error al ser generado por gcc.
A sugerencia de Erik Hjortsberg, desarrollador de Ember, me di la tarea de probar Code::Blocks. Me ha tomado todo el día bajar lo necesario, así que apenas puede correrlo e importar el proyecto VC del servidor. Ni siquiera me atreví a compilar, eso quedó para mañana. El proceso es algo trabajoso, primero debes bajarte la versión 1.0rc2, que es algo vieja, luego descargas el nightly build más reciente (que por suerte está disponible para Windows también) y un DLL que falta y ya está.
Manténganse al tanto para nuevas noticias.
A sugerencia de Erik Hjortsberg, desarrollador de Ember, me di la tarea de probar Code::Blocks. Me ha tomado todo el día bajar lo necesario, así que apenas puede correrlo e importar el proyecto VC del servidor. Ni siquiera me atreví a compilar, eso quedó para mañana. El proceso es algo trabajoso, primero debes bajarte la versión 1.0rc2, que es algo vieja, luego descargas el nightly build más reciente (que por suerte está disponible para Windows también) y un DLL que falta y ya está.
Manténganse al tanto para nuevas noticias.
Servidor en funcionamiento
Avances en el servidor
Este fin de semana trabajé en la implementación de restriciones a las habilidades y objetos. Como había dicho, un script puede acceder fácilmente las habilidades e inventario de una entidad, ya sea para obtener información o para agregar elementos nuevos.
Esto no ha cambiado mucho, excepto que ahora las habilidades, atributos básicos e items deben haber sido previamente declarados en un archivo xml, más o menos así:


Me disculpan las imágenes, pero es la única forma que he encontrado de mostrar el xml sin que se confunda con las etiquetas de la página y se forme un reguero.
Aclaro que todo esto que ven es solo un trabajo inicial. Muchas cosas podrían cambiar en el formato de los archivos xml, o los mismos archivos podrían desaparecer en dependencia de que en un futuro se demuestre que esto no es tan buena idea como parece.
Esto no ha cambiado mucho, excepto que ahora las habilidades, atributos básicos e items deben haber sido previamente declarados en un archivo xml, más o menos así:


Me disculpan las imágenes, pero es la única forma que he encontrado de mostrar el xml sin que se confunda con las etiquetas de la página y se forme un reguero.
Aclaro que todo esto que ven es solo un trabajo inicial. Muchas cosas podrían cambiar en el formato de los archivos xml, o los mismos archivos podrían desaparecer en dependencia de que en un futuro se demuestre que esto no es tan buena idea como parece.
Flexibilidad y restricciones
Hablando con un amigo hace dos días, acerca del diseño del servidor, el mismo me señaló un detalle: que los atributos de los objetos (sea entidad o item) debería estar normalizados de alguna forma, para evitar que los scripts introdujeran alguna inconsistencia. Al principio me pareció imposible unir esta restricción con el diseño flexible del servidor, sin embargo luego de pensar un poco (sano ejercicio ese de pensar, se los recomiendo siempre que no se excedan) me di cuenta que tal vez no sea tan difícil. De momento no puedo dar detalles, pero creo que puedo compaginar ambas cosas a través de las definiciones en XML, lo explicaré a fondo cuando tenga algo ya implementado.
Por lo demás, estoy sorprendido de que el trabajo me vaya tan bien. A pesar de la complejidad a la que he llegado (creo que la aplicación más compleja que he hecho es un clon del Norton Commander) el servidor corre estable y con poco consumo de recursos. Estable, a pesar de depender de scripts, un sistema que en opinión de Alvaro es totalmente inadecuado. En cuanto al consumo, pues habrá que esperar al editor de mapas y una IA realmente pesada a ver cómo se comporta el tiempo de CPU consumido cuando se traten de cientos de entidades.
Por lo demás, estoy sorprendido de que el trabajo me vaya tan bien. A pesar de la complejidad a la que he llegado (creo que la aplicación más compleja que he hecho es un clon del Norton Commander) el servidor corre estable y con poco consumo de recursos. Estable, a pesar de depender de scripts, un sistema que en opinión de Alvaro es totalmente inadecuado. En cuanto al consumo, pues habrá que esperar al editor de mapas y una IA realmente pesada a ver cómo se comporta el tiempo de CPU consumido cuando se traten de cientos de entidades.
Scripts del servidor
En estos dias he avanzado algo en las funcionalidades de los scripts en Lua para el servidor. Aunque muchas cosas están ahí simplemente para tapar el hueco, los scripts ya están interactuando con las entidades sin ocasionar daños de consideración. O sea, que no hay caídas aleatorias ni datos corruptos.
Como ejemplo, aquí están un par de scripts.
El primero es el de creación de entidades que estoy usando ahora.
dofile("data/global_const.lua")
ent=world:getEntity(eID)
plus=math.random(0,3)
ent.attr:addAttribute(STRENGTH,math.random(10+eLevel,15+eLevel+plus))
ent.attr:addAttribute(INTEL,math.random(10+eLevel,13+eLevel+plus))
ent.attr:addAttribute(DEXT,math.random(10+eLevel,15+eLevel+plus))
ent.attr:addAttribute(CONSTIT,math.random(10+eLevel,14+eLevel+plus))
ent.attr:addAttribute(WILL,math.random(10+eLevel,15+eLevel+plus))
ent.attr:addAttribute(LUCK,math.random(10,15+plus))
ent.skills:addSkill(skUNARM)
ent.skills:addSkill(skSWORD)
--Add a sword
ent.invent:addItem(1,3,1)
-- Give some random namis
ent.invent:addItem(10000,0,math.random(1+eLevel,20+eLevel))
El segundo es el script (mejor no llamarlo de IA) que se ejecuta periódica y por el momento lo que hace es mover la entidad de vez en cuando, más precisamente, hay una probabilidad de 1/4 de que eche a andar. También verifica la hora, pues ciertas entidades serán nocturnas y otras diurnas.
ent=world:getEntity(eID)
-- What time is it? Some ents wont be visible at certain times
T=world:getTime()
if ent.type==5 then
--Goblin marauders sleep during day
if (T.hour>6 and T.hour<20)>
return
end --if T
else
--Normal ents, walk on daylight
if (T.hour<6>20) then
return
end --if T
end
chance=math.random(1,40)
if (chance<10)>
ent.actions=1
else
if ent.actions==1 then
ent.actions=2
end
end
Y esto que ven ustedes, damas y caballeros, no solamente es verídico, sino que también es cierto.
Como ejemplo, aquí están un par de scripts.
El primero es el de creación de entidades que estoy usando ahora.
dofile("data/global_const.lua")
ent=world:getEntity(eID)
plus=math.random(0,3)
ent.attr:addAttribute(STRENGTH,math.random(10+eLevel,15+eLevel+plus))
ent.attr:addAttribute(INTEL,math.random(10+eLevel,13+eLevel+plus))
ent.attr:addAttribute(DEXT,math.random(10+eLevel,15+eLevel+plus))
ent.attr:addAttribute(CONSTIT,math.random(10+eLevel,14+eLevel+plus))
ent.attr:addAttribute(WILL,math.random(10+eLevel,15+eLevel+plus))
ent.attr:addAttribute(LUCK,math.random(10,15+plus))
ent.skills:addSkill(skUNARM)
ent.skills:addSkill(skSWORD)
--Add a sword
ent.invent:addItem(1,3,1)
-- Give some random namis
ent.invent:addItem(10000,0,math.random(1+eLevel,20+eLevel))
El segundo es el script (mejor no llamarlo de IA) que se ejecuta periódica y por el momento lo que hace es mover la entidad de vez en cuando, más precisamente, hay una probabilidad de 1/4 de que eche a andar. También verifica la hora, pues ciertas entidades serán nocturnas y otras diurnas.
ent=world:getEntity(eID)
-- What time is it? Some ents wont be visible at certain times
T=world:getTime()
if ent.type==5 then
--Goblin marauders sleep during day
if (T.hour>6 and T.hour<20)>
return
end --if T
else
--Normal ents, walk on daylight
if (T.hour<6>20) then
return
end --if T
end
chance=math.random(1,40)
if (chance<10)>
ent.actions=1
else
if ent.actions==1 then
ent.actions=2
end
end
Y esto que ven ustedes, damas y caballeros, no solamente es verídico, sino que también es cierto.
Sistema de creación de entidades
Hacía un buen tiempo que no hablaba acerca del progreso del proyecto. Si bien estuvo un tiempo estancado y dediqué el mayor esfuerzo a otra cosa que tengo en mente y que debería dar resultados a más corto plazo, en los últimos días de la semana encontré un hueco para avanzar un poco.
Me interesaba hacer más pruebas con el sistema de scripting y el resultado del trabajo de ayer es la base de un sistema de creación de entidades NPC más flexible. Siempre teniendo en cuenta que el núcleo del server debe saber lo menos posible acerca de los detalles de "alto nivel" de la entidad (atributos, habilidades) ahora la creación de entidades está dividida en dos partes. En el servidor se crea la instancia y el constructor inicializa algunos valores básicos. A continuación se ejecuta un script que se encarga de asignar los valores de los atributos y habilidades, teniendo en cuenta el nivel de la entidad. Además no todas las entidades del mismo nivel tienen atributos iguales, hay un cierto margen aleatorio. O sea, que podrías encontrar un Merodeador Goblin con un par de puntos de fuerza más de lo que se podría esperar.
Cada tipo de entidad puede tener su propio script de creación, que permita personalizar al máximo el tipo específico. También es posible hacer un cambio importante, como por ejemplo agregar un atributo básico o una nueva habilidad sin necesidad de recompilar el server. Lo cual no excluye que haya que modificar un montón de scripts, pero lamentablemente no puedo hacer magia con mis escasos conocimientos.
Me interesaba hacer más pruebas con el sistema de scripting y el resultado del trabajo de ayer es la base de un sistema de creación de entidades NPC más flexible. Siempre teniendo en cuenta que el núcleo del server debe saber lo menos posible acerca de los detalles de "alto nivel" de la entidad (atributos, habilidades) ahora la creación de entidades está dividida en dos partes. En el servidor se crea la instancia y el constructor inicializa algunos valores básicos. A continuación se ejecuta un script que se encarga de asignar los valores de los atributos y habilidades, teniendo en cuenta el nivel de la entidad. Además no todas las entidades del mismo nivel tienen atributos iguales, hay un cierto margen aleatorio. O sea, que podrías encontrar un Merodeador Goblin con un par de puntos de fuerza más de lo que se podría esperar.
Cada tipo de entidad puede tener su propio script de creación, que permita personalizar al máximo el tipo específico. También es posible hacer un cambio importante, como por ejemplo agregar un atributo básico o una nueva habilidad sin necesidad de recompilar el server. Lo cual no excluye que haya que modificar un montón de scripts, pero lamentablemente no puedo hacer magia con mis escasos conocimientos.
Integrando Lua
Tal vez es un poco temprano para integrar el soporte de scripting en el servidor (en otros proyectos es lo último qu ese integra) pero tenía algunas ideas que probar y había venido trabajando en eso desde hace un tiempo. Me faltaba un detalle: tener la .lib de tolua++ para Visual C++. Hoy me di a la tarea de crear un proyecto para tolua++ y compilar. Por suerte todo salió bien y la integración avanza.
Aún el sistema está lejos de ser óptimo, es que ni siquiera está bien definido, pero algunas cosas ya funcionan. Por ejemplo, los scripts tienen un interfaz a la instancia del juego, que permite que accedan a las entidades y más adelante a los mapas y otras cosas. La idea es que los scrips hagan y definan la mayor cantidad de cosas posibles para lograr que el servidor sea tan personalizable que puedan haber cambios drásticos sin tocar el código base escrito en C++.
Aún el sistema está lejos de ser óptimo, es que ni siquiera está bien definido, pero algunas cosas ya funcionan. Por ejemplo, los scripts tienen un interfaz a la instancia del juego, que permite que accedan a las entidades y más adelante a los mapas y otras cosas. La idea es que los scrips hagan y definan la mayor cantidad de cosas posibles para lograr que el servidor sea tan personalizable que puedan haber cambios drásticos sin tocar el código base escrito en C++.
Estados
El día de hoy hubiera pasado sin progresos, pues dediqué toda la mañana a definir si usaba SDL_net o Enet para el manejo de redes, un dilema del que hablaré luego si tengo ánimos, pero que ya hacia el final de la tarde resultó ser muy fructífero.
Hoy he integrado el soporte de estados en el cliente. Los estados (game states) como bien lo dice el nombre son los estados en los que el programa puede estar, digamos, la pantalla de login y selección de servidores, juego pausado, juego en progreso, etc. Usé como base el trabajo de Pablo, modificado para adaptarse a Ogre 1.4+OIS. Un estado tiene sus propios eventos de manejo de entrada y desciende de la clase FrameListener. Un gestor de estados se encarga de lanzar y detener estados mediante una pila y en general el diseño de Pablo es muy flexible, claro y fácil de adaptar a mis necesidades. Supongo que me tome todo el día de mañana implementar los dos estados que necesito y reorganizar un poco el código.
Hoy he integrado el soporte de estados en el cliente. Los estados (game states) como bien lo dice el nombre son los estados en los que el programa puede estar, digamos, la pantalla de login y selección de servidores, juego pausado, juego en progreso, etc. Usé como base el trabajo de Pablo, modificado para adaptarse a Ogre 1.4+OIS. Un estado tiene sus propios eventos de manejo de entrada y desciende de la clase FrameListener. Un gestor de estados se encarga de lanzar y detener estados mediante una pila y en general el diseño de Pablo es muy flexible, claro y fácil de adaptar a mis necesidades. Supongo que me tome todo el día de mañana implementar los dos estados que necesito y reorganizar un poco el código.
Nuevo paisaje
Progresos con autotools
Al fin, luego de muchos intentos fallidos, logré armar mis primeros scripts de autotools. Sin embargo el precio a pagar fue cambiar la estructura de directorios anterior (include para los .h y src para los .cpp) a una más simple, con todos los archivos en un mismo directorio.
Aún está lejos de estar terminado, faltan dependencias por agregar que serán más dolores de cabeza sin duda alguna.
Aún está lejos de estar terminado, faltan dependencias por agregar que serán más dolores de cabeza sin duda alguna.
Colisión con el terreno
Echándole un vistazo al demo de Ogre me percaté que implementaba un sistema de colisión con el terreno que evita que la cámara caiga por debajo del nivel del terreno. En el código escrito por Pablo para nuestro anterior proyecto hay algo similar, pero pensé que no era aplicable al mío, así que no me había interesado en investigar al respecto.
El viernes tenía algunos minutos libres que dediqué a implementar esto, con ayuda del tutorial y aquí está el video con el resultado. Inicialmente no logré el efecto buscado, pero una mirada al código de Pablo me dio una variante que a la postre fue la que funcionó. Y ahí se quedará por los siglos de los siglos.
Las cosas se ven diferentes desde las alturas.
El viernes tenía algunos minutos libres que dediqué a implementar esto, con ayuda del tutorial y aquí está el video con el resultado. Inicialmente no logré el efecto buscado, pero una mirada al código de Pablo me dio una variante que a la postre fue la que funcionó. Y ahí se quedará por los siglos de los siglos.
Las cosas se ven diferentes desde las alturas.
Relatos de Elymuria
Les había prometido una sorpresa desde hace tiempo y esto es parte de ella. Tenía pensado escribir una serie de relatos sobre el universo del juego en que estoy trabajando y tenerlos listos antes de fin de año. Pero parece que soy un desastre como escritor, solo he logrado concluir uno.
Esto que someto a su consideración aún no ha sido revisado, de hecho la revisión no me importa mucho porque no tiene ninguna pretensión literaria. Su único objetivo es dar un trasfondo del mundo de Elymuria, en este caso específico de una de las profesiones. Lo cual no quiere decir que no acepte las críticas e ideas para mejorarlo.
Aunque no está incluido en el relato para no hacer bulto, de más está decir que lo libero bajo licencia Creative Commons. Eres libre de redistribuir la obra, en caso de que alguien quisiera hacer algún trabajo derivado, pues simplemente nos ponemos de acuerdo para que se ajuste al universo que tengo en mente.
Descargar Shenzu.doc (formato Word)
Descargar Shenzu.pdf
Esto que someto a su consideración aún no ha sido revisado, de hecho la revisión no me importa mucho porque no tiene ninguna pretensión literaria. Su único objetivo es dar un trasfondo del mundo de Elymuria, en este caso específico de una de las profesiones. Lo cual no quiere decir que no acepte las críticas e ideas para mejorarlo.
Aunque no está incluido en el relato para no hacer bulto, de más está decir que lo libero bajo licencia Creative Commons. Eres libre de redistribuir la obra, en caso de que alguien quisiera hacer algún trabajo derivado, pues simplemente nos ponemos de acuerdo para que se ajuste al universo que tengo en mente.
Descargar Shenzu.doc (formato Word)
Descargar Shenzu.pdf
Cliente Ogre (video)
Aquí está, el cliente en acción, ahora en 29 segundos de video. No me gusta Google Video, pero Youtube insistía una y otra vez en confirmar mi email, así que me decanté por el primero. A partir de este momento, oficialmente estoy reclutando miembros para el proyecto.
Now oficially Im recruiting members!
Now oficially Im recruiting members!
Ausencia
Debido a un trámite burocrático he estado -de hecho aún estoy- sin conexión desde hace 15 días. Si todo sale bien, la recuperaré en esta semana. Entre otras cosas que se me han pasado, está el cumpleaños del blog, el 10 de marzo. ¡Ya tiene dos añitos!
Esperen algunas sorpresas.
Esperen algunas sorpresas.
Imágenes
Esta es una nueva versión del cliente que estoy haciendo con Ogre 3D. El mapa es bastante pequeño y tanto la textura como el mapa de alturas están hechos a mano, pero esto es solo una prueba mientras averiguo cómo usar el formato dotScene.
Esta vez la cáma en tercera persona funciona, pronto agregaré la animación, que es algo sencillo y luego la posibilidad de mover la cámara. No uso framelisteners (por ahora) y tengo total control del lazo principal gracias al tutorial que me sugirió Pablo.
Aclaro, no es que me haya convertido de momento en un experto en programación gráfica, es que estas tareas son triviales cuando te has familiarizado un poco con el motor (y además has plagiado el 90% del código).

Esta vez la cáma en tercera persona funciona, pronto agregaré la animación, que es algo sencillo y luego la posibilidad de mover la cámara. No uso framelisteners (por ahora) y tengo total control del lazo principal gracias al tutorial que me sugirió Pablo.
Aclaro, no es que me haya convertido de momento en un experto en programación gráfica, es que estas tareas son triviales cuando te has familiarizado un poco con el motor (y además has plagiado el 90% del código).

Suscribirse a:
Entradas (Atom)

