2011-12-30 22 views
5

Estoy diseñando un juego, pero no puedo entender bien la estructura de herencia. Normalmente soy bastante bueno en eso, pero este tiene demasiada superposición y no puedo decidir sobre todo.Herencia/diseño de interfaz de un juego

Estoy buscando modelar veleros - piense en Age of Sail. Presumiblemente, por lo tanto, todo se extiende a una clase de buque.

Existen varios tipos de estilo de barco: remo (galeras, canoas), plataforma cuadrada, plataforma delantera y trasera, con diferente comportamiento. Cada uno de estos se subdivide en varios otros tipos. No puedo decidir si esto debería ser una serie de interfaces o extensiones de Vessel. Tenga en cuenta también que puede haber un cruce (un buque puede ser tanto remolcado como cuadrado) lo que me lleva a pensar en las interfaces.

Los barcos también tienen diferentes comportamientos: buques mercantes, hombres de guerra, corsarios, piratas. Realmente no puedo determinar si esto debería ser una interfaz o una extensión de otra clase. Sin embargo, no hay cruce de tipos en este caso.

Finalmente, existen varios comportamientos que los barcos individuales pueden tener. Los mercaderes pueden estar en un convoy (defenderse) o independientes (huir). Los hombres de guerra casi siempre atacan a menos que superen las armas ... pero pueden trabajar en flotas, escuadrones o independientemente. Los corsarios y los piratas solo atacan si son más débiles, por lo general de forma independiente, pero ocasionalmente en parejas. ¿Asumo que esto también debería ser una interfaz?

Mi gran problema es que cada estilo de barco (fragata, barco de guerra, etc.) puede cumplir casi con cualquiera de estos roles, por lo que no puedo construir una estructura de herencia sólida simple. Fragata no puede extender man-o-war porque algunos son corsarios. Sloop no puede extenderse cuadrado aparejado porque algunos están aparejados. etcétera etcétera.

Cualquier pensamiento sería apreciado, estoy un poco suelto. Gracias

+1

Las dos ideas que me vienen a la mente de la cabeza son "diseño basado en componentes" y "patrón de estrategia". En cuanto a los diferentes comportamientos que pueden tener los barcos individuales, eso definitivamente es un patrón de estrategia para mí: cada barco está utilizando una de una variedad de estrategias diferentes. Consulte aquí en Wikipedia: http://en.wikipedia.org/wiki/Strategy_pattern –

+0

Un barco puede pasar de buque mercante a pirata ** en tiempo de ejecución **, por lo que las interfaces no funcionarán para este tipo de comportamiento dinámico. –

+0

@amadeus: no entiendo tu punto. Si está "programando para interfaces", puede hacerlo con precisión. – Bhushan

Respuesta

2

Ok, aquí están algunas ideas:

  • buques tienen uno o más medios de propulsión (remos, velas, etc.), que se puede modelar por la composición (por ejemplo, tienen una lista de métodos de propulsión).
  • buques utilizan uno de una variedad de estrategias (utilice el patrón de estrategia - ver http://en.wikipedia.org/wiki/Strategy_pattern - para esto)
  • estrategias que dependen de la presencia de buques cercanos necesitará alguna forma de consulta para aquellos otros buques - por lo que necesitará algún tipo de estructura de datos que le permita encontrar qué objetos están cerca de qué otros objetos (observe el tipo de estructuras de datos que se utilizan para la detección de colisiones de amplia fase)

Como alternativa a el patrón de estrategia, puede cambiar a usar un diseño basado en componentes. En esta configuración, un buque estaría compuesto por uno o más componentes de propulsión, un componente estratégico, etc. Luego podría combinar los componentes individuales según lo crea conveniente para fabricar diferentes recipientes.

Como bonificación adicional, los diseños basados ​​en componentes son muy útiles si desea que su juego sea basado en datos, porque puede escribir un salvador/cargador para cada tipo diferente de componente, en lugar de para cada tipo posible de buque.

Es posible que desee ver aquí si está interesado en este tipo de enfoque:

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

5

Haga que el "comportamiento" sea parte de las interfaces. Eso te ayudará a asignar diferentes comportamientos a diferentes barcos sin problema. Strategy Pattern es útil aquí. En pocas palabras, establece que las propiedades cambiantes y constantes deben separarse.

Para diferentes medios de movimientos, la composición suena como la respuesta más adecuada en este momento.

En cuanto al "pero puede funcionar en flotas, escuadrones o de forma independiente. Los corsarios y los piratas solo atacan si son más débiles, generalmente de forma independiente, pero ocasionalmente en parejas". parte, creo que esto no tiene nada que ver con el árbol de herencia. Puedes hacer "grupos" de clases dependiendo de tus necesidades.

Esto podría ayudarle a:

enter image description here

"Hay, pues varios tipos de estilo de los vasos: ..." es especificar diferentes comportamientos posibles. Entonces la interfaz "movible" y sus subclases son para eso. En la clase "Buque", puede tener un miembro de tipo "Movible". Como "Movible" es una interfaz, cualquier clase que la implemente se puede asignar a este miembro. Entonces, cualquier subclase de Vasija puede tener cualquier comportamiento posible, que también podemos cambiar en tiempo de ejecución. También puede convertirlo en ArrayList. (No estoy seguro de si realmente quieres hacerlo o no). Pero si necesita múltiples comportamientos diferentes para un mismo buque, puede hacerlo.

Cuando dice "Los barcos también tienen diferentes comportamientos: ..." parece que las clases separadas que extienden el barco cumplirán este requisito. Sin embargo, la oración "No hay cruce de tipos en este caso". Hace la vida más fácil.

Para el nido para "Finalmente hay varios comportamientos que los barcos individuales pueden tener ...", debe agregar un miembro más para diferentes comportamientos posibles. Principalmente será una ArrayList ya que un barco tendrá múltiples modos de ataque.

Para el último párrafo, si puede dar más detalles, puedo dar algunas ideas más.

+0

Ese diagrama es el tipo de idea que surgió originalmente, sin embargo, me di cuenta de que todavía necesito otra capa. Por ejemplo, ¿cómo creo tres recipientes? ¿Un balandro mercante con aparejo cuadrado, otro aparejo de proa y popa y un balandro pirata aparejado a proa y popa? Necesitaría MUCHAS clases más para obtener todas las combinaciones posibles. Terminaría con FAPirateSloop extends Pirate implementa ForeAndAft, SQPirateSloop extends Pirate implementa SquareRigged etcetc. –

1

Debe separar los tipos y usar el patrón strategy.
Las propiedades inmutables deben vincularse al árbol de herencia (por ejemplo, una fragata no se convertirá en canoa, estos son tipos exactos, no conductuales, que heredan del buque) y todo lo que pueda cambiar debe almacenarse como referencias a tipos de comportamiento que son intracambiable (Man-o-war es un tipo de comportamiento)
AI debe manejarse por separado, por ejemplo con estados, pero eso también tiene que estar en un módulo diferente en su arquitectura.

1

En lugar de pensar en ello como estrictamente herencia, creo que hay que pensar sobre el objeto y cómo Composition eso puede ayudar a hacer las cosas más fáciles.

Por ejemplo: un barco tiene un Comportamiento. (Composición ... los delegados de la nave a la conducta para determinar cómo reaccionar a la situación X)

un pirata es un comportamiento (herencia de una interfaz de Comportamiento) ...

+2

Técnicamente hablando, un pirata es un tipo enojado con un parche en el ojo que dice "¡Arrr!" mucho y hace que las personas caminen por el tablón.El comportamiento pirata es un comportamiento :) Tenga en cuenta que este no es un punto totalmente bromista, ya que las personas que ven una clase llamada 'Pirata 'no esperarían que fuera un comportamiento. –

