Componentes: Polimorfismo

De cara a poder tener una gran variedad de componentes, sería lógico usar un vector de “componentes” (o CComponentes) con el fin de almacenar nuestros componentes únicos en un Game Object.

componentes

Como se puede apreciar, cada componente tiene 3 partes:

  • Contenido o atributos del componente.
  • Métodos del componente.
  • Identificador único para ese componente.

Para facilitar el acceso, puesto que un objeto de nuestro juego podría llegar a tener una cantidad elevada de componentes (dependiendo del número de componentes implementados), hemos decidido usar un std::map de la librería estándar de plantillas de C++. Además, como se ha mencionado en el post anterior, un objeto sólo puede tener un componente de cada tipo. En este caso, para nuestro mapa, las claves serían unos identificadores numéricos, mientras que el valor contenido serán punteros a dichos componentes, que a su vez guardan un objeto al puntero que los contiene, intentando garantizar que los componentes no puedan ser compartidos (tal vez interese implementar algo por el estilo más adelante).

Por tanto, tendremos un std::map con una lista de punteros del tipo CComponent que, por medio de polimorfismo y herencia, crearemos una gama de clases hijas con distintas propiedades y ejecuciones de métodos distintos.

Se pueden realizar una serie de operaciones sobre los componentes desde los Game Objects, entre ellas, las siguientes:

    template
    Type* GetComponent();

    template
    bool AddComponent();

    template
    bool RemoveComponent();

    template
    void SetComponentStateComponent(bool state);

    // Funciones para acceso directo a los componentes:
    inline CComponent_Transform* transform()
    {
      // Siempre existe un componente Transform
      return (CComponent_Transform*)components[components::transform];
    }

    inline CComponent_Camera* camera()
    {
      if(components.find(components::camera) == components.end())
        components.insert(pair<int, CComponent*>(components::camera, new CComponent_Camera(this)));

      return (CComponent_Camera*)components[components::camera];
    }
  • Obtener componente: Devuelve un puntero al componente del tipo seleccionado. Si no existe, devolverá NULL.
  • Añadir componente:  Intenta añadir un componente. Si no existe, se creará y devolverá true. Si existe, no se hará nada y devolverá false.
  • Eliminar componente:  Intenta eliminar un componente. Si existe, lo elimina y devuelve true. Si no existe, no se hará nada y devolverá false.
  • Cambiar estado:  Cambia el estado del componente (activado o desactivado) en función del argumento state.
  • Accesos directos: Permiten acceder de forma rápida y cómoda al componente. Si el componente no existe, lo crea.

Además, se creará un acceso directo en la clase GameObject (por ejemplo, CComponente_Transform* transform() )para cada componente, declarado, que actuará de la siguiente forma: si el componente existe, devuelve un puntero. Si no, crea el componente y lo devuelve. Así podemos garantizar que no se produzcan accesos indebidos a memoria por no comprobar la existencia de los componentes.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s