2011-09-22 4 views
5

En primer lugar, permítanme pedir disculpas por hacer una pregunta que puede parecer un poco vaga (o mal formalizada), pero me falta experiencia para preguntar algo más específico.C# Estructura para objetos en un juego 2D

Estoy construyendo un motor para jugar juegos de aventuras en 2D (el tipo "haz clic en un objeto y pasa algo") en C# y estoy considerando la mejor estructura para ello. Como se puede imaginar, diferentes cosas pueden suceder cuando interactúa con un objeto: si es una puerta, espera ingresar a otra sala, si es una persona, espera comenzar a hablar con ella, etc. Mi idea es lograr este comportamiento con los delegados, como este:

public abstract class GameObject { 
    public delegate void onAction(); 
    public onAction Click; 
} 

public class Door : GameObject { 
    public Door() { 
     Click = new onAction(ChangeRoom); 
    } 
    private void ChangeRoom() { 
     //code to change room here 
    } 
} 

public class Person : GameObject { 
    public Person() { 
     Click = new onAction(StartTalking); 
    } 
    private void StartTalking() { 
     //code to display dialogue here 
    } 
} 

me parece una solución muy elegante, porque si quiero crear un objeto especial con un comportamiento no cubierto por su clase, simplemente puede hacer esto:

specialObject.Click += new onAction(SpecialMethod); 

Pero aquí también es donde las cosas se complican. Quiero que mi motor sea capaz de jugar diferentes juegos simplemente cargando diferentes datos, sin cambios en el motor, así que codificar el SpecialMethod en algún lugar dentro del motor no es una opción, debe ser parte de los datos. Para el objeto normal, todo se puede hacer con (de) serialización, pero por lo que he leído, esto es problemático para los delegados. ¿Puedes sugerir una forma de hacerlo?

P.S .: Como todavía estoy en el nivel de concepto y el código anterior aún no está implementado, puede sugerir cualquier solución que encuentre mejor, incluso una que evite por completo a los delegados.

+0

Parece que está describiendo un motor de reglas http://martinfowler.com/bliki/RulesEngine.html – Jodrell

+1

Creo que puede publicar esta pregunta en http://gamedev.stackexchange.com/ – Luca

+0

Gracias @luca por el enlace. Seguramente lo verificará, aunque a primera vista, parece que este foro es un poco más profesional que yo. –

Respuesta

1

Antes que nada escribir un motor cuando le falta experiencia puede ser más difícil de lo que cree. Le sugiero que escriba su primer juego sin motor y código duro tanto como desee y luego aprenda de la experiencia y escriba su motor ... Sé que eso no es lo que quiere: D

Si no lo ha hecho comprobado pero mira http://www.adventuregamestudio.co.uk/ juega con el editor y piensa en el modelo de objetos debajo. Ayudará.

Dado que desea que sus juegos sean controlados por datos, debe poder cargar y ejecutar código dinámicamente. "No tiene que ser un lenguaje de scripting". Está en contra de mi naturaleza sugerir agregar lenguaje de scripting y aprenderlo al mismo tiempo cuando aprendes cómo construir un motor. .NET Framework tiene un gran sistema de reflexión que le permite cargar código C# y compilarlo en tiempo de ejecución. Debo señalar que esto es una especie de secuencias de comandos en C#, pero hay una falta de definición adecuada del lenguaje de scripting.

Dado que no tienes mucha experiencia en esto, mi sugerencia sería usar archivos XML que definan tus salas y tener una secuencia básica de nodos (comandos) que definen lo que debería suceder cuando haces clic en algo. Debería implementar todos los comandos en su "motor", pero podría crear fácilmente salas nuevas, por lo tanto, juegos similares. XML también será un enfoque muy ampliable ya que debido a su estructura jerárquica le permitirá agregar condiciones, bucles, etc. que ampliarán las capacidades de "scripting" de su motor.

+0

Después de pensar y explorar diferentes opciones, encontré esta respuesta realmente la más útil. Me recordó que no tienes que complicar demasiado las cosas, y me dio una idea que puedo usar como punto de partida. ¡Así que gracias! –

1

No es necesario para codificar la función SpecialMethod en su motor, puede usarlo de diferentes juegos que utilizan su motor:

