• No results found

O projeto do primeiro jogo, para movimentos específicos, inicia a partir da classe Airpla- neGame, que é a principal do projeto. Esta agrega os componentes importantes do jogo, possui a referência do dispositivo gráfico e do dispositivo de entrada utilizado (Kinect), além do gerenciador de configuração do jogo e do controle sobre a dinâmica e interação. Nesta

4.2 Desenvolvimento e Arquitetura dos Jogos (Módulo do Paciente) 34

classe os elementos mostrados na tela são instanciados, trocam mensagens e realizam o teste de colisão. É possível observar na Figura 4.8 o diagrama de classes no projeto do jogo para movimentos específicos.

Figura 4.8: Diagrama de classe do jogo para movimentos específicos

No trecho de código simplificado (Código 4.1) é possível observar a inicialização dos componentes do jogo através do método Initialize, onde as imagens e profundidade captu- radas pelo Kinect são adicionadas ao jogo, assim como as referencias aos componentes de jogabilidade. Também está descrito de forma simplificada o método Update, que atualiza as informações na tela e constantemente checa a colisão entre dois componentes do jogo. O método Update de cada componente ligado à classe AirplaneGame é responsável pela atualização do próprio estado e posição no jogo.

Código Fonte 4.1: Método Update da classe

1 / / I n i c i a l i z a os c o m p o n e n t e s 2 p r o t e c t e d o v e r r i d e void I n i t i a l i z e ( ) { 3 t h i s . Components . Add ( t h i s . d e p t h S t r e a m ) ; 4 t h i s . Components . Add ( t h i s . c o l o r S t r e a m ) ; 5 t h i s . Components . Add ( t h i s . a i r p l a n e ) ; 6 t h i s . Components . Add ( t h i s . s t o n e ) ; 7 b a s e . I n i t i a l i z e ( ) ; 8 }

9 p r o t e c t e d o v e r r i d e void Update ( GameTime gameTime ) { 10 / / I m p r i m i r i n f o r m a c a o do a n g u l o na t e l a 11 d i s p l a y I n f o ( ) ;

4.2 Desenvolvimento e Arquitetura dos Jogos (Módulo do Paciente) 35 13 c o l l i s i o n T e s t ( ) ; 14 / / A t u a l i z a r p o n t u a c a o 15 u p d a t e S c o r e ( ) ; 16 b a s e . Update ( gameTime ) ; 17 }

Os elementos de ColorStreamRerender, DepthStreamRerender e SkeletonStreamReren- dersão utilizados para realizar a comunicação com os sensores do Kinect, ativando o fluxo de cor, profundidade e o motor para reconhecimento de corpo humano. Tais elementos são utilizados para mostrar a imagem do jogador na tela do jogo e para realizar a detecção de movimento, que servirá como entrada para o elemento Airplane.

A classe Airplane e a é responsável por controlar a captura de movimentação e o perso- nagem no jogo. A Stone é responsável por estimular a dinâmica do jogo, devendo o jogador sempre evitar colidir com os objetos desta classe com seus movimentos.

a) Capturando Movimentos

A classe Airplane utiliza os dados do corpo humano capturados pelo Kinect para controlar a movimentação do personagem no jogo. O componente responsável por se comunicar com o dispositivo de entrada, o Kinect, e capturar o esqueleto humano é o SkeletonStreamRerender, retornando um objeto que representa o esqueleto humano em 21 articulações, ilustradas na Figura 4.9

Figura 4.9: Ilustração das articulações captadas pelo Kinect. Fonte: (WEBB; ASHLEY, 2011).

4.2 Desenvolvimento e Arquitetura dos Jogos (Módulo do Paciente) 36

Para se comunicar com o dispositivo, é necessário informar ao sensor que o fluxo de dados deve ser inicializado. O trecho de código descrito no Código 4.2 é utilizado pela classe SkeletonStreamRerenderpara capturar o objeto do tipo Skeleton. Estes dados, assim como os dados de imagem e profundidade, são obtidos através de um fluxo de dados constante que é capturado a cada novo quadro.

Código Fonte 4.2: Método Update da classe SkeletonStream.

