El documento describe cómo implementar una máquina de estado en un juego usando C# y Visual Studio. Se introduce un tipo enumerado con dos estados posibles (titleScreen y playingGame) y una variable que almacena el estado actual. Dependiendo del estado, los métodos Draw y Update dibujan y actualizan elementos diferentes. Cuando termina el juego, cambia el estado a titleScreen para mostrar la pantalla de título nuevamente.
2. Ahora tenemos un programa que puede ser la
base de nuestro propio juego.
Sin embargo, la estructura del programa ha
evolucionado adicionándoles nuevas
características y arreglando algunos problemas.
Es importante que el programa esté bien
estructurado
◦ Esto lo hace fácil de entender
◦ Fácil de adicionar nuevas características
En este clásico vamos a averiguar como ordenar
nuestro programa para hacerlo más claro y
entendible
3. En este momento, el código tiene un poquito
de desorden.
No existe una estructura en la forma que los
métodos se organizan dentro del código.
Aunque esto no es un problema para el
compilador, pues solamente le concierne si o
no el código es legal, pero puede hacer que el
programa sea difícil de entender.
Es mejor si los programadores hacemos
esfuerzos regulares para asegurarnos que el
código fuente se vea bien.
4. En este momento, hemos visto los métodos
como una manera de rehusar código de
programa.
Es preferible a repetir bloques de sentencias,
el programa puede algún método para hacer
el trabajo.
Esto hace programa más pequeño y fácil de
mantener
◦ Se puede apreciar un fallo sólo lugar.
Sin embargo, es posible utilizar métodos para
mejorar la estructura del programa
5. Este método update llama otros métodos
para actualizar cada elemento en turno.
protected override void Update(GameTime gameTime)
{
updateCheese();
if (lives <= 0)
{
return;
}
updateBread();
updateTomatoes();
}
6. Re areglar el código, no mejore su desempeño.
De hecho, la llamada de métodos hace un poco
más lento que el trabajo
Sin embargo, esto puede tener un enorme
impacto en la manera en como el código se ve
después
Se deben intentar asegurar que todo el tiempo el
código esté organizado de la mejor manera
posible
El término técnico para este esfuerzo se llama “
Refactorizar”
7. VS que ayuda a re
factorizar el
programa
Uno de esos
métodos a crear
partirá de un bloque
de sentencias
8. 1. Crear un método
updateTomatoes.
◦ Vamos a remover
todo el código que
actualiza el sprite
tomato, y vamos a
crear un método para
hacerlo.
9. Previamente hemos visto que podemos
cambiar el nombre de una clase el juego y el
archivo donde estaba almacenada.
Podemos utilizar VS para cambiar los
identificadores de variables y métodos del
programa.
Para identificar mejor lo que el item
actualmente hace.
Esto hace el código más fácil de entender
10. Este método fue creado para establecer el
tamaño y la posición de los sprites en el
juego.
Sin embargo, esto es utilizado para hacer
otras cosas, por ejemplo el puntaje y las
vidas, por lo que tiene más de un rol en la
configuración del juego.
Sería más sensato llamar a este método
setupGame, porque es lo que hace
VS renombra del método y actualiza todos los
lugares en donde ha sido llamado
11. Re nombrando
setupSprite
◦ Esto hace que se
renombre el método y
todas las llamadas de
este método.
◦ Es más fácil que buscar
y remplazar
12. Como cualquier otro
programa, VS tiene la
capacidad de deshacer
los cambios que han
sido hechos.
Es posible seleccionar
esta opción del menú
de edición, o
presionando CtrlZ o
ALTBackspace
13. El comando Layout
desde el menú de
edición, es bueno
para distribuir el
código y hacer todo
alineado referente a
los llaves.
El comando solo
trabaja cuando el
programa será
compilado
14. El pre-procesador, puede ser interrogado para
colapsar secciones de codigo dentro de regiones
que lo hacen mas fácil de entender.
Se crea una región encerrando el código
requerido entre la directivas #region y
#endregion.
El editor hará desaparecer el texto en la región.
Se pueden colocar regiones dentro del programa
para hacerlos mas estructurados.
Nada de esto afecta el funcionamiento del cósigo
en si.
16. Se han adicionado comentarios al código
desde que iniciamos el programa.
Ahora se harán comentarios aun más útiles.
El editor del VS, es capaz de hacer
comentarios que permitan proveer ayuda
interactiva.
La ayuda aparece cuando se necesita.
17. Estos comentarios han sido formateados para
que el editor del VS pueda utilizarlos para
proveer ayuda interactiva.
/// <summary>
/// Draws text on the screen
/// </summary>
/// <param name="text">text to write</param>
/// <param name="textColor">color of text</param>
/// <param name="x">left edge of text</param>
/// <param name="y">top of text</param>
void drawText(string text, Color textColor, float x, float y)
{
// draw text method body here
}
18. VS puede usar la información en los
comentarios para proveer una ayuda
detallada, cuando escribimos un método.
Todos lo métodos en C# y la librería XNA son
documentados en esta forma.
20. Un programa bien diseñado es bien
estructurado internamente y todos los
elementos contenidos en el tienen nombres
que nos indican su propósito.
El entorno de VS provee una gama de
herramientas que ayudan a los
programadores a crear códigos bien
diseñados
◦ Convertir sentencias en métodos.
◦ Hacer que los nombres reflejen su propósito.
◦ Asegurarse que el código sea fácil de leer e
internamente documentado.
21. A los usuarios les agradan solo programas que
están bien estructurados.
VS puede renombrar solamente métodos
privados.
El nombre de un identificador en un programa
debe comenzar con i.
Los programas bien estructurados corren más
rápido
El código de las regiones en un programa puede
estar anidado.
Comentarios solo pueden colocarse al inicio del
programa
22. A los usuarios les agradan solo programas que
están bien estructurados.
VS puede renombrar solamente métodos
privados.
El nombre de un identificador en un programa
debe comenzar con i.
Los programas bien estructurados corren más
rápido
El código de las regiones en un programa puede
estar anidado.
Comentarios solo pueden colocarse al inicio del
programa
23. A los usuarios les agradan solo programas que
están bien estructurados.
VS puede renombrar solamente métodos
privados.
El nombre de un identificador en un programa
debe comenzar con i.
Los programas bien estructurados corren más
rápido
El código de las regiones en un programa puede
estar anidado.
Comentarios solo pueden colocarse al inicio del
programa
24. A los usuarios les agradan solo programas que
están bien estructurados.
VS puede renombrar solamente métodos
privados.
El nombre de un identificador en un programa
debe comenzar con i.
Los programas bien estructurados corren más
rápido
El código de las regiones en un programa puede
estar anidado.
Comentarios solo pueden colocarse al inicio del
programa
25. A los usuarios les agradan solo programas que
están bien estructurados.
VS puede renombrar solamente métodos
privados.
El nombre de un identificador en un programa
debe comenzar con i.
Los programas bien estructurados corren más
rápido
El código de las regiones en un programa puede
estar anidado.
Comentarios solo pueden colocarse al inicio del
programa
26. A los usuarios les agradan solo programas que
están bien estructurados.
VS puede renombrar solamente métodos
privados.
El nombre de un identificador en un programa
debe comenzar con i.
Los programas bien estructurados corren más
rápido
El código de las regiones en un programa puede
estar anidado.
Comentarios solo pueden colocarse al inicio del
programa
27. A los usuarios les agradan solo programas que
están bien estructurados.
VS puede renombrar solamente métodos
privados.
El nombre de un identificador en un programa
debe comenzar con i.
Los programas bien estructurados corren más
rápido
El código de las regiones en un programa puede
estar anidado.
Comentarios solo pueden colocarse al inicio del
programa
28.
29. EL juego que se esta diseñando esta tomando
forma y luce cada vez más como un juego
completo.
Sin embargo, hay un pequeño problema: se
puede jugar solamente una vez.
Cuando se pierden todas las vidas el juego
termina y se debe de comenzar de nuevo el
programa.
En esta sesión, encontraremos cómo hacer un
juego que utilice el estado de la máquina
para comportarse como un juego debería
30. En este momento, el juego está activo tan
pronto se ejecuta.
Cuando la última vida ha sido perdida, éste
deja de funcionar, pero no hay manera que el
jugador pueda iniciar otra partida.
Esta no es una buena práctica de diseño.
El jugador debe de reiniciar el programa cada
vez que quiera jugar otro juego
31. Al inicio del juego, y cuando el juego ha
finalizado, debemos tener una pantalla de
título.
Esto brinda el nombre del juego y una
pequeña parte de arte
32. Nuestro juego tiene dos estados
◦ Desplegando el título en pantalla
◦ Jugando el juego.
Cuando el programa comienza su ejecución
se muestra la pantalla de título.
Cuando el juego finaliza deberá de mostrar
nuevamente la pantalla de título.
El juego debe contener una variable miembro
que almacene el estado del juego
33. Ya hemos visto anteriormente los tipos
enumerados.
◦ Sabemos que el tipo Keys tiene un valor para cada
posible tecla.
Ahora se creara nuestro propio tipo
enumerado.
Por el momento solamente tendrá dos
estados
enum GameState
{
titleScreen,
playingGame
}
34. Éste es el nombre del tipo que se ha creado.
Una vez que se ha declarado este tipo
procedemos a crear variables de dicho tipo.
Este nombre prefijará cualquier valor que
usemos en el programa
enum GameState
{
titleScreen,
playingGame
}
35. Esta es la lista de posibles valores que el tipo
GameState puede tener.
Todos los valores son actualmente más
creados dentro del número, y es como las
computadoras realmente trabajan
enum GameState
{
titleScreen,
playingGame
}
36. Una vez que tenemos el nuevo tipo,
declaramos las variables de este tipo.
La variable state es declarada y establecemos
el valor de GameState.titleScreen.
Este será la variable de estado que controla el
estado del juego.
Esto controlará el comportamiento de los
métodos Draw y Update
GameState state = GameState.titleScreen;
37. El juego de dibujar a diferentes cosas
dependiendo del estado y del cual se
encuentre
switch (state)
{
case GameState.titleScreen:
drawTitle();
break;
case GameState.playingGame:
drawBackground();
drawCheese();
drawBread();
drawTomatoes();
drawScore();
break;
}
38. La variable state además controlará el
comportamiento del juego dentro del método
update
switch (state)
{
case GameState.titleScreen:
// updateTitle changes state to playingGame when A pressed
updateTitle();
break;
case GameState.playingGame:
// updateCheese changes state to titleScreen when game ends
updateCheese();
updateBread();
updateTomatoes();
break;
}
39. El diseño del estado de
la máquina es
mostrado por el
diagrama de estado.
Este muestra el evento
como un valor de
estado y el evento que
causa el cambio.
El punto en color
negro es el punto de
entrada
Title screen
Playing game
[No lives left]
[A button pressed]
40. El método updateTitle el llamado cuando el
juego está en el estado
GameState.titleScreen.
Si el boton A es detectado, se llama a
startGame, cual configura el juego y cambia
el estado a GameState.playingGame
private void updateTitle()
{
if (gamePad1.Buttons.A == ButtonState.Pressed)
{
startGame();
}
}
41. Este método es llamado para iniciar la
ejecución del juego.
Esto le dice a todos los elementos del juego
que se coloquen en su posición inicial.
Y luego cambia el estado para iniciar el juego
void startGame()
{
score = 0;
lives = 3;
startCheese();
startBread();
startTomatoes();
state = GameState.playingGame;
}
42. Este código dentro de updateCheese llama al
gameover si él que eso golpea la parte baja
de la pantalla no hay más vidas.
if (cheese.Y + cheese.SpriteRectangle.Height >= maxDisplayY)
{
cheese.YSpeed = Math.Abs(cheese.YSpeed) * -1;
if (lives > 0)
{
lives--;
}
if (lives == 0)
{
gameOver();
}
}
43. Se ha adicionado un registro de el puntaje
más alto.
Este es actualizado al final del juego.
Este método luego establece el estado del
juego de regreso a GaemState.titleScreen
void gameOver()
{
if (score > highScore)
{
highScore = score;
}
state = GameState.titleScreen;
}
44. Este método dibuja el puntaje más alto en la
pantalla utilizando el método drawText
creado anteriormente.
El llamado cuando el juego está en el estado
titleScreen
void drawHighScore()
{
drawText(
"Highscore : " + highScore + " Press A to play",
Color.Blue,
minDisplayX, minDisplayY);
}
45.
46. Un programa implementado una maquina de
estado utilizando una variable que almacena el
estado que se estaba ocupando.
El programa puede luego responder a eventos de
una manera apropiada a su estado actual.
Un tipo de enumeración es muy apropiado para
almacenar el estado de una máquina de estado.
Algunas veces un evento puede causar el cambio
de estado.
Se pueden dibujar los estados y los eventos en
un diagrama de estado
47. La máquina de estado puede solamente tener
dos estados.
Una máquina de estado siempre cuando un
evento en particular ocurra.
Una variable de un tipo enumerado es
administrada por valores.
Un diagrama de estados muestra los métodos
en el programa
48. La máquina de estado puede solamente tener
dos estados.
Una máquina de estado siempre cuando un
evento en particular ocurra.
Una variable de un tipo enumerado es
administrada por valores.
Un diagrama de estados muestra los métodos
en el programa
49. La máquina de estado puede solamente tener
dos estados.
Una máquina de estado siempre cuando un
evento en particular ocurra.
Una variable de un tipo enumerado es
administrada por valores.
Un diagrama de estados muestra los métodos
en el programa
50. La máquina de estado puede solamente tener
dos estados.
Una máquina de estado siempre cuando un
evento en particular ocurra.
Una variable de un tipo enumerado es
administrada por valores.
Un diagrama de estados muestra los métodos
en el programa
51. La máquina de estado puede solamente tener
dos estados.
Una máquina de estado siempre cuando un
evento en particular ocurra.
Una variable de un tipo enumerado es
administrada por valores.
Un diagrama de estados muestra los métodos
en el programa