¿Cómo diseñar un motor de juego en un lenguaje orientado a objetos? [cerrado]

26

Cada vez que intento escribir un juego en un lenguaje orientado a objetos, el primer problema que siempre enfrento (después de pensar en qué tipo de juego escribir) es cómo diseñar el motor. Incluso si estoy usando bibliotecas o marcos existentes como SDL, todavía tengo que tomar ciertas decisiones para cada juego, como si usar una máquina de estado para administrar menús, qué tipo de clase usar para cargar recursos, etc.

¿Qué es un buen diseño y cómo se implementaría? ¿Cuáles son algunas compensaciones que deben hacerse y sus pros / contras?

motor extropico
fuente
12
¿Qué tiene de malo seguir el impulso y refactorizar desde allí en lugar de sufrir parálisis de análisis?
El pato comunista
77
@TheCommunistDuck Porque seguir el impulso es el enfoque que he adoptado en todos mis proyectos anteriores, y cada uno de ellos llega a un muro después de unos meses cuando descubro que cualquier característica nueva requiere un esfuerzo monumental y complejidad para agregar. En este momento paso más tiempo reescribiendo mis motores que escribiendo el juego en sí, así que espero que con un poco de previsión y planificación me ahorre tiempo a largo plazo.
motor extropico
3
@chuzzum, buen punto. Una cosa que recomendaría es revisar la arquitectura del motor C4, es decir; terathon.com/c4engine/images/architecture.png Puede ser un nivel mucho más alto de lo que necesita, pero podría darle algunas ideas ;-)
The Communist Duck
1
i.imgur.com/81zIY.png
El pato comunista
3
También esta pregunta es algo vaga. Quizás tome uno de sus ejemplos y haga de eso una o dos preguntas más profundas.
Tetrad

Respuestas:

24

Dudo que alguien pueda decir 'Tienes que hacer esto y aquello y esto y esto tragamonedas con eso usando el patrón X'.

Sin embargo, algunos recursos útiles:
Enginuity - una serie de artículos de construcción de motores en Gamedev.net.
Game Coding Complete - Soy el propietario de este libro, y trata todos los aspectos (bueno, casi) de la programación del juego. También tiene un motor construido en todo el libro.
Game Engine Architecture : este es otro gran libro para el diseño de motores.
Diseño del motor C4 : tomado de mi comentario, pero esto muestra una forma de alto nivel de ajustar cada parte del motor.

Estos pueden ser demasiado para lo que necesita, pero no puede saber demasiado sobre algo, y estoy seguro de que obtendrá un buen plan de ellos.

EDITAR: Olvidé que los artículos de Gamedev se han archivado desde el nuevo sitio, corregido :)

El pato comunista
fuente
El enlace de Enginuity se rompió, y buscar en Google los artículos parecía mostrar que ya no están en la web. (?) Sin embargo, los libros parecen buenos recursos, y siempre estoy atento a más libros de programación;)
extropic-engine
Además, con respecto a su primer comentario, no espero que nadie presente un plan maestro que se adapte a cada juego. Acabo de notar, en el transcurso del desarrollo de algunos juegos, que los patrones comunes tienden a surgir mucho, así que me preguntaba qué otras personas usaban en sus juegos.
motor extropico
1
Corregido el enlace.
El pato comunista
+1 por enginuidad. @chuzzum Simplemente examine un par de motores de juego, déjelos inspirarlo y obtenga la arquitectura óptima para usted. Además: a menudo es mejor hacer que el componente de su motor de juego esté basado en la jerarquía, consulte cowboyprogramming.com/2007/01/05/evolve-your-heirachy
Dave O.
1
No diría que es el motor el que necesita ser agregado, más la parte del marco de la entidad.
El pato comunista
7

Como ejemplo, así es como está estructurado mi proyecto roguelike actual (en Java). Está utilizando un motor de gráficos 2D, por lo que gran parte del código de renderización ya estaba a cargo de mí. La crítica es bienvenida.

