GDE: Arranque y Parada

Vamos a empezar con el primer artículo técnico dedicado al proyecto GDE. Como sabéis la intención de este proyecto es la de aprender a desarrollar los elementos básicos de un Game Engine 2D o de un videojuego en general por un método práctico y colaborativo. En este primer artículo vamos a ver como vamos a gestionar el arranque y parada del motor.

La clase App

Con nuestro motor no vamos a reinventar la rueda, por lo que siempre es bueno mirar el modelo que tienen otros motores consolidados para inspirarte. Nuestra clase App representa lo que en, por ejemplo, Ogre3D sería la clase Root ó en la saga de versiones de Cocos2D sería la clase Director.

La clase App por tanto se trata de una clase con el patrón Singleton. Para los no versados, decir que se trata de una clase que tiene una única instancia en nuestro programa. Esto lo hacemos estableciendo el constructor y el destructor como privados para que no se puedan crear nuevos objetos y definiendo unos métodos que nos permitan crear u obtener el objeto (En nuestro motor se llaman instance y release).

El método intance comprueba si existe la instancia única del objeto, si no existe, lo crea y devuelve un puntero a dicha instancia. Por el contrario, si existe, devuelve el puntero a dicha instancia por lo que siempre que llamamos al método instance de la clase App nos devuelve un puntero al mismo objeto se llame desde donde se llame.

Lo más extraño de esta simple interfaz puede ser que antes del nombre de la clase tenemos la macro GDE_API, es usada por el proyecto para crear las clases en modo exportable para Visual Studio, nada de lo que preocuparse. Por otra parte como vemos hereda de la clase sf::NonCopyable de la biblioteca SFML, esta clase no es más que una clase que tiene definidos el Constructor copia y el operador de asignación como privados, al heredar de ella el constructor copia y el operador de asignación quedan como privados en nuestra clase, algo que tiene todo el sentido tratándose de un Singleton.

Arrancando el motor: métodos básicos

Ahora que tenemos establecida nuestra clase App como un Singleton debemos empezar a aportar funcionalidad. La clase App será la encargada de arrancar y parar nuestro motor por la que su función es arrancar todos los subsistemas y contener el bucle principal del juego, el llamado Game Loop. Por último debe realizar tareas de limpieza al terminar.

Sus tareas quedan definidas entonces, en primer lugar arranca todos los subsistemas necesarios como pueden ser el Gestor de recursos, el gestor de escenas, Logs, etc.

Luego crea la ventana ya que la clase App será la que contenga la ventana de nuestra aplicación y la gestiones. La crearemos en base a un fichero de configuración llamado window.cfg que se encontrará en el directorio del ejecutable.

Una vez creada la ventana, si todo ha ido bien entramos en el Game Loop que es un bucle que se ejecuta durante toda la vida de la aplicación y del que hablaremos en el próximo artículo cuando abordemos la integración del Scene Manager.

Por último, cuando se sale del Game Loop, se entra en un método llamado cleanup que tendrán muchas clases de nuestro Engine y se encargará de hacer las tareas de limpieza: liberar memoria, apagar los subsistemas, etc.

Un esquema general de la clase App con estas cosas sería el siguiente:

Vemos que contiene un sf::RenderWindow que será la ventana de nuestra aplicación. Otros atributos que contiene son running que será true mientras el motor deba estar activo y exitCode que almacena el valor de salida de la aplicación. Los atributos referidos a Scene y SceneManager los comentaremos en el siguiente artículo ya que tienen que ver con la gestión de escenas.

Podemos observar los métodos de los que hemos hablado: init, createWindow, gameLoop y cleanup son privados. Esto es así porque todos ellos se lanzan en el orden esperado a través del método run de la interfaz pública.

Hay otros métodos públicos que son utilidades como getWindow que devuelve una instancia a la ventana, isRunning que devuelve el valor del atributo running o quit que establace running a false y el exitCode pasado por parámetro.

En cuanto a la implementación, aún le queda mucho que revisar y cosas que añadir como gestión de subsistemas en el método init o un Fixed Time adecuado en el Game Loop, pero antes de que se complique podéis mirar como es la implementación actual con lo que aquí se explica y el SceneManager que será lo próximo que abordemos.

Como vemos la implementación ya integra el sistema de Log, La creación de la ventana desde el fichero, creándolo si no existiera y la inicialización del SceneManager.

Como ya hemos dicho en el siguiente artículo técnico explicaremos la integración del SceneManager y como funciona el GameLoop.

En Genbeta Dev | Proyecto GDE En Github | Genbeta Dev Engine

Ver todos los comentarios en https://www.genbeta.com

VER 0 Comentario

Portada de Genbeta