#KINECTV2 – Piedra, papel, tijera con #KinectForWindowsV2

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

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

image image image Google

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.