class Game
Esta clase configura la máquina de estado que administra el estado actual del juego. (en un menú vs. comenzar un nuevo juego vs. jugar un juego guardado)

interface State
Cada clase de estado contiene dos bucles: un bucle para actualizar la lógica y un bucle para renderizar. También contienen código para llamar a la Gameclase y solicitar un cambio a un estado diferente.

class ResourceManager
Un singleton que es inicializado por la Gameclase que carga todos los recursos necesarios y permite el acceso a ellos. No me gusta este diseño porque hace que sea difícil cargar / descargar recursos en diferentes niveles, por ejemplo. Probablemente diseñaría esto de manera diferente si estuviera comenzando de nuevo.

class Map
Un mapa contiene una serie de mosaicos y una lista de todas las criaturas y elementos del mapa. Es una clase bastante básica.

class Creature
Las criaturas contienen información sobre sí mismas, incluidos los cálculos de movimiento (lo que requiere que sepan en qué Mapa se encuentran y que puedan consultarlo para descubrir obstáculos). Decidir si hacer esto, o hacer que algún tipo de clase gerente se encargue de todas las criaturas es algo con lo que lucho.

interface AITask
Las criaturas pueden tener una lista de AITasks, que se ejecutan cada vez que se ejecuta el bucle lógico de la criatura. El AITask tiene su propio bucle lógico que emite comandos a la criatura, y una condición de terminación que determina si la tarea se completó con éxito o no.

interface UIElement
Implementé mi propia interfaz de usuario para este motor. Cada UIElement tiene un bucle de representación y un bucle lógico. También tienen un bucle para procesar la entrada del teclado / mouse. Todos los elementos pueden tener una cantidad de elementos secundarios, que se representan después de sus padres, y se hacen cargo de la entrada del teclado / mouse. Esto le permite tener menús con submenús, por ejemplo.

motor extropico
fuente
¿Qué está pasando exactamente con esto? Me parece perfectamente bien.
El pato comunista
@TheCommunistDuck Realmente no aparece en los ejemplos que elegí, pero tengo muchos problemas con este código. La clase ResourceManager es una de ellas, pero también tengo problemas con los estados; termino con una gran proliferación de ellos y copio mucho código. Especialmente en un juego de rol, donde el jugador tiene muchas opciones en cualquier momento, puede terminar con gráficos de estado realmente complejos. Ejemplo: lanzar un hechizo. Va desde NormalState -> SelectSpellState -> SelectTargetState -> InvalidTargetState (si falló) -> DoSpellAnimationState -> NormalState. Y esa es solo una acción.
motor extropico
1
No no. NO . NO. Por favor no. Oh espera, dijiste que no te gustaba.
Bartek Banachewicz
6

El primer punto importante es que no hay una respuesta "buena" a esta pregunta.

Lo más parecido a una respuesta correcta sería algo como: depende en gran medida del tipo de juego, la plataforma objetivo, las limitaciones (tiempo), etc.

Dicho esto, hay algunos artículos realmente buenos que le mostrarán cómo otras personas han intentado responder a este problema (ya que he tratado de encontrar información sobre esto en el pasado).
Como el pato comunista mencionó la enginuidad artículo sobre sobre el desarrollo del juego me ayudó a comprender algunas partes de la arquitectura del juego.

Mi diseño actual es un híbrido de Quake3 / Doom3 y un poco de la biblioteca de clases .NET :)

Tengo dos bibliotecas (estática o dinámica depende de cómo quiera construir / entregar) el Frameworky el Library.

La Biblioteca contiene todas las clases auxiliares que están ahí para ayudar con la producción del software del juego, pero no se limitan a este tipo de producto. es decir, tiene una implementación de una lista vinculada que está optimizada para el código del juego, pero podría ser utilizada por cualquier cosa que necesite el servicio de una lista vinculada.

El Framework es la agalla del 'motor' si quieres llamarlo así. Mucho de esto sigue las filosofías de diseño de Quake3 (solo de una manera más orientada a objetos). Contiene la CLI , la gestión de tiempos, el código específico del sistema operativo y, finalmente, las capas de red, etc.

