Sistemas auxiliares

Como hemos visto en el post “sistemas“, existen dos tipos de sistema en nuestro proyecto. El segundo, que describiremos en este post, son los sistemas auxiliares.

Un sistema auxiliar se caracteriza por ofrecer servicios o contenidos a los objetos y a otros sistemas para que puedan operar de una manera más cómoda o amplia. De momento, poseemos la siguiente lista de sistemas auxiliares:

  • Time
class CSystem_Time: public CSystem
{
  private:
    Uint32 deltaT;
    Uint32 lastT;

    GLfloat Tscale;

  public:
    // ...

    void SetTimeScale(GLfloat tscale);
    GLfloat timeScale();

    Uint32 deltaTime();
    GLfloat deltaTime_s();

    Uint32 GetTicks();

    GLfloat GetTicks_s();

    // ...
};
Time tendrá 3 objetivos principales: proporcionar un tiempo delta (deltaT) que define el lapso de tiempo transcurrido entre el fotograma (frame) o iteración anterior y el último fotograma (actual). Esto es útil para realizar operaciones que dependen del tiempo (por ejemplo, mover un objeto 8 unidades por segundo), para que funcione igual en todas las máquinas (ya que algunas ejecutarán más fotogramas o iteraciones por segundo que otras). Otro objetivo es proporcionar una escala de tiempo (Tscale), que servirá para escalar el tiempo. Esto simplemente modifica el valor devuelto por las funciones deltaTime y deltaTime_s, multiplicando dicho valor por la escala de tiempo (valor entre 0.0 (tiempo parado) e infinito (tiempo acelerado)(usar una escala de tiempo negativa puede dar resultados inesperados, aunque teóricamente es posible). El último objetivo es proporcionar el tiempo transcurrido desde la ejecución del programa (útil para realizar temporizadores).

  • Math

Este sistema proporcionará una serie de funciones matemáticas (seno, coseno, calcular producto cartesiano entre vectores, raíz cuadrada…) para operar de forma cómoda. De momento, el sistema está vacío (ni siquiera existe), pero en cuanto necesitemos añadir funciones, las colocaremos sin problema.

  • Data_Storage
#include "_globals.h"
#include "_system.h"

class CSystem_Data_Storage: public CSystem
{
  protected:
    map<string, string> strings;
    map<string, int> ints; //GLint
    map<string, float> floats; //GLfloat

  public:
    // ...

    // Cargar y guardar encriptados?
    void SetString(string name_id, string value);
    void SetInt(string name_id, int value);
    void SetFloat(string name_id, float value);

    string GetString(string name_id);
    int GetInt(string name_id);
    float GetFloat(string name_id);

    bool RemoveString(string name_id);
    bool RemoveInt(string name_id);
    bool RemoveFloat(string name_id);

    void RemoveAll();
    void RemoveUserVars();
};

Simplemente se trata de un contenedor capaz de almacenar enteros, flotantes y cadenas de caracteres mediante un identificador (un std::map para cada tipo). Así pues, puede haber un entero y un flotante con un mismo nombre, pero no dos enteros con un mismo nombre. Las variables se podrán guardar en ficheros, al igual que cargarlas (por defecto, en users.cfg). Además, se distinguen dos tipos de variables: variables de sistema, que empiezan por “__“, y variables de usuario, que equivalen al resto. Por ejemplo, “__Ejemplo” sería una variable de sistema, y “UN__EJEMPLO” sería una variable de usuario. Hay que advertir que se distingue entre mayúsculas y minúsculas. Estas variables se pueden usar para cualquier propósito: almacenar datos de sistema, de usuario, de objetos, etc…

  • Debug
class CSystem_Debug: public CSystem
{
  protected:
    // Debug
    bool opened;
    FILE* file;

    // ...

  public:

    // log.txt File
    void log(const char* fmt, ...);
    void error(const char* fmt, ...);
    void raw_log(const char* fmt, ...);

    // Message Boxes
    // Flags: debug::error for error, debug::warning for warnings, debug::information for info
    void msg_box(const char* title, const char* message, Uint32 flags = debug::error);
    void msg_box(Uint32 flags, const char* title, const char* fmt, ...);

    // Console
    void console_msg(const char* fmt, ...);
    void console_error_msg(const char* fmt, ...);
    void console_warning_msg(const char* fmt, ...);
    void console_custom_msg(GLfloat r, GLfloat g, GLfloat b, GLfloat a, const char* fmt, ...);

    void OnEvent();
    void OnRender();

  protected:
      // Console commands
    // General
    void Console_command__UNKNOWN_COMMAND(string arguments);
    void Console_command__HELP(string arguments);

    // ...

Este es el más amplio de los antes mencionados. Se encarga de permitirnos depurar nuestro programa. Principalmente, tiene 3 tipos funciones de depuración: la primera, escribe en un fichero log.txt (log escribe la hora de llamada a la función seguido de un mensaje, error escribe la hora y un error, y raw_log sólo escribe un mensaje); la segunda consiste en mostrar una ventana con un mensaje en su interior (tipo ventanas de error de error de windows); la tercera y última consiste en la gestión de una consola. Se podrá escribir mensajes en el buffer de la consola desde cualquier objeto. Además, el usuario podrá interactuar con la consola, escribiendo mensajes en ella. Un ejemplo de cómo se vería la consola es el siguiente:

console

  • Resources
/**
 * Formato fichero de resources (.rc):
 * ----------------------------------
 * # Comentario
 *
 * # Linea superior en blanco
 * # Formato de resource:
 * # tipo: nombre_rc ruta_al_fichero
 * mesh: nombre ruta/fichero
 * # Fin de fichero
 */

class CSystem_Resources: public CSystem
{
  protected:
    map<string, CResource*> resource_list;
    bool InitEngineResources();            // Recursos de sistema (ERROR Texture, ERROR model, ERROR sound, etc...)

  public:

    bool LoadResourceFile(string rc_file);
      bool LoadResource(string name, string rc_file, resources::types_t type, flags_t flags = 0x00);
    void AddEmpty(string name);

    void ClearResources();
      void ClearResource(string name);

    CResource_Mesh* GetMesh(string id);
    CResource_Texture* GetTexture(string id);
    CResource_Sound* GetSound(string id);
    // ...
};

Este sistema se encargará de gestionar los recursos de nuestro juego, entendiéndose por recursos texturas, sonidos, modelos… Y dependiendo del tipo de recurso que sea, se almacenará y se tratará de una forma u otra. Estos recursos podrán ser asociados a objetos de manera cómoda y sencilla.

Por cada instancia del juego, se cargará un fichero de recursos (por ejemplo, fase1.rc) que contendrá todos los archivos y recursos necesarios por dicha instancia (el formato del fichero se explica en el comentario del código superior).

(Sinceramente, llevo escribiendo esto desde hace un buen rato y creo que está más que explicado. No me apetece nada seguir documentando estas cosas, la verdad).

Advertisements