Diseño de videojuegos orientado a entidades y componentes

Diseño de videojuegos orientado a entidades y componentes
Sin comentarios Facebook Twitter Flipboard E-mail

Los que nos dedicamos al desarrollo de videojuegos sabemos que la programación orientada a objetos es la paradigma dominante en la programación de los mismos ya que es la que mejor se adapta, pero últimamente está surgiendo cada vez más el diseño basado en entidades y componentes.

Dentro de este marco y enfoque de trabajo del que se ha escrito bastante a surgido Artemis Entity System Framework un marco de de trabajo enfocado al modelo entidad - componente, pero antes de abordar esta biblioteca vamos a dedicar este artículo a ver el modelo entidad - componente y su diferencia con un modelo orientado a objetos.

Juegos orientados a objetos

En un diseño orientado a objetos cada cosa en el juego suele estar representada por una clase única como puede ser un jugador, una bala, un enemigo o un coche. Muy probablemente cada clase herede de otras, por ejemplo, en un juego puede existir la clase camión y la clase coche. Ambos son similares y probablemente en nuestra jerarquía de clases ambos hereden de una clase abstracta llamada vehículo que representa a un vehículo esta a su vez seguramente herede de una clase PhysicObject que representa a un objeto físico del mundo y muy probablemente todas ellas hereden de una clase superior llamada GameObject que los identifica dentro del juego.

Todo este sistema de herencia hace que cada vez vayamos teniendo clases más especializadas que cumplen su función aprovechando el código genérico lo máximo posible, pero existe un inconveniente en este método, a medida que crece la estructura del árbol de herencia se va haciendo más difícil de mantener. Ya que las aplicaciones están constantemente cambiando sus requisitos y funcionalidades lo más probable es que llegado un momento necesitemos añadir una funcionalidad en alguna de las clases bases haciendo que se vea afectada toda su estructura de herencia y puede que no todo su árbol de herencia se adapte a estos nuevos cambios haciendo que el árbol se rompa, una solución sería añadir los cambios en cada nodo hoja del árbol lo que sin duda sería una peor solución.

Juegos orientado a componentes

Uno de los principios básicos del diseño de software es la modularidad, hacer que cada sistema o componente sea lo más independiente del resto posible. Ese es el principio en el que se basa la programación orientada a entidades y componente. Abramos la mente y olvidémonos por un momento de la programación orientada a objetos y los paradigmas acerca de un buen diseño Orientado a Objetos que hemos aprendido durante muchos años.

Las Entidades

En el paradigma Entidad - Componente cada elemento del juego es una entidad independiente ya sea el jugador, una bala, un enemigo, un coche o un tanque cada uno de ellos se debe representar como una entidad única, nada de estructuras de herencia. Luego cada entidad esta compuesta de una serie de componentes por ejemplo la entidad Coche puede tener componentes como Velocidad, Posición o Modelo. Veamos a las entidades como sacos de componentes que le pueden enchufar y desenchufar los que queramos en cada momento.

Yo creo una entidad jugador y le enchufo varios componentes como pueden ser un componente vida, un componente posición, un componente velocidad o un componente modelo. En cualquier momento podemos quitar y poner un componente a una entidad sin que afecte al resto de componentes ya que son independientes y uno no necesita conocer la existencia del otro.

Los Componentes

Bien, ya hemos visto que las entidades están compuestas de componentes ahora hay que saber que son los componentes. Si las entidades son "sacos" de componentes, los componentes podemos decir que son sacos de "datos relevantes", por ejemplo un componente de posición en un sistema 2D tendría dos datos una coordenada X y una coordenada Y. Lo mismo un componente velocidad en un sistema 2D tendría la velocidad en el eje X y la velcidad en el eje Y. Un componente de modelo tendría en un juego 3D tendría una referencia a un modelo 3D.

Como vemos con este sistema nosotros solo debemos diseñar los componentes que son claros y específicos con sus pocos datos relevantes como puede ser una posición. Así por ejemplo todo aquel objeto del juego que necesite tener una posición solo debemos enchufarle a la entidad que lo representa un componente de posición. La entidad en ningún momento sabe cual es su posición ni si quiera tiene que saber de que datos está compuesto el componente posición ella solo sabe que tiene uno asociado.

Como vemos los componentes tampoco saben de la existencia de otros componentes solo se preocupan de los datos que contienen. Ni si quiera de como deben ser tratados estos datos, las únicas funciones de un componente son los métodos get y set para modificar los valores de sus atributos.

La unión de todo, los sistemas

Bien volviendo al ejemplo de nuestro personaje, dijimos que estaba representado por una entidad como todo en el juego y que tenía, en nuestro ejemplo, enchufados tres componentes el de posición, velocidad y modelo.

Por ahora sabemos que nuestro personaje solo tiene unos datos que están dentro de unos componentes, pero no se comunican entre sí. De esto se encargan los sistemas. Por ejemplo, queremos que nuestro personaje se dibuje en determinada posición usando su modelo 3D.

Lo que hacemos es crear "un sistema" que no es más que una clase que procesa entidades, en nuestro caso podríamos tener un RenderSystem que se encargara de coger a todas las clases que tienen enchufados un componente de posición y un componente de modelo y dibujar el modelo en la posición dada.

Por otro lado queremos que nuestro personaje se mueva según su velocidad, es decir, que según su componente de velocidad variamos la posición de nuestra entidad. Así que lo que hacemos es crear un MovementSysteme que se encarga de procesar todas las entidades del mundo que tengan un componente posición y un componente velocidad y el sistema se encarga de actualizar los valores del componente posición teniendo en cuenta el tiempo pasado y la velocidad.

Veamos lo bueno de este sistema. Imagina que en un mundo de un juego 3D tienes una entidad mesa a la que enchufamos dos componentes posición y modelo. La mesa estará siempre en el mismo sitio por lo que solo tiene un componente posición y modelo y no uno de velocidad. El RenderSystem actuará sobre ella ya que cumple los requisitos de tener un componente posición y otro modelo, sin embargo el MovementSystem no actuará sobre ella ya que no tiene un componente de velocidad. Por otro lado tenemos un jugador que tiene los 3 componentes dicho por lo que actuarían sobre él los dos sistemas dándole la capacidad de moverse y de dibujarse.

Como vemos los sistemas no se conocen entre sí solo se preocupan de las entidades que tienen sus componentes necesarios y los actualizan en consecuencia. Con esto conseguimos un sistema totalmente desacoplado en el que solo debemos enchufar y desenchufar componentes a las entidades para que los sistemas actúen sobre ella.

Las posibilidades sin infinitas imagina que a nuestro personaje le enchufamos en un momento del juego un componente espada que le da la capacidad de usarla y en una versión futura decidimos que es mejor que lleve una pistola, solo debemos desenchufar el componente espada y enchufar el componente pistola y ya lo tenemos.

El Framework Artemis

En este artículo he querido explicar lo que es la programación entidad - componente, en el siguiente artículo veremos como un ejemplo de como funciona con el Framework Artemis que esta basado en esta idea.

Más información | Entity Systems are the future of MMOG development Más información | Framework Artemis

Comentarios cerrados
Inicio