Actualmente estoy estudiando desarrollo de juegos y practicando hacer juegos.
Yo uso mucha OOP en mis juegos. Por ejemplo, cada misil que se dispara es una instancia de un Missile
objeto y se agrega a una lista de Missile
objetos. Cada tanque en el juego es un Tank
objeto. Etc.
Todo el diseño del programa se basa en esto. Por ejemplo, tener una lista de Missile
objetos me permite cada cuadro mover los misiles, dibujarlos, etc. Y tener una instancia de un Tank
objeto para cada tanque me permite verificar si cada tanque choca con algo, etc.
Me resulta difícil imaginar cómo se podría programar un juego (que es más complejo que Pac-Man) en un lenguaje que no sea OO. (Sin faltarle el respeto a los programadores que no son OO, por supuesto). No solo en términos de cuánto tiempo llevará, sino principalmente en términos de cómo se podría diseñar un juego de esta manera.
No puedo imaginar diseñar un juego sin usar programación orientada a objetos, porque toda mi comprensión de cómo diseñar un programa de juego se basa en OOP.
Me gustaría preguntar: Hoy, ¿hay algún juego que no esté programado usando OOP, de manera similar a lo que describí anteriormente? ¿Hay algún juego 'profesional' que no use OOP como un factor importante en el proceso de desarrollo?
Si es así, ¿podría darme una idea de cómo, por ejemplo, se podría implementar la detección de colisión entre un tanque y N número de misiles, sin OOP?
fuente
Respuestas:
Entonces, probablemente sea bueno para usted intentar escribir algunos programas en un estilo que no sea OO. Incluso si descubres que esto no es pragmático para ti, probablemente aprenderás mucho en el camino que te ayudará en el futuro.
El estilo OO es bastante adecuado para los juegos porque los juegos casi siempre se tratan de la manipulación de objetos con estado. Un rayo láser golpea al robot y el estado del robot cambia mientras su identidad permanece igual.
Sin embargo, es posible programar juegos en un estilo funcional . En un estilo funcional, el estado no cambia per se. Los objetos son inmutables. En lugar de cambiar objetos, te preguntas cómo sería diferente el universo si yo cambiara esto. y luego produce un universo completamente nuevo que tiene la propiedad modificada. Por supuesto, puede reutilizar una gran parte del universo existente anteriormente porque es inmutable .
En la programación funcional, cada función debe calcular su valor de retorno únicamente a partir de la información transmitida; no hay lectura del "estado global".
Si hace esto, el problema fundamental que tendrá que resolver es que cada actualización no es destructiva . Cuando el láser golpea al robot, no cambia el estado del robot. En última instancia, calcula un universo completamente nuevo idéntico al antiguo universo, excepto que el robot tiene un estado diferente; si necesitas ese viejo universo, sigue ahí, sin cambios.
Esta serie de artículos de blog tiene más ideas sobre escribir juegos en un estilo funcional:
http://prog21.dadgum.com/23.html
Este artículo aborda específicamente su pregunta "la cáscara golpea un tanque":
http://prog21.dadgum.com/189.html
De hecho, solo lea todo el blog. Hay cosas buenas allí y los artículos son cortos.
fuente
Cualquier programa orientado a objetos se puede refactorizar a un programa de procedimiento reemplazando todas las clases con estructuras y convirtiendo todas las funciones miembro en funciones independientes que toman el objeto que sería
this
un argumento.Entonces
se convierte
o cuando esa función es trivial, simplemente lo haces
La principal diferencia entre la programación orientada a objetos y la programación de procedimientos es cómo trata sus datos. En OOP, los datos son inteligentes . Se maneja y se manipula a sí mismo. Pero en la programación de procedimientos, los datos son tontos . No hace nada por sí solo y necesita ser manipulado desde el exterior.
Cuando incluso considera estructuras demasiado orientadas a objetos, puede reemplazar una matriz de estructuras con múltiples matrices, una para todo lo que sería una variable de un misil. Entonces
se convierte
En este diseño, una función que realiza una operación que involucra múltiples atributos en el mismo misil ahora tomaría un índice de matriz en lugar de una referencia a una estructura. Su implementación se vería así:
fuente
missile
es una instancia de un objeto. En no OOP, no hay instancias, ¿estoy en lo correcto? Si es así, ¿cómo podría establecer setMissileVelocity (misil, 100)?Missile
, que es una estructura con varios campos, comox
,y
,angle
yvelocity
.Lo hago de la siguiente manera:
this
. Para utilizarthis
en un enfoque que no sea OO, simplemente pase en cualquier caso (vea el siguiente punto)this
, como primer parámetro.struct
s a sus funciones comothis
, pero creo que la mejor manera de lograr un buen rendimiento de caché para objetos que son prolíficos, como entidades o partículas, es simplemente pasar un único índice a varias matrices de primitivas o pequeñostruct
s. Por lo tanto, este índice se utiliza para cada miembro de datos individual de la clase original. Entonces, por ejemplo, si tuvieras...
Lo reemplazarías con
De modo que ahora está pasando un índice a la función para obtener lo que normalmente sería
this
.Tenga en cuenta que es posible que desee utilizar matrices de primitivas como las anteriores o matrices de
struct
s, dependiendo de la mejor manera de intercalar sus datos para una buena localidad de caché (localidad de referencia). Por supuesto, el rendimiento de caché decente depende de mucho más que esto, en particular, en qué idioma / plataforma está escribiendo su código, pero incluso en lenguajes asignados dinámicamente basados en VM como Java, las grandes matrices lineales de primitivas tienden a muestra mejores características de rendimiento que las instancias de objeto. La razón principal de esto es que se accede a los objetos por referencia y esto significa que está saltando por toda la memoria para acceder a los datos, lo que es ineficiente en comparación con el acceso contiguo a las primitivas desde una gran matriz.Para obtener más información sobre la creación de entidades, etc., como un conjunto de estructuras o primitivas, consulte Evolve your Hierarchy de Mick West .
fuente
Además de las respuestas existentes, es posible que desee saber cómo hacer polimorfismo en un lenguaje de procedimiento.
Hay dos enfoques:
Almacenar el tipo
En este caso, la estructura tiene un campo para el identificador de tipo, probablemente una enumeración, que se verifica mediante una
switch
instrucción cuando es necesario realizar una acción específica de tipo.La otra forma es:
Almacenamiento de punteros de función
No mencionó en qué lenguaje de programación tiene experiencia, pero en varios idiomas también se denominan devoluciones de llamada, delegados, eventos o funciones de alto orden o simplemente objetos de función.
En este caso, no almacenará un tipo, sino que almacenará un puntero / referencia a una función que realiza la acción particular. Cuando se debe realizar una acción específica de tipo, simplemente llame a esta función. Este se parece mucho a los métodos virtuales comunes.
Al permitir configurar cada función de forma independiente, obtiene el patrón de estrategia libre.
En cuanto a su último párrafo con la detección de colisión. Creo que probablemente tienes múltiples tipos de tanques y tienes varios tipos de misiles, y cada combinación puede tener un resultado diferente cuando chocan. Si esto es lo que busca, tiene un problema que aún no se resuelve ni siquiera con los lenguajes de OOP: envío múltiple y métodos múltiples que pueden tener múltiples
this
parámetros de diferentes tipos. Para este problema hay nuevamente dos alternativas:fuente