1 u s i n g ( v a r s k e l e t o n F r a m e = t h i s . Chooser . S e n s o r . S k e l e t o n S t r e a m . OpenNextFrame ( 0 ) ) 2 { 3 / / Algumas v e z e s o f r a m e vem n u l o 4 i f ( n u l l == s k e l e t o n F r a m e ) 5 { 6 r e t u r n ; 7 } 8 i f ( n u l l == s k e l e t o n D a t a | | s k e l e t o n D a t a . Length != s k e l e t o n F r a m e . S k e l e t o n A r r a y L e n g t h ) 9 { 10 s k e l e t o n D a t a = new S k e l e t o n [ s k e l e t o n F r a m e . S k e l e t o n A r r a y L e n g t h ] ; 11 } 12 s k e l e t o n F r a m e . C o p y S k e l e t o n D a t a T o ( s k e l e t o n D a t a ) ; 13 s k e l e t o n D r a w n = f a l s e ; 14 }

Os objetos que podem ser acessados a partir da identificação do esqueleto humano iden- tificado no SkeletonStream estão ilustrados na Figura 4.10. Com estes dados é possível saber a posição de cada articulação que representa o jogador nos planos X, Y e Z.

b) Posição do Corpo e o Cálculo dos Ângulos entre as Articulações

É possível detectar diferentes posições de um corpo com o Kinect através de diversas rela- ções entre as articulações. Diferentemente de gestos, que possuem ações de articulações e movimentos em um período de tempo, a detecção de uma pose ou posição utiliza um corpo que está inerte [Webb e Ashley 2011]. Por exemplo, durante um determinado momento que é necessário detectar uma posição simples, como levantar as mãos, deve-se verificar a relação entre a articulação que representa a mão e sua posição relativa no eixo vertical à articulação da cabeça.

Supondo uma postura em que o utilizador estende seus braços, afastando-os do corpo, na altura dos ombros, formando a posição de uma cruz. É possível detectar esta posição

4.2 Desenvolvimento e Arquitetura dos Jogos (Módulo do Paciente) 37

Figura 4.10: Modelo de objetos do esqueleto captado pelo Kinect. Fonte: (WEBB; ASH- LEY, 2011).

utilizando apenas o eixo vertical para as articulações da mão, cotovelo e ombro. Outras técnicas que podem ser utilizadas para detectar posições são a intersecção da posição das articulações e pelo calculo do ângulo entre duas articulações adjacentes.

A identificação das posições pode ser feita a partir do cálculo do ângulo entre diferentes articulações do corpo. O Kinect, através da detecção do esqueleto disponível no pacote de desenvolvimento, permite a manipulação de até vinte pontos diferentes do corpo humano. Para calcular o ângulo entre quaisquer dois dos pontos, é feita uma triangulação, estendendo- se um terceiro ponto para formar um triângulo, e para saber o ângulo entre duas articulações é utilizada a lei dos cossenos. A lei dos cossenos para o triângulo ilustrado na Figura 4.11 é dada pela equação 4.1. Isolando o ângulo na equação, é possível encontrar o ângulo pela equação 4.2

4.2 Desenvolvimento e Arquitetura dos Jogos (Módulo do Paciente) 38 c2 = a2+ b2− 2ab cos θ (4.1) θ= arccos(a 2+ b2 − c2 2ab ) (4.2)

Para a utilização com duas articulações detectadas pelo Kinect, o terceiro ponto do trian- gulo é um ponto arbitrário, estendido no plano que se deseja mensurar o ângulo. É possível utilizar diferentes planos para realizar o cálculo do ângulo. No Código 4.3 a função em des- taque retorna o ângulo entre duas articulações, que devem ser adjacentes, no plano coronal.

Código Fonte 4.3: Função da classe UtilsKinect para calcular o ângulo entre duas artucula- ções no plano coronal