Estos dos se vinculan con la aplicación real que se está produciendo. losGame si quieres, que contiene el código específico del juego. De la misma manera, Quake3 carga las DLL dependiendo de qué 'mod' se esté reproduciendo.

Para darle una idea de la estructura aquí hay un desglose rápido de carpetas y contenidos para cada lib:


  • Marco de referencia
    • IO (clases especializadas de gestión de archivos, clases de impresión de texto (por ejemplo, a la CLI), y registro, etc.)
    • Red
      • Cliente (clases que representan lo que el Framework considera una 'persona jugando / conectada al juego')
      • Servidor (clases para administrar la conexión en el marco y administrar los reproductores)
    • Plataforma (clases de manejo de teclado / mouse / controladores, rutinas específicas del sistema operativo como getTime ())
    • Sistema (clases de muy bajo nivel, como una clase de error para ayudar a imprimir mensajes de error, clases de temporización y la propia CLI).
    • Renderizador (autoexplicativo)
    • etc.

  • Biblioteca
    • Colecciones (clases que representan colecciones de datos, listas vinculadas / tablas hash, etc.)
    • Matemáticas (clases básicas de ayuda matemática como vectores y matrices)
    • etc.

HTH! Debería darte algunos consejos ...

Adam Naylor
fuente
Enlace alternativo a la Serie
Enginuity
-3

Cosas para considerar

  • Los lenguajes orientados a objetos tienen problemas porque generalmente no tienen funciones de primera clase o no todos los datos son objetos (como enteros o flotantes en Java). Los patrones de diseño abordan estos problemas con varios patrones. Generalmente es más rápido codificar y más fácil de mantener el uso del lenguaje que puede hacerlos (objetos de primera clase); por ejemplo Python (que también permite un diseño orientado a objetos), tendrá una velocidad más lenta.
  • Cálculo del evento, al menos para la IA
  • Lógica de Hoare, use precondiciones y postcondiciones para al menos probar su código
  • Agentes, miren las entidades del terremoto
  • Bases de datos relacionales, una forma poderosa de almacenar datos

Buen diseño

  • hacer diagrama ER
  • hazlo correcto
  • cree su base de datos, objetos o estructuras de datos a partir de ella

Los datos son clave para la programación. Si diseña bien sus datos, el algoritmo generalmente emerge de ellos (si no cuenta algunos algoritmos numéricos, como el determinante informático).

usuario712092
fuente
-1 ya que esta respuesta es muy vaga y confusa. Las bases de datos relacionales no tienen absolutamente nada que ver con un motor OO. Puedo entender que el inglés no es su primer idioma, pero ¿podría explicar lo que quiere decir en su primer párrafo? Parece contradictorio (los lenguajes OO tienen problemas pero es más fácil programar en lenguajes con patrones de diseño ... aunque los patrones de diseño son casi siempre estructuras OO).
El pato comunista
@duck Contradictorio? OO tiene problemas que no existen en otros idiomas, DP resuélvalos, consulte c2.com/cgi/wiki?DesignPatternsInDynamicProgramming .
user712092
@Duck 1) Puede usar SQL en C ++ 2) Puede inferir atributos de objetos desde ER (aunque no es una práctica recomendada) 3) Puede estructurar datos a partir de relaciones (esta es una lista porque necesito reordenar los elementos a voluntad esto es un hash porque necesito una búsqueda rápida)
user712092
@Duck Pido disculpas, cometí un error al reordenar. No quería decir "DP son más fáciles de XY" pero "los idiomas que pueden hacer la primera clase son ...". :)
user712092
Sí, puede haber ventajas para los lenguajes funcionales. Sin embargo, incluso de manera imparcial, siento que un enfoque OO tiene sentido lógico desde una perspectiva gamedev. Además, no hay ninguna razón por la que necesite una base de datos relacional en ningún lado. Claro, pueden ser útiles. Sin embargo, no se convierte en un componente necesario en ninguna parte.
El pato comunista