+0

@StuartGolodetz - ¿podría ser ese el lugar donde utilizo "Piracy" como clase para eliminar la confusión? –

+1

Un buen punto para tener cuidado al nombrar ... Admitiré que acabo de sacar la pregunta original sin pensar demasiado y ¿a quién no le gustan los piratas? (Bueno ... además de ninjas): D – Charlie

2

quiero proporcionar una un consejo basado en el segundo párrafo de la respuesta de Bhusan, que cito aquí en su totalidad:

"En relación con" pero puede funcionar en flotas, escuadrones o de forma independiente. Los corsarios y los piratas solo atacan si son más débiles, generalmente de forma independiente, pero ocasionalmente en parejas. "En parte, creo que esto no tiene nada que ver con el árbol de la herencia.Usted puede hacer "grupos" de clases dependiendo arriba en su necesidad."

Esto me lleva a creer que, además, puede que desee considerar el patrón compuesto para ciertos grupos de buques, al menos aquellas que se componen de barcos que todos comparten el mismo comportamiento. Consulte http://en.wikipedia.org/wiki/Composite_pattern donde está escrito que "el patrón compuesto describe que un grupo de objetos debe tratarse de la misma manera que una instancia única de un objeto."

Por ejemplo, usted dice " Los comerciantes pueden estar en un convoy (defenderse) ", pero presumiblemente también pueden defenderse individualmente. Por supuesto, todo es más fácil decirlo que hacerlo, y mi consejo para usted es no pensar demasiado y comenzar con una pequeña subs et de lo que quiere hacer como un prototipo

+0

El compuesto funcionará para grupos que siempre se mantienen unidos, pero se necesitará un manejo cuidadoso cuando los barcos puedan separarse del grupo principal, p. Ej. es posible que deban considerar abandonar el compuesto si navegan demasiado lejos. –

+0

No creo que los patrones compuestos tomen una posición en grupos estáticos o dinámicos de todos modos. – alphazero

1

No debe extender la clase de recipiente. Más bien, un objeto de barco debería contener otros objetos que lo describan. (Esto se conoce como Inyección de Dependencia, ser molestamente pedante; olvide que dije eso). Tiene una clase de propulsión, con ejemplos de velas cuadradas, ida y vuelta, y remos. Es posible que desee instancias especiales de cada uno para cascos grandes y pequeños. Tienes una clase de Comportamiento para manejar su actitud. Algunas veces, un entero simple funciona tan bien como una clase. Su clase de Armamento podría ser, en cambio, solo una cantidad de armas. (O dos números, uno para poundage.) Si espera embestir, o tiene un barco cargado con cohetes, o necesita distinguir entre armas largas y carronadas, es posible que necesite volver a usar una clase.

Esto le permite cambiar las características sobre la marcha si lo desea, aunque probablemente no lo haga. Aún así, puede pasar de navegar a usar barridos, o cambiar el comportamiento audaz de la nave con el comportamiento de guardar un cargamento de un comerciante para implementar un capitán perdiendo el valor. De todos modos, está ahí si lo necesitas.

+0

Una buena respuesta concisa, gracias. Casi recogí la misma idea de una combinación de otras respuestas, pero la fraseó bien. –

Cuestiones relacionadas