Hola!
Después de las fiestas de Navidad y Año nuevo, me pongo al día con renovación como MVP y empezamos con un post de nivel 2 con el nuevo Kinect. En este caso haremos el juego “piedra papel y tijera” con el nuevo Kinect for Windows V2.
Nota: si no sabes como jugar a piedra, papel o tijera, Wikipedia te lo explica aquí.
La verdad es que implementar este juego es bastante simple con Kinect for Windows V2, ya que ahora la propiedad HandState soporta varios estados
- Open
- Closed
- Lasso
- NotTracked
- Undefined
Los 3 primeros nos permiten tener un match claro con los estados del juego
- Open, Papel
- Closed, Piedra
- Lasso, Tijera
De esta forma, lo único que tenemos que hacer es validar los estados de la mano con un Random generado para el ordenador (por cierto, la rutina que genera el Random de un Enum la he sacado de StackOverflow y es una maravilla).
La vista principal de la app posee un boton que al presionarlo, inicia un timer con un contador descendente de 5 segundos. En cada tick del timer se muestra el estado de la mano del jugador (línea 24), y cuando el contador llega a cero, se genera un valor random para el juego (línea 41) y se validan las posibilidades para definir un ganador (líneas 48 a 80).
1: private string GetRockPaperScissorFromHandState(HandState handState)
2: {
3: switch (handState)
4: {
5: case HandState.Closed:
6: return "Rock";
7: case HandState.Open:
8: return "Paper";
9: case HandState.Lasso:
10: return "Scissor";
11: }
12: return "not defined, please play fair !!!";
13: }
14:
15: private void ButtonPlay_OnClick(object sender, RoutedEventArgs e)
16: {
17: ButtonPlay.IsEnabled = false;
18: _gameCounter = 5;
19: _timerGame.Start();
20: }
21:
22: private void GameTimerTick(object sender, EventArgs e)
23: {
24: HumanPlay = GetRockPaperScissorFromHandState(_humanHandState);
25: if (_gameCounter == 0)
26: {
27: _timerGame.Stop();
28: ButtonPlay.IsEnabled = true;
29: DefineWinner();
30: }
31: else
32: {
33: SkynetPlay = _gameCounter.ToString(CultureInfo.InvariantCulture) + " seconds to play ...";
34: _gameCounter--;
35: }
36: }
37:
38: private void DefineWinner()
39: {
40: // get computer play and validate with last human play
41: var skynetPlay = RandomEnum<HandState>();
42: while (skynetPlay == HandState.NotTracked || skynetPlay == HandState.Unknown)
43: {
44: skynetPlay = RandomEnum<HandState>();
45: }
46: SkynetPlay = GetRockPaperScissorFromHandState(skynetPlay);
47:
48: if (skynetPlay == _humanHandState)
49: {
50: TextBlockPlayResult.Foreground = new SolidColorBrush(Colors.Green);
51: PlayResult = "TIED !!!";
52: }
53: else if (
54: (skynetPlay == HandState.Open && _humanHandState == HandState.Closed) ||
55: (skynetPlay == HandState.Closed && _humanHandState == HandState.Lasso) ||
56: (skynetPlay == HandState.Lasso && _humanHandState == HandState.Open))
57: {
58: TextBlockPlayResult.Foreground = new SolidColorBrush(Colors.Red);
59: PlayResult = "SKYNET WINS !!!";
60: }
61: else if (
62: (_humanHandState == HandState.Open && skynetPlay == HandState.Closed) ||
63: (_humanHandState == HandState.Closed && skynetPlay == HandState.Lasso) ||
64: (_humanHandState == HandState.Lasso && skynetPlay == HandState.Open))
65: {
66: TextBlockPlayResult.Foreground = new SolidColorBrush(Colors.Green);
67: PlayResult = "YOU WIN !!!";
68: }
69: else
70: {
71: TextBlockPlayResult.Foreground = new SolidColorBrush(Colors.Red);
72: PlayResult = "Can't track your hand, please play fair !!!";
73: }
74: }
75:
76: public T RandomEnum<T>()
77: {
78: var values = (T[])Enum.GetValues(typeof(T));
79: return values[new Random().Next(0, values.Length)];
80: }
Nota: La verdad es que la sección de validación de resultados la podría implementar de manera “más bonita”, pero luego se me complica escribir el post y explicar esta parte.
En la app además muestro el feed de la camara y el body, en el mismo es posible ver como la coordinación de ubicación de la mano no es 100% correcta entre el video y el body. Zubair lo comentó aquí y lo arreglamos con unos cálculos simples en el código.
El siguiente video, muestra un ejemplo de la app en funcionamiento. En el mismo se puede ver como el Random favorece para que siempre gane Skynet y además como se cambia el color de la mano en las posiciones de peidra, papel o tijera. .
Cuando vuelva a Madrid, hablaré con Gema o con Marta para que me ayuden con la parte estética y dejar la app un poco más “bonita”. Además de cambiarla forma de empezar, para que sea como el clásico piedra, papel tijera.
Recursos
- Wikipedia, piedra, papel o tijera; http://es.wikipedia.org/wiki/Piedra,_papel_o_tijera
- Generate Random from Enum, http://stackoverflow.com/questions/319814/generate-random-enum-in-c-sharp-2-0
- Kinect For Windows V2 Deep Dive, http://www.zubairahmed.net/?p=1652
Y como siempre, el disclaimer
“This is preliminary software and/or hardware and APIs are preliminary and subject to change”
Saludos @ Córdoba
El Bruno
![]() |
![]() |
![]() |