var medievalDoor = new Door(); 
medievalDoor.Click += OpenDoorNormally; 

Pero en un juego diferente:

var starTrekDoor = new Door(); 
starTrekDoor.Click += SlideDoorUpward; 

Mientras expone el evento Click, no necesita codificar nada en su motor. Se puede poner en su juego que podría tener su motor como una referencia DLL.

+0

If 'medievalDoor.Haga clic en + = OpenDoorNormally' se define en el nivel del motor, que parece ser lo que está impidiendo, entonces tendría que modificar el código del motor cada vez que cambie los datos del juego. – InBetween

0

No veo el problema si la 'decisión' de ejecutar algún comportamiento especial o no se deja al objeto del juego en sí. Si desea que el motor decida, entonces tiene, creo, especificaciones de diseño incompatibles, ya que efectivamente haría que el motor tomara una decisión definida por el juego que es exactamente lo que no quiere.

Crea un campo ISpecialBehaviorProvider en los objetos de tu juego y configúralo en un valor adecuado cuando sea necesario (a través de constructor, propiedad pública, ¿qué tienes?).

Su motor siempre ejecutará GameObject.Click siempre que el usuario haga clic en. Sin embargo, si specialBehaviorProvider es nulo, haga que el GameObject.Click ejecute el código 'en clase'; de lo contrario, llame al ISpecialBehaviorProvider.SpecialMethod.

De esta forma, el motor no tiene nada que ver con la decisión de qué método llamar.

+0

Sí, mi idea es que el motor active el 'GameObject.Click' cuando sea apropiado sin ninguna comprobación. Pero aún así, debo ser capaz de transmitir ese comportamiento especial de algún objeto "desde afuera". Como sugieren las próximas respuestas, estoy en camino de aprender sobre scripting. –

0

Lo primero que señalaré aquí es que ya que estas son las clases, el polimorfismo sería bastante ideal aquí, con un método de clic virtual, por ejemplo.

Los delegados pueden ser realmente complicados para los serializadores, dependiendo del enfoque de serialización.BinaryFormatter hará hacer eso, pero tiendo a evitar ese serializador a toda costa como regla general.

Si es posible, yo sugeriría solo tener su subclase de personalizaciones las implementaciones estándar, y usar polimorfismo. Si se debe definir puramente a través de los datos, esencialmente se estaría implementando un motor de scripting. Muchos de ellos están disponibles en .NET - IronPython puede ser útil, aunque para juegos lua es bastante común (debería poder usar Lua.NET con bastante facilidad). Luego puede tener un script opcional asociado con la acción e invocar el script (definido en los datos).

+0

Diría que el 90% del comportamiento de los objetos podría definirse únicamente por polimorfismo. El problema (como de costumbre) es en los que quedan 10%. ¿Puedo preguntar por qué evitas BinaryFormatter? (Soy bastante nuevo en esa área, también.) –

3

Lo que necesita es scripting.

Esencialmente, una secuencia de comandos es un recurso externo (es decir, un archivo externo) que contiene un código fuente, que describe las acciones.

C# tiene una opción diferente para esto.

Puede emitir ensamblajes desde idiomas .NET. O puede integrar otro idioma (python, por ejemplo) y ejecutar el script en tiempo de ejecución. Básicamente, el script se carga, interpreta o compila y ejecuta en el momento adecuado. Si el script puede modificar el estado de la aplicación (las estructuras de datos), puede definir el comportamiento de los objetos con datos externos (desarrollo basado en datos).

Hay mucha literatura sobre este tema, pero sugiero GPU Programming Gems 6 (sección 4). Sin embargo, el esfuerzo requerido para integrar un gran motor de scripting es mucho. De esa manera intenté descubrir una lógica simple basada en archivos XML (here es mi pregunta acerca de, unirme a otra question para definir los contenidos XML); lamentablemente, descubrí que casi depende de la flexibilidad que necesita.

+0

+1 para scripting. Los IronLanguages ​​son triviales para integrarse en una aplicación .NET y tienen muy buena interoperabilidad con C#: https://github.com/IronLanguages/main – robbrit

Cuestiones relacionadas