2011-11-01 2 views
8

lector de tiempo largo póster por primera vez. Por favor se gentil.clases 'Autoconscientes'?

Avidly crear juegos en VB.net. Siendo un programador aficionado, doy mis juegos de forma gratuita. Como soy un hobbiest sin formación formal, intento educarme sobre los principios de programación adecuados y los sigo cuando programo, como OOP. Sin embargo, hay algunas cosas que obviamente me perdí de ser autodidacta que tal vez yo sabría si tuviera una educación formal.

Una vez que el problema que realmente ha sido mi perdición es cómo las diferentes clases (de ahora en adelante referidos como objetos) 'saben' el uno del otro SIN programar interacción específica (quédense conmigo aquí ... por favor ...)

bien imaginar esto, usted tiene un espacio de juego y los siguientes objetos

  • clsShip
  • clsMissile
  • clsAsteroid
  • clsSpaceJunk

Ahora cada uno de estos objetos tiene un Health, X, Y y Z, miembros privados y propiedades que son todos heredados de clsSpaceEntity por argumento sake. Ahora bien, una forma de abordaje de programación entre ellos sería para codificar los datos del siguiente lógica en el bucle principal del juego

para cada buque en una lista de buques
cheque cada clsMissile en una lista para ver si se choca con él y si así, reducir la salud
cheque cada clsAsteroidin una lista para ver si se choca con él y si es así, reducir la salud
cheque cada lista clsSpaceJunka para ver si se choca con él y si es así, reducir la salud
... y así y así sucesivamente para cada objeto siguiente

ect ect ect ...

Ahora bien, esto podría salir bien si hablas del simple ejemplo anterior, pero algunos de mis juegos tienen decenas o incluso CIENTOS de objetos que interactúan de esta manera básica.

Ahora mi pregunta a los programadores experimentados que hay.

¿Hay una manera de programación orientada a objetos para hacer lo siguiente ...

para cada cosa que hereda de clsSpaceEntity
control contra cualquier otro objeto que hereda este tipo (excepto sí mismo) y si colisionan luego reducen la salud
siguiente

?

Este tipo de capacidad para un tipo de objetos/clase o lo que sea para 'conocer' a otro y cómo son iguales/diferentes e interactúan me ahorraría toneladas y toneladas y TONELADAS de codificación.

Cualquier ayuda/ayuda o comentario sobre esto sería muy apreciada. Gracias por su tiempo, perdón por la larga lectura.

+7

No utilice la notación húngara ('clsWhatever'). – SLaks

+1

Parece que está tratando de lograr la separación adecuada de las preocupaciones. Usando algunos conceptos más de OOP, puede hacer una lógica bellamente separada sin métodos gigantes que manejen todo tipo de objeto. ¡Buena suerte! – SLaks

+1

Un poco fuera de tema, pero pareces un poco confundido acerca de las clases y los objetos. Si bien están relacionados, no son lo mismo. Este cuadro de comentarios es un poco pequeño para una explicación completa, pero leer las diferencias te haría la vida más fácil. –

Respuesta

7

En lugar de tener un List(Of T) por separado para cada objeto derivado, debe crear un solo List(Of SpaceEntity) que contenga todas sus entidades.

Puede hacer un anidado For Each bucle que recorre cada par de entidades y realiza la comprobación de colisión. (Después de una comprobación If x <> y)

Puede mejorar aún más su diseño, dando SpaceEntity una función MustOverride para manejar colisiones con otros objetos, sin contaminar el bucle de colisión con la lógica separada para cada entidad.
Probablemente deberías usar el visitor pattern para permitir que las entidades reaccionen de manera diferente a las colisiones con otros tipos de entidades.

Tenga en cuenta que cada colisión se enviará a ambos objetos que colisionaron por separado; necesitas manejar eso en tu lógica.

2

Si estaba escribiendo la lógica que se refiere a un solo barco, o un solo misil, asteroide, etc. Entonces esa lógica debería pertenecer claramente a la clase respectiva.

Si escribo lógica que trata con múltiples objetos o, incluso peor, múltiples objetos de diferentes tipos, tendería a poner esa lógica en una clase que representa un concepto de nivel superior.

Por ejemplo, es posible que tenga una clase de universo que contenga una colección de SpaceEntity. Y hay un universo. FindCollisions() que devuelve una colección de objetos de colisión.

public class Universe { 
    private IEnumerable<SpaceEntity> _entities; 

    public IEnumerable<Collision> FindCollisions() { 
     foreach(var e1 in _entities) { 
      foreach(var e2 in _entities) { 
       if (e1.CollidesWith(e2)) { 
        yield return new Collision(e1, e2); 
       } 
      } 
     } 
    } 
} 

Otra manera de abordar que podría ser tener una clase CollisionCalculator que acepte una colección de SpaceEntity de en su constructor y es el lugar donde vive ese lógicos específicos.

public class CollisionCalculator { 
    public IEnumerable<Collision> Collisions {get; set;} 

    public CollisionCalculator(IEnumerable<SpaceEntity> entities) { 
     // logic to build the Collisions collection goes here 
    } 
} 
+0

Ese bucle foreach anidado devolverá dos colisiones por cada par de entidades superpuestas. Uno para el misil que colisiona con la roca y otro para la roca que colisiona con el misil. Es posible que deba filtrarlos, dependiendo de cómo se maneje la resolución de colisión. – tcarvin

+0

Puede valer la pena señalar que el doble anidado para el bucle se volverá impráctico a medida que el número de objetos aumenta (más de unos pocos cientos). Si hay alguna distancia entre los objetos que garantice que posiblemente no puedan colisionar, puede ser útil subdividir el universo en bloques que son más grandes que eso, y mantener una lista de los objetos que están al menos parcialmente en cada bloque. Con el uso de particiones simples en el espacio 3D, algunos objetos pueden aparecer en hasta ocho listas, pero probar 100 grupos de diez objetos para colisiones será más rápido que probar un grupo de 1,000. – supercat

+0

Por cierto, es posible y no excesivamente difícil subdividir el espacio tridimensional en regiones de modo que ningún objeto caiga en más de cuatro regiones (en lugar de ocho). Si al redondear Y al entero más cercano se obtiene un número impar, sume 0.5 a X. Si redondear Z al entero más cercano arrojaría un número impar, agregue 0.5 a X e Y. Luego redondee las tres coordenadas a números enteros. Un mapeo entre las coordenadas espaciales y los valores XY mostraría que el espacio se dividió en cubos unitarios colocados de manera que no más de cuatro estarían dentro de un cuarto de unidad de cualquier punto. – supercat