é necessário que a classe Movimento tenha um contador para quadros em que o
movimento está em execução. Além disso, ele deve conter um nome e deve pos-
suir métodos que permitam validar se a posição do usuário está de acordo com o
movimento que ele está tentando executar. A classe deve ficar similar à abaixo: public abstract class Movimento
{
protected int ContadorQuadros { get; set; }
public string Nome { get; set; }
public abstract EstadoRastreamento Rastrear(
Skeleton esqueletoUsuario);
protected abstract bool PosicaoValida(
Skeleton esqueletoUsuario);
}
Para que uma pose tenha validade é necessário que ela esteja sendo feita por um período de tempo. A etapa que avalia a pose ao longo do tempo chama-se rastreamento e a etapa que ocorre quando a pose é reconhecida como válida chama-se identificação.
Agora criaremos a classe abstrata que deverá ser utilizada como base para to-
das as poses de nossa aplicação. Ela deverá ser chamada de Pose e deve herdar a classe Movimento, bem como possuir a propriedade que marca em qual frame a
pose é reconhecida e a implementação do método Rastrear herdado pela classe
Movimento. Mas por enquanto deixaremos o método Rastrear em branco e vol-
taremos aqui mais tarde.
public abstract class Pose : Movimento
{
protected int QuadroIdentificacao { get; set; }
public
override EstadoRastreamento Rastrear(
85
7.1. Iniciando a Estrutura Base para Detectar Movimentos
Casa do Código
Skeleton esqueletoUsuario)
{
}
}
Além das classes bases para os movimentos também precisamos de uma classe
que irá rastrear e identificar as poses, então no namespace Movimentos criaremos a interface IRastreador e a classe Rastreador.
A interface IRastreador deve ser implementada por todos os rastreadores.
Em seu corpo deve ser definido o método Rastrear, que recebe por parâmetro o
esqueleto do usuário e não precisa retornar nenhum tipo de valor, e a propriedade EstadoAtual, que deve ser somente leitura.
public interface IRastreador
{
void Rastrear(Skeleton esqueletoUsuario);
EstadoRastreamento EstadoAtual { get; }
}
A classe Rastreador irá fazer o rastreamento de um determinado movimento,
seja ele pose ou gesto, implementando o método Rastrear da interface criada anteriormente. Para configurarmos que tipo de pose ou gesto iremos rastrear é necessária a utilização de generics.
Generics
Generics é uma funcionalidade da linguagem C# que permite ao de-
senvolvedor criar um design de classes que podem aplicar funcionali-
dades a um determinado tipo que será definido apenas na aplicação fi-
nal. Classes genéricas maximizam bastante a reutilização de código, um
exemplo de utilização é a coleção List<T>, onde T pode ser um tipo qual-
quer. Dessa forma, é possível criar listas de qualquer tipo de objeto e ela
terá os mesmos métodos. Para mais informações acesse:
http://msdn.microsoft.com/en-us/library/512aeb7t
Apesar de usar generics, nossa classe Rastreador deve rastrear apenas objetos
que herdem da classe Movimento e que sejam objetos concretos. Podemos definir
86
Casa do Código
Capítulo 7. Rastreando e Identificando Movimentos
isso na própria declaração da classe utilizando a palavra reservada where e defi-nindo as condições desejadas, conforme o código.
public class Rastreador<T> : IRastreador where T : Movimento, new()
{
}
Com este cabeçalho definimos que a classe Rastreador pode ser utilizada com
um tipo genérico, que ela implementa a interface IRastreador e que ela permite
somente tipos que herdem a classe Movimento e que possuem um construtor. Inter-
namente, nosso construtor terá de ter um atributo privado para controlar o próprio objeto referente ao movimento que está sendo rastreado. Além disso, precisaremos criar um evento para quando o movimento é reconhecido e outro para notificar o
progresso do rastreamento. No construtor padrão desta classe iremos inicializar o objeto que armazena o movimento que será rastreado.
public class Rastreador<T> where T : Movimento, new()
{
private T movimento;
public EstadoRastreamento EstadoAtual { get; private set; }
public event EventHandler MovimentoIdentificado;
public event EventHandler MovimentoEmProgresso;
public Rastreador()
{
EstadoAtual = EstadoRastreamento.NaoIdentificado;
movimento = Activator.CreateInstance<T>();
}
}
A classe Activator é utilizada para invocar o construtor do tipo definido como
genérico de nossa classe (existem formas mais performáticas, mas por simplicidade utilizaremos esta no exemplo). Para finalizar a implementação de nosso rastreador iremos implementar o método Rastrear da interface e nele iremos verificar através do método Rastrear da classe Movimento se o mesmo foi identificado ou está
em progresso. De acordo com o estado do rastreamento, chamaremos os eventos.
Não esqueça que é necessário verificar se o evento está nulo antes de chamá-lo. O
código final desta classe deve ficar semelhante ao código a seguir.
public class Rastreador<T> : IRastreador where T : Movimento, new()