Rune : Gesture Recognizer part 1

Au début il n’y avait rien

A l’origine du projet il y a eu une gamejam pendant laquelle, mon équipe est moi, nous avions parlé d’utiliser les dessins du joueur pour diriger le gameplay. Nous étions inspirés par le jeu « Magic touch »

Crédit : Magic Touch : Wizard for Hire

Cet élément avait été jugé trop audacieux pour être réalisable correctement dans le temps imparti avec les ressources disponibles.

Cependant cette mécanique ne m’est jamais vraiment sortie de la tête et j’ai eu envie de l’utiliser pour mon jeu actuellement développé « Rune ».

Une reconnaissance simple

Dans l’idée de la gamejam j’imaginais détecter uniquement certains mouvements assez facilement reconnaissables entre eux.

Un peu de silence au fond, le cours va commencer

Un peu de théorie avant de parler des algorithmes de détection. Voici le système d’axe utilisé dans cet article :

crédit : openclassroom

Le tracé du joueur est fait par sa souris dès le moment où il appui sur le clique gauche et jusqu’au moment où il relâche le clique gauche. Si le joueur utilise un périphérique tactile, le tracé du joueur début dès que le joueur presse sur l’écran jusqu’à ce qu’il retire son doigt.

Pendant ce tracé on va récolter la position où se trouve la souris/le doigt du joueur et constituer un échantillon de n point partant du premier point (P1) jusqu’au dernier point (Pn) : P1, P2, P3, Pi,  …, Pn-1, Pn

Par exemple pour 5 points : P1, P2, P3, P4, P5 où P5 est notre Pn.

Les points contiennent une coordonnée en X et une en Y de la manière suivante :

Pi = {Xi,Yi}

Par exemple : P5 = {X=12,Y=34} qui peut être écrit P5 = {12,34}

Pour faire référence à une coordonnée en point je peux utiliser la notation suivante: P5.X pour faire référence à la coordonnée X du P5 qui vaut 12.

Les additions et soustraction des points se font par opérations vectorielles. Par exemple l’addition :

P5 = {12,34} et P4 = {10,1}

Delta = P5-P4 = {12,34} – {10,1} = {12-10 = 2 , 34-1 = 33} = {2,33}

Pour le reste de la théorie je vous laisse googler ou me demander dans les commentaires.

1) Un trait à gauche, droite, haut, bas

Très facile à détecter. Il suffit de calculer la différence entre la dernière position et la première position. Si cette différence est nulle sur un des axes (X ou Y) cela veut dire que le joueur a tracé un trait dans une des quatre directions (gauche, droite, haut ou bas). L’axe non nulle de cette différence ainsi que le signe de celui-ci définira la direction. Par exemple:

P1 = premier point = {0,0}

Pn = dernier point = {10, 0}

D = delta = P2 – P1 = {x = 10, 0}

Donc D.x égal à 10. L’axe y (vertical dans ma situation) est nul. Le trait est donc horizontal. Vu que le signe de D.x est positif il s’agît d’un trait allant vers la droite (selon mon système d’axe, on est d’accord). Autre exemple:

P1 = {x = 0, y = 10}

Pn = {x = 0, y = -2}

D = {x = 0, y = -12}

Dans cette situation D.x égal 0. Il s’agît d’un trait vertical. La valeur de D.y est -12 donc le trait va vers le bas dans ma situation.

2) Les flèches /\, \/, <,>

Nous appliquons le même algorithme que pour les traits mais en plus de la direction on va s’intéresser à la variation de l’axe qui est censé être nul entre le début et la fin. On va chercher son plus grand éloignement de sa position de début et de fin (qui est censé être plus ou moins la même).

La première chose à faire est d’utiliser le premier algorithme des traits pour savoir la direction de la flèche ainsi que l’axe qui ne varie pas entre le P1 et Pn. Si par exemple on a le cas P1 = {0,0} et Pn = {0,10} et donc D = {0, 10} : On sait que le trait est dirigé vers le haut et que l’axe nul est le X.

On va donc prendre le point le plus éloigné du X de référence (0 dans notre cas).

P1 = {0,0} ; P2 = {-2,2} ; P3 = {-4,4} ; P4 = { -1, 8} , P5 = Pn = {0,10}

L’éloignement maximum sur l’axe des X est de -4. Maintenant il faut décider si cet éloignement est suffisant pour définir qu’il s’agît d’une flèche où alors s’il s’agît d’une erreur admissible au traçage d’un trait (car oui dans la pratique personne ne trace des traits parfaitement droit).

Une solution est d’arbitrairement fixer une limite et de définir par exemple qu’il faut au moins un éloignement supérieur à 6. Une solution un peu mieux est de définir cette limite en rapport à la longueur du trait. Par exemple en disant que si on ne s’éloigne pas plus de 20% de sa longueur sur l’axe nul, il s’agît de tremblement et le trait est droit. Alors que si on dépasse 20% de la longueur sur l’axe vertical, il s’agît alors d’une flèche.

Dans notre cas l’éloignement maximum est de -4, et la longueur sur l’axe du trait (axe Y) est de 10 (P5.Y – P1.Y = 10). 20% de 10 = 2. Si l’éloignement est supérieur à 2, il s’agît d’une flèche. Mais que faire dans notre cas où l’éloignement est de -4 ?

Il faut prendre la valeur absolue, c’est à dire sans le signe, car le signe donne la direction de la pointe de la flèche mais pour savoir si la variation est une erreur ou une flèche cela ne nous intéresse pas. Donc 4 étant supérieur à la limite 2, on considère que l’on a une flèche.

Et pour finir le signe -4 nous indique que la pointe de la flèche est négative, et dans notre cas notre flèche pointe dans le sens négatif de l’axe X, donc vers la gauche. Nous avons donc une flèche comme ceci « < »

Et le reste?

D’autre tracés sont assez facilement reconnaissance, on peut imaginer le rond. Où l’idée est que P1 = Pn (en admettant une erreur évidemment) et l’éloignement maximum en X et en Y doit être conséquent. Ou encore un triangle où on va utiliser les algorithmes du trait et de la flèche en s’assurant que P1 = Pn.

Mais d’autre solution existe dont celle que j’ai utilisé pour mon prototype de jeu « Rune ». Si je dois le résumer en quelques mots je dirais que je cherche à trouver la suite de direction « élémentaires » se trouvant dans le tracé. Par exemple mon système décomposera un tracé comme cela :

⬂ ⇩ ⇩

Pour se faire j’ai testé 3 algorithmes différents pour récolter finalement le tracé principal que voulait faire le joueur. Qui est probablement :

qui est donc un « U ».

Clique ici pour voir ce que cela donne en gif!

Cliquez sur l’image pour la voir en GIF!

J’ai donc choisi une approche utilisant les directions. Si cet article vous a plus je vais essayer d’en écrire un chaque semaine.

Dans un prochain article je vous expliquerai en détail l’outil « Gesture recognizer » qui a été mis en place ainsi que les différents algorithmes utilisés si cela vous intéresse!

A plus!

 

 

2 réponses sur “Rune : Gesture Recognizer part 1”

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *