Para demonstrar como o uso do Kinect para interação com um aplicativo pode ser facilitado com o uso da biblioteca descrita anteriormente, usaremos um código para controlar uma aplicação de exibição de fotos.
Neste programa, após escolhido o diretório onde as imagens se localizam, é exibida a primeira imagem em ordem alfabética de nome. Na janela onde a estará sendo exibida a imagem, haverá dois botões, um para passar para a próxima imagem e outro para voltar a imagem anterior. Será permitido ainda nesse programa aplicar zoom em uma imagem ou girá-la em qualquer direção, como também avançar ou voltar na galeria apenas por deslizar a mão para a esquerda ou direita, respectivamente.
Abaixo, temos o código necessário para criar a nossa aplicação.
struct Botao{
public Texture2D textura;
public Rectangle retangulo;
public bool estaDentro(int x, int y){
return (x > retangulo.Left && x < retangulo.Right && y >
retangulo.Top && y < retangulo.Bottom);
}
public Botao(Texture2D text, Rectangle ret){
textura = text;
retangulo = ret;
}
}
class Exemplo: Tela{
Botao avancar;
Botao voltar;
int qualFoto;
List<Texture2D> fotos;
Rectangle areaFoto;
CursorKinectDuplo cursor;
Exemplo(Game1 slider) : base(slider) {
avancar = new Botao(slider.Content.Load<Texture2D>("avancar"),new Rectangle(100, 100,50, 50));
voltar = new Botao(slider.Content.Load<Texture2D>("voltar"), new Rectangle(200, 100, 50, 50));
cursor = new CursorKinectDuplo(slider);
fotos = carregaFotosDiretorio();
qualFoto = 0;
areaFoto = new Rectangle();
}
public override void Update(GameTime gameTime){
cursor.Update(gameTime);
if (cursor.DelizaLeft && qualFoto < fotos.Count)
qualFoto++;
else if (cursor.DelizaRight && qualFoto > 0)
qualFoto--;
if ((avancar.estaDentro((int)cursor.DirX, (int)cursor.DirY) &&
cursor.BotaoDireito == CursorKinectDuplo.estadoPressao.PRESSIONADO)
||
(avancar.estaDentro((int)cursor.EsqX, (int)cursor.EsqY) && cursor.BotaoEsquerdo
== CursorKinectDuplo.estadoPressao.PRESSIONADO)){
if (qualFoto < fotos.Count)
qualFoto++;
}else if ((voltar.estaDentro((int)cursor.DirX, (int)cursor.DirY) &&
cursor.BotaoDireito == CursorKinectDuplo.estadoPressao.PRESSIONADO)
||
(voltar.estaDentro((int)cursor.EsqX, (int)cursor.EsqY) &&
cursor.BotaoEsquerdo == CursorKinectDuplo.estadoPressao.PRESSIONADO)){
if(qualFoto > 0 )
qualFoto--;
}
if(cursor.ZoomIn)
aumentaZoom();
else if(cursor.ZoomOut)
diminuiZoom();
base.Update(gameTime);
}
public override void Draw(GameTime gameTime){
spriteBatch.Draw(avancar.textura, avancar.retangulo, Color.White);
spriteBatch.Draw(voltar.textura, voltar.retangulo, Color.White);
spriteBatch.Draw(fotos[qualFoto], areaFoto, Color.White);
cursor.Draw(gameTime);
base.Draw(gameTime);
}
Nas primeiras linhas do nosso código, definimos um struct chamado Botao, que irá facilitar o manuseio desse tipo de objeto em uma aplicação feita em XNA. Neste struct, temos a textura (imagem) que representará o botão, sua posição e uma função para verificar se certo ponto está dentro do botão.
Em seguida, começamos a traçar nossa classe Exemplo, para exibir a interface do nosso programa. Note que essa classe deriva da classe Tela, mas isso não interfere no resultado que iremos demonstrar.
Iniciamos declarando os botões avancar e voltar, que serão responsáveis pela navegação na galeria. Em sequência, temos uma variável inteira qualFoto que serve para indicar a foto que está sendo atualmente exibida. A lista fotos e o Rectangle área fotos são apenas auxiliares no nosso contexto, sendo que a primeira conterá as fotos da nossa galeria e o segundo a área e posição de visualização.
Então, fazemos a declaração da variável cursor da classe KinectCursorDuplo. Ela será a responsável por nossa interação com o programa.
No construtor da classe, fazemos a inicialização das variáveis. A única inicialização relevante porém é a da variável cursor, que recebe uma variável da classe Slider no seu construtor. Essa classe é na verdade a classe onde está o loop principal do jogo XNA e pode ter qualquer nome, bastando para isso uma refatoração.
Partimos então para a função Update, que é onde as ações são realmente executadas, e a variável cursor vai ter seu poder destacado. A primeira coisa que é necessária se fazer é chamar a função Update da variável cursor para atualizar os valores dentro desta. Feito isso, podemos usá-la.
A primeira coisa testada é se houve algum deslizamento horizontal, ou para esquerda, ou para direita. Para isso, basta chamar as propriedades DeslizaLeft e DeslizaRight das classes, que são variáveis booleanas, como mostrado anteriormente.
A seguir, temos uma ação com um grau de dificuldade maior, que é a verificação do clique. Primeiro obtemos a localização do cursor na tela, através das propriedades DirX, DirY, EsqX e EsqY. Passamos esses valores, de maneira separada para o caso da coordenada da mão direita e da mão esquerda para a função estaDentro do botão que desejamos verificar. Caso o cursor “esteja dentro” do botão, ou seja, o cursor está sobre o botão, resta saber se ele está o pressionado. Para isso usamos o valor da propriedade BotaoDireito ou BotaoEsquerdo e verificamos se é igual ao valor PRESSIONADO. Desta forma, usando treze linhas de código e sem nenhuma menção direta ao Kinect ou seu SDK, moldamos uma verificação de clique em dois botões da tela, realizado por qualquer uma das duas mãos.
Por fim, voltamos a simplicidade de verificação do movimento de zoom, realizado apenas com o valor de duas propriedades, ZoomIn e ZoomOut, que também são booleanas.
Como pode ser visto neste pequeno exemplo, a utilização do Kinect pode se tornar extremamente simples em muitos aspectos utilizando esta biblioteca.