1 c l a s s U t i l s K i n e c t { 2 p u b l i c s t a t i c double G e t J o i n t A n g l e C o r o n a l ( J o i n t z e r o J o i n t , J o i n t a n g l e J o i n t ) { 3 double xx = z e r o J o i n t . P o s i t i o n .X + a n g l e J o i n t . P o s i t i o n .X; 4 double xy = z e r o J o i n t . P o s i t i o n .Y; 5 double a , b , c ; 6

7 a = Math . S q r t ( Math . Pow ( z e r o J o i n t . P o s i t i o n . X − a n g l e J o i n t . P o s i t i o n . X, 2 ) + Math . Pow ( z e r o J o i n t . P o s i t i o n . Y − a n g l e J o i n t . P o s i t i o n . Y, 2) ) ;

8 b = a n g l e J o i n t . P o s i t i o n . X;

9 c = Math . S q r t ( Math . Pow ( a n g l e J o i n t . P o s i t i o n . X − xx , 2) + Math . Pow ( a n g l e J o i n t . P o s i t i o n . Y − xy , 2) ) ;

10 double angleRad = Math . Acos ( ( a ∗ a + b ∗ b − c ∗ c ) / (2 ∗ a ∗ b ) ) ; 11 double angleDeg = angleRad ∗ 180 / Math . PI ;

12 13 i f ( z e r o J o i n t . P o s i t i o n .Y < a n g l e J o i n t . P o s i t i o n .Y) { 14 angleDeg = 360 − angleDeg ; 15 } 16 r e t u r n angleDeg ; 17 }

Os dados do esqueleto humano provenientes do Kinect podem apresentar um grau de erro devido à natureza de captura do dispositivo, já que é uma tecnologia não invasiva e que calcula as posições a partir do processamento das imagens e dados do sensor de profundi- dade. A posição de uma articulação pode apresentar uma pequena variação, assim, o cálculo do ângulo entre duas articulações também pode apresentar variação, como foi identificado por Fernandez’Baena [Fern’ndez-Baena, Susin e Lligadas 2012].

4.2 Desenvolvimento e Arquitetura dos Jogos (Módulo do Paciente) 39

c) Monitorar Posição e Coluna

Durante o exercício o sistema deve guiar o paciente a executar os movimentos da forma cor- reta, a partir da repetição do movimento especificado no intervalo de tempo e na angulação definida. Além disso, é necessário observar e registrar caso o paciente efetue algum exercício de forma incorreta. Um exemplo de execução de exercício na forma errada acontece quando o paciente não alcança ou mesmo ultrapassa a angulação definida pelo fisioterapeuta.

Além de seguir os exercícios nos ângulos definidos, o paciente deverá manter a postura ereta durante a sessão. Tal postura poderá ser ajustada com o auxílio de um profissional e também é detectada e informada ao paciente pelo sistema. O Código 4.4 descreve a função responsável por tal verificação. Caso o paciente realize alguma inclinação para os lados, ocasionará na execução errada do movimento e será registrada no arquivo de relatório para o fisioterapeuta, além de ser informada na tela do jogo.

Código Fonte 4.4: Função que monitora o posicionamento e se há desviu na coluna

1 p r i v a t e b o o l M o n i t o r a r P o s i c a o C o l u n a ( ) {

2 double h i p = s k e l e t o n S t r e a m . mySkeleton . J o i n t s [ J o i n t T y p e . H i p C e n t e r ] . P o s i t i o n .X; 3 double s p i n e d = s k e l e t o n S t r e a m . mySkeleton . J o i n t s [ J o i n t T y p e . S p i n e ] . P o s i t i o n .X; 4 double s h o u d e r = s k e l e t o n S t r e a m . mySkeleton . J o i n t s [ J o i n t T y p e . S h o u l d e r C e n t e r ] .

P o s i t i o n . X;

5 i f ( Math . Abs ( h i p − s p i n e d ) > 0 . 0 2 | | Math . Abs ( s p i n e d − h i p ) > 0 . 0 2 | | 6 Math . Abs ( h i p − s h o u d e r ) > 0 . 0 2 | | Math . Abs ( s h o u d e r − h i p ) > 0 . 0 2 | | 7 Math . Abs ( s p i n e d − s h o u d e r ) > 0 . 0 2 | | Math . Abs ( s h o u d e r − s p i n e d ) > 0 . 0 2 )

8 {

9 e s t a d o D a C o l u n a = "Coluna com desvio" ; 10 r e t u r n t r u e ; 11 } 12 e l s e { 13 e s t a d o D a C o l u n a = "Coluna normal" ; 14 r e t u r n f a l s e ; 15 } 16 }