Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Programming

Deje a sus jugadores deshacer sus errores en el juego con el patrón de comandos

by
Difficulty:IntermediateLength:LongLanguages:

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

Muchos juegos basados en turnos incluyen un botón de deshacer para permitir a los jugadores revertir los errores cometidos durante el juego. Esta característica se vuelve especialmente relevante para el desarrollo de juegos móviles donde el toque puede tener un reconocimiento táctil torpe. En lugar de confiar en un sistema en el que se pregunta al usuario "¿está seguro de que desea realizar esta tarea?" para cada acción que toman, es mucho más eficiente dejarlos cometer errores y tener la opción de invertir fácilmente su acción. En este tutorial, veremos cómo implementar esto usando el patrón de comandos, usando el ejemplo de un juego tic-tac-toe.

Nota: Aunque este tutorial está escrito con Java, debería ser capaz de usar las mismas técnicas y conceptos en casi cualquier entorno de desarrollo de juegos. (No se limita a los juegos de tic-tac-toe, tampoco!)


Vista previa del resultado final

El resultado final de este tutorial es un juego tic-tac-toe que ofrece ilimitadas deshacer y rehacer operaciones.

Esta demostración requiere que Java funcione.

¿No se puede cargar el applet? Mira el video del juego en YouTube:

También puede ejecutar la demostración en la línea de comandos utilizando TicTacToeMain como la clase principal de la que ejecutar. Después de extraer el código fuente, ejecute los siguientes comandos:


Paso 1: Crear una implementación básica de Tic-Tac-Toe

Para este tutorial, vas a considerar una implementación de tic-tac-toe. Aunque el juego es extremadamente trivial, los conceptos proporcionados en este tutorial pueden aplicarse a juegos mucho más complejos.

La siguiente descarga (que es diferente de la descarga de la fuente final) contiene el código básico para un modelo de juego tic-tac-toe que no contiene una función de deshacer o rehacer. Será su trabajo seguir este tutorial y agregar estas características. Descargue la base TicTacToeModel.java.

Debe tomar nota, en particular, de los siguientes métodos:

Estos métodos son los únicos métodos para este juego que cambian el estado de la rejilla del juego. Ellos serán lo que va a cambiar.

Si no eres un desarrollador de Java, probablemente seguirás entendiendo el código. Se copia aquí si sólo desea referirse a ella:


Paso 2: Entender el patrón de comando

El patrón de comandos Command es un patrón de diseño que se utiliza comúnmente con interfaces de usuario para separar las acciones realizadas por botones, menús u otros widgets de las definiciones de código de interfaz de usuario para estos objetos. Este concepto de separar código de acción se puede utilizar para realizar un seguimiento de cada cambio que ocurre en el estado de un juego, y puede utilizar esta información para invertir los cambios.

La versión más básica del patrón de comandos Command es la siguiente interfaz:

Cualquier acción tomada por el programa que cambie el estado del juego -como colocar una X en un espacio específico- implementará la interfaz de Comando Command . Cuando se toma la acción, se llama al método execute ().

Ahora, probablemente notó que esta interfaz no ofrece la capacidad de deshacer acciones; todo lo que hace es tomar el juego de un estado a otro. La siguiente mejora permitirá implementar acciones para ofrecer capacidad de deshacer.

El objetivo al implementar un comando Command será hacer que el método undo() invierta cada acción tomada por el método execute. Como consecuencia, el método execute() también podrá proporcionar la capacidad de rehacer una acción.

Esa es la idea básica. Será más claro a medida que implementamos comandos específicos para este juego.


Paso 3: Cree un administrador de comandos

Para agregar una función de deshacer, creará una clase CommandManager. El CommandManager es responsable de rastrear, ejecutar y deshacer implementaciones de comandos Command.

(Recuerde que la interfaz de comandos Command  proporciona los métodos para hacer cambios de un estado de un programa a otro y también invertirlo.)

Para ejecutar un comando Command, el CommandManager pasa una instancia de comando Command y ejecutará el comando Command y luego almacenará el comando Command ejecutado más recientemente para referencia posterior.

Agregar la función de deshacer al CommandManager simplemente requiere decirle que deshaga el Comando Command más reciente que se ejecutó.

Este código es todo lo que se requiere para tener un CommandManager funcional. Para que funcione correctamente, tendrá que crear algunas implementaciones de la interfaz de comandos Command.


Paso 4: Crear implementaciones de la interfaz de comandos Command

El objetivo del patrón Command para este tutorial es mover cualquier código que cambie el estado del juego tic-tac-toe en una instancia Command. Es decir, el código en los métodos placeX() y placeO() es lo que va a cambiar.

Dentro de la clase TicTacToeModel, agregue dos nuevas clases internas denominadas PlaceXCommand y PlaceOCommand, respectivamente, que implementan la interfaz Command.

El trabajo de una implementación de comandos Command es almacenar un estado y tener lógica para la transición a un nuevo estado resultante de la ejecución del comando Command o para volver al estado inicial antes de ejecutar el comando Command. Hay dos formas sencillas de lograr esta tarea.

  1. Almacene todo el estado anterior y el estado siguiente. Establezca el estado actual del juego al siguiente estado cuando se ejecuta execute() y configure el estado actual del juego al estado anterior almacenado cuando se invoca undo().    
  2. Almacene sólo la información que cambia entre estados. Cambie sólo esta información almacenada cuando se ejecuta con execute() o se deshace con undo()

La primera opción es un poco derrochadora, pero eso no significa que sea un mal diseño. El código es sencillo y, a menos que la información del estado es muy grande la cantidad de residuos no será algo de qué preocuparse.

Verá que, en el caso de este tutorial, la segunda opción es mejor, pero este enfoque no siempre será el mejor para cada programa. Más a menudo que no, sin embargo, la segunda opción será el camino a seguir.

La segunda opción sólo almacena los cambios que ocurren, en lugar de todo el estado. En el caso de tic-tac-toe, es más eficiente y no notablemente más complejo usar esta opción.

La clase interna de PlaceOCommand está escrita de una manera similar - tiene que escribirlo usted mismo!


Paso 5: Poner todo junto

Para poder utilizar las implementaciones Command, PlaceXCommand y PlaceOCommand, deberá modificar la clase TicTacToeModel. La clase debe hacer uso de un CommandManager y debe usar instancias de comandoCommand en lugar de aplicar acciones directamente.

La clase TicTacToeModel funcionará exactamente igual que antes de los cambios, pero también puede exponer la función de deshacer. Agregue un método undo() al modelo y también agregue un método de control canUndo para que la interfaz de usuario lo utilice en algún momento.

¡Ahora tienes un modelo de juego tic-tac-toe completamente funcional que soporta deshacer!


Paso 6: profundicelo más

Con algunas pequeñas modificaciones en CommandManager, puede agregar soporte para operaciones de rehacer, así como un número ilimitado de deshacer y rehacer.

El concepto detrás de una característica de rehacer es prácticamente lo mismo que una función de deshacer. Además de almacenar el último comando Command ejecutado, también almacena el último comando Command  que se anuló. Almacena ese comando Command cuando se llama a un deshacer y lo borra cuando se ejecuta un comando Command.

La adición de múltiples deshacer y redos es una cuestión de almacenar una pila de acciones que se pueden deshacer y rehacer. Cuando se ejecuta una nueva acción, se agrega a la pila de deshacer y la pila de rehacer se borra. Cuando se deshace una acción, se agrega a la pila de rehacer y se elimina de la pila de deshacer. Cuando se vuelve a realizar una acción, se elimina de la pila de rehacer y se agrega a la pila de deshacer.

Undo and redo in game development with the command pattern

La imagen anterior muestra un ejemplo de las pilas en acción. La pila de rehacer tiene dos elementos de comandos que ya se han deshecho. Cuando se ejecutan nuevos comandos, PlaceX(0,0) y PlaceO(0,1), la pila de rehacer se borra y se agregan a la pila de deshacer. Cuando se deshace un PlaceO(0,1), se quita de la parte superior de la pila de deshacer y se coloca en la pila de rehacer.

Así es como se ve en el código:

Ahora tienes un modelo de juego tic-tac-toe que puede deshacer acciones hasta el principio del juego y volver a hacerlas.

Si quieres ver cómo encaja todo esto, toma la descarga de la fuente final, que contiene el código completo de este tutorial.


Conclusión

Es posible que haya notado que el CommandManager final que escribió funcionará para cualquier implementación de Command. Esto significa que puede codificar un CommandManager en su idioma favorito, crear algunas instancias de la interfaz de comandos Command y tener un sistema completo preparado para deshacer / rehacer. La función de deshacer puede ser una gran manera de permitir a los usuarios explorar su juego y cometer errores sin sentirse comprometidos con las malas decisiones.

¡Gracias por interesarnos en este tutorial!

Como algo más de reflexión, considere lo siguiente: el patrón de comandos Command junto con CommandManager le permiten realizar un seguimiento de cada cambio de estado durante la ejecución de su juego. Si guarda esta información, puede crear repeticiones de la ejecución del programa.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.