Estoy trabajando en un simple juego de rompecabezas basado en bloques.
El juego consiste básicamente en mover bloques alrededor del área de juego, por lo que es una simulación de física trivial. Sin embargo, mi implementación, en mi opinión, está lejos de ser ideal y me pregunto si puede darme algunos consejos sobre cómo hacerlo mejor.
He dividido el código en dos áreas: lógica de juego e interfaz de usuario, como lo hice con muchos juegos de rompecabezas:
- La lógica del juego es responsable de las reglas generales del juego (por ejemplo, el sistema de reglas formales en el ajedrez)
- La interfaz de usuario muestra el área de juego y las piezas (por ejemplo, tablero de ajedrez y piezas) y es responsable de las animaciones (por ejemplo, movimiento animado de piezas de ajedrez)
La lógica del juego representa el estado del juego como una cuadrícula lógica, donde cada unidad es el ancho / alto de una celda en la cuadrícula. Entonces, para una cuadrícula de ancho 6, puede mover un bloque de ancho 2 cuatro veces hasta que colisione con el límite.
La interfaz de usuario toma esta cuadrícula y la dibuja convirtiendo tamaños lógicos en tamaños de píxeles (es decir, la multiplica por una constante). Sin embargo, dado que el juego apenas tiene lógica de juego, mi capa de lógica de juego [1] no tiene mucho que hacer, excepto la detección de colisiones. Así es como funciona:
- El jugador comienza a arrastrar una pieza.
- La interfaz de usuario solicita la lógica del juego para el área de movimiento legal de esa pieza y permite que el jugador la arrastre dentro de esa área
- El jugador suelta una pieza
- La interfaz de usuario ajusta la pieza a la cuadrícula (para que esté en una posición lógica válida)
- La interfaz de usuario le dice a la lógica del juego la nueva posición lógica (a través de métodos mutantes, que prefiero evitar)
No estoy muy contento con eso:
- Estoy escribiendo pruebas unitarias para mi capa de lógica de juego, pero no para la interfaz de usuario, y resultó que todo el código complicado está en la interfaz de usuario: evitar que la pieza colisione con otros o el límite y encajarlo en la cuadrícula.
- No me gusta el hecho de que la interfaz de usuario le dice a la lógica del juego sobre el nuevo estado, prefiero que llame a un
movePieceLeft()
método o algo así, como en mis otros juegos, pero no llegué lejos con ese enfoque, porque la lógica del juego no sabe nada sobre el arrastre y el ajuste que es posible en la interfaz de usuario.
Creo que lo mejor sería deshacerme de mi capa de lógica de juego e implementar una capa de física. Tengo algunas preguntas al respecto:
- ¿Es común esta capa de física o es más típico que la capa de lógica del juego haga esto?
- ¿El ajuste a la cuadrícula y al código de arrastre de piezas pertenecerían a la interfaz de usuario o la capa de física?
- ¿Una capa física de este tipo normalmente funcionaría con tamaños de píxel o con algún tipo de unidad lógica, como la capa lógica de mi juego?
- Una vez vi una detección de colisión basada en eventos en la base de código de un juego, es decir, el jugador simplemente arrastraba la pieza, la interfaz de usuario lo mostraba obedientemente y notificaba al sistema físico, y el sistema físico llamaba a un método onCollision () en la pieza una vez que se detecta una colisión. ¿Qué es más común? Este enfoque o preguntando por el área de movimiento legal primero?
[1] capa probablemente no sea la palabra correcta para lo que quiero decir, pero el subsistema suena exagerado y la clase es errónea, porque cada capa puede consistir en varias clases.
Respuestas:
Intentaré intentar responder esta pregunta, ya que puedo entender lo que estás preguntando, aunque no tengo mucha experiencia en el desarrollo de juegos, ya que todavía solo estoy aprendiendo.
Tal como lo veo, debes separar el código GUI de la lógica del juego y los objetos de dominio, es decir, las piezas del rompecabezas. Estas son de hecho tres capas separadas, y sí,
layer
es un término apropiado en mi opinión. A menudo se usa para explicar los conceptos de separar cada nivel de objetos de un sistema en subsistemas que son independientes entre sí.En lo que respecta a la programación orientada a objetos, cada objeto será una clase. Por lo tanto, cada pieza de tu rompecabezas consistirá en una clase en sí misma y, por lo tanto, en el tablero de juego. El tablero de juego debe contener X piezas de rompecabezas dependiendo de su tamaño y capacidad de movimiento que desee darle al jugador.
Entonces, aquí están mis pensamientos sobre el tema: espero que ayude:
En esta arquitectura, la capa de la GUI le mostrará al jugador el estado del juego, la ubicación de cada pieza del rompecabezas. La capa GUI sería responsable de obtener las entradas del jugador y pasarla a una capa subyacente de Game Controller, que luego sería responsable de la detección de colisiones. Si no hay ninguno, entonces se puede ordenar que la pieza se mueva en esa dirección de entrada. Para hacerlo, simplemente deberías llamar a esta pieza
MoveLeft
,MoveRight
, etc. métodos para hacer que la pieza se mueva. También puedes dejar que el tablero sepa qué pieza quieres mover, y luego ordena por sí sola el movimiento de la pieza, y la pieza luego se mueve en la dirección solicitada. Esta arquitectura facilita la prueba de cada fragmento de código en las diferentes capas, y luego le permite realizar pruebas unitarias, pruebas de integración y pruebas funcionales.Sé que esto puede parecer un poco confuso a la vista, ¡y gracias a Dios si no lo es! Si necesita más información y ayuda, no dude en preguntar, estaré encantado de ayudarlo lo mejor que pueda, aunque soy un principiante en el desarrollo de juegos.
¡Gracias por leer! =)
fuente
Position
función de obtención de propiedades, de modo que el controlador del juego ahora requiere que la GUI muestre esta pieza movida a esa nueva posición.