Le projet
Notre projet consistait en l'implémentation d'un jeu de bataille navale utilisant le matériel de réalité virtuelle mis à notre disposition.
Vous trouverez sur cette page:
- Le cahier des charges
- Nos choix d'implémentation
- Comment jouer
- Téléchargements
- Retours sur le projet
Le cahier des charges
L'idée:
L'idée de départ est de créer un jeu de bataille navale immersif. Les joueurs sont plongés dans un environnement virtuel. Ils peuvent interagir avec un plateau virtuel horizontal représentant leur mer et la position de leurs bateaux (sur une grille 10x10), et un plateau virtuel vertical représentant la mer de l'adversaire (une grille 10x10 également). Dans un premier temps, le joueur place ses bateaux sur sa grille horizontale avec les mains. Ensuite, il lancera ses bombes sur la grille de l'adversaire.
Les outils:
Nous utiliserons le visiocasque pour le rendu graphique, un fob pour tracker la position de la tête, et le gant pour déterminer la position des doigts (des articulations). Nous aurons également besoin de tracker la position de la main, mais puisqu'il est impossible d'utiliser un deuxième fob, nous avons pensé à un système de pictogramme placé sur la main, et filmé par une caméra fixe et/ou par la caméra du visiocasque.
Les interactions:
Les bateaux sont des objets virtuels initialement posés à coté de la grille du joueur. Le joueur peut manipuler ses bateaux en plaçant sa main dessus puis en serrant les doigts (on utilisera le gant). Une fois le bateau « en main », il peut le déplacer et le tourner. Lorsqu'il le lâche au dessus de la grille, le bateau tombe dessus et se place sur les cases les plus proches. Si le joueur lâche le bateau en diagonale sur la grille, le bateau se placera de lui même parfaitement vertical ou parfaitement horizontal sur la grille. Si le joueur lâche le bateau à coté de la grille, il reviendra dans sa position initiale à coté de la grille.
Une fois la position des bateaux validée, le joueur ne peut plus les manipuler. En revanche, il peut lancer des bombes sur la grille de l'adversaire. Soit en indiquant la case visée, soit en jetant la bombe dessus (elle aura une trajectoire parabolique). Le joueur voit la grille de l'adversaire en face de lui. En levant le bras et en pointant du doigt une case, celle-ci se place en surbrillance. Si le joueur étend complètement la main, une bombe est lancée sur cette case. Une autre option permet au joueur de « lancer » la bombe à la main. En reculant son bras et en serrant la main, puis en projetant son bras en avant et en détendant les doigts. La trajectoire de l'objet lancé sera calculée et se terminera sur une case de la grille de l'adversaire. Une bombe sera lancée sur cette case.
A tout moment du jeu , le joueur a accès à un « tableau de bord » représenté par des boutons placés autour de sa grille. Ces boutons représentent les options du jeu (« Nouvelle partie », « sauvegarder partie », « difficulté de l'IA », « taille de la grille », etc...). Le joueur peut appuyer sur ces boutons, et déclencher les options, en plaçant sa main dessus puis en la déplaçant en direction du bouton. Si la main « traverse » le bouton de haut en bas, on considère que le joueur « appuie » dessus.
MUST:
- Un moteur de jeu de bataille navale classique (5 bateaux par joueur, grilles 10x10 cases)
- Des graphismes minimums utilisant les lunettes: les grilles et les bateaux sont affichés à l'aide de primitives openGL.
- Tracker la position de la tête avec un fob et afficher l'environnement en conséquence.
- Tracker la position de la main avec un pictogramme et une caméra .
- Manipuler les bateaux avec le gant.
- Poser les bateaux sur la grille horizontale.
- Sélectionner une case sur la grille de l'adversaire et lancer une bombe dessus.
- Quelques « boutons » de base pour « nouvelle partie » et « quitter le jeu ».
- Un petit module pour interagir avec le jeu depuis un PC normal.
SHOULD:
- Faire une interface graphique sur PC pas trop moche pour pouvoir jouer à deux joueurs, un avec le casque et les gants, l'autre sur le PC.
- Implémenter une IA pour pouvoir jouer seul.
- Afficher la grille en fonction d'un pictogramme placé sur une table en face du joueur.
De façon à avoir un retour haptique quand on touche la grille. - Améliorer les graphismes des bateaux et des grilles.
- Faire un environnement graphiquement potable: un environnement de machinerie quelconque qui ferait croire au joueur qu'il se trouve dans une tour de contrôle ou dans un sous-marin.
- Ajouter quelques boutons / fonctionnalités au menu: « sauvegarder la partie », « charger la partie », « jouer contre l'IA », « partie à deux joueurs ».
- Ajouter un environnement sonore de base (bruit d'explosions, « plouf », etc...)
MAY:
- Effets graphiques de lancement et d'explosions des bombes et des bateaux
- Améliorer les graphismes de l'environnement et des bateaux.
- Module pour jouer en réseau (deux joueurs sur deux PC).
- Fonctionnalités avancées: modifier la taille des grilles, le nombre de bateaux, plusieurs niveaux de difficulté pour l'IA, etc…
- Utiliser des parallélépipèdes en carton pour représenter les bateaux, avec des pictogrammes dessus pour les reconnaître.
Ainsi le joueur aura un retour haptique quand il déplacera les bateaux. - Améliorer les effets sonores, ajouter de la musique ? Ajouter des boutons au tableau de bord pour changer le volume des effets en cours de partie.
Planning
Avant lundi 23/11:
- Implémenter un moteur de jeu de bataille navale classique + petit module graphique (ou en ligne de commande) pour le debug.
- Afficher correctement une grille et un bateau en OpenGL sur un écran classique.
- Préparer quelques textes et interfaces de debugage.
Lundi 23/11:
- Transférer l'affichage sur les lunettes.
- Apprendre à utiliser le gant. Détecter la position des doigts et définir les positions pour « prendre un objet » et « lâcher un objet ».
- Apprendre à utiliser le flock of bird pour tracker la position de la tête, et modifier l'affichage en conséquence.
- Utiliser des pictogrammes pour tracker la position de la main. L'afficher en conséquence
Mardi 24/11:
- Prendre et déplacer les bateaux avec le gant.
- Poser les bateaux sur la grille horizontale et associer le déplacement au moteur de jeu de bataille navale (enregistrer la position du bateau posé).
- Associer la sélection de case sur la grille adverse avec la fonction « envoyer une bombe » du moteur de jeu.
- Implémenter une IA basique qui place des bateaux et qui tire aléatoirement.
Mardi soir: Première version jouable
Mercredi 25/11:
- Implémenter une version du jeu utilisant un flock of bird pour la main.
- Placer des boutons pour les options « nouvelle partie », « sauvegarder », etc...
- Améliorer les graphismes de l'environnement pour rendre le jeu presque beau.
- Ajouter des effets lorsque l'on pose un bateau et lorsque l'on lance une bombe.
- Ajouter des effets sonores.
Ensuite:
- Ajouter un module au moteur de jeu permettant de jouer en réseau.
- Terminer les graphismes (environnement + bateaux + « effets spéciaux »)
- Test du jeu final et peaufinage.
- Optimisations ?
Télécharger
La version .doc du cahier des charges est disponible ici.
Nos choix d'implémentation
Architecture de notre programme
Nous avons choisi pour notre code une architecture plutôt modulaire. Nous disposons donc de modules pour:
- la tete, (tete.cpp)
- la main, (main.cpp)
- les bateaux, (bateau.cpp)
- la grille, (grille.cpp)
- le menu et les boutons, (menu.cpp et button.cpp)
- le son, (sound.cpp)
- l'affichage principal (main_display.cpp)
Chaque module gère les interactions avec l'objet et son affichage s'il le faut. Comme il s'agit de notre premier projet d'affichage d'objets en OpenGL, nous avons beaucoup hésité sur la façon de gérer les objets dans l'espace (notre code comprend encore quelques incohérences à ce niveau). Finalement, chaque objet affichable s'est vu attribuer une frame qglviewer qui indique sa position et son orientation.
Affichage
Pourquoi pas QGLVIEWER ?
Nous étions tenté, dans un premier temps, d'employer l'interface de très haut niveau qglviewer afin de développer.
Cependant, l'affichage sur chaque œil d'une image différente nous a beaucoup gêné. En effet, qglviewer fournit
une option pour gérer la stéréoscopie, mais uniquement avec le matériel qui le supporte. Notre HMD n'est pas un
appareil qui supporte la stéréoscopie puisque il propose deux écrans bien distincts. Il s'agit peut être d'une
interprétation personnelle, mais la stéréoscopie me semble être le fait d'envoyer des images sur une seule sortie
vidéo mais en précisant qu'on envoie les images des deux yeux simultanément. Quoiqu'il en soit, le HMD consiste en
deux écrans bien distincts, donc il ne s'agit pas de stéréoscopie au même sens que le voit qglviewer. Il m'a été dit
que qglviewer gérait aussi le cas de stéréoscopie avec deux écrans différents, mais je n'ai jamais trouvé de mention
à ce fait dans la documentation.
Nous avons donc finalement opté pour glut, surcouche de OpenGL beaucoup plus bas niveau que qglviewer mais qui a l'avantage de gérer les subwindows (sous fenêtre dans la fenêtre principale), ce qui nous convenaient tout à fait.
Retour d'informations
Un aspect important de notre application est que nous voulions que celle ci soit la plus interactive possible avec l'utilisateur. Pour ce faire, divers retours d'information se devaient d'être réalisés. Les couleurs ont ici été très importantes pour signifier par exemple par un surlignage que le bateau était plaçable ou non, que celui ci était préhensible ou non, que l'on pouvait tirer sur la case adversaire ou pas, que le bouton du menu était activé ou non. Toutes ces informations permettaient à l'utilisateur de savoir que son action avait été vraiment prise en compte et d'éxpérimenter une vraie interaction avec l'environnement.
Afin de pouvoir configurer le jeu et fournir davantage d'interaction, nous avons choisi d'inclure un menu dans l'environnement virtuel, directement à droite de la grille du joueur. Celui ci permettant quelques actions de base comme commencer une nouvelle partie, placer les bateaux aléatoirement, changer le niveau de l'IA, quitter. Les boutons peuvent être de deux types: boutons poussoirs qui restent activés après la relache ou standards activés juste au moment de l'appui. Ici encore l'activation d'un bouton est signifiée par un changement de couleur et son appui par une division de la taille du bouton simulant l'interaction avec de vrais boutons.
Intelligence Artificielle
Nous avons décidé de proposer au joueur un adversaire virtuel au lieu de proposer la possibilité de jouer à deux. D'abord parce qu'un adversaire virtuel est toujours disponible, ensuite parce qu'il était impossible de proposer aux deux joueurs de s'affronter en utilisant tous les deux le système de réalité virtuelle. Ne serait-ce que par manque de matériel.
L'IA implémentée dispose de 3 niveaux d'"intelligence":
- Au niveau "Moussaillon", elle joue de façon complètement aléatoire sur toute la grille.
- Au niveau "Matelot", elle joue aléatoirement sur toute la grille jusqu'à ce qu'elle touche un bateau. A partie de là, elle jouera sur les cases autour du bateau jusqu'à ce qu'il soit coulé.
- Au niveau "Capitaine", elle joue aléatoirement sur certaines diagonales de la grille, de façon à optimiser ses chances de toucher un bateau. Une fois qu'un bateau est touché, elle jouera autour jusqu'à ce qu'il soit coulé.
Au niveau de l'implémentation, l'IA gère des listes de cases de priorité variable.
Une case avoisinant un bateau tout juste atteint sera de priorité maximale: il faut tirer sur cette case au plus vite.
Une case sur une diagonale sera de priorité 1: il faut tirer dessus avant de chercher ailleurs.
Les autres cases (les coins par exemple) seront de priorité 0: si on a pas le choix, on tire dessus.
Ces listes de priorité sont mises à jour en permanence, mais elles ne sont utilisées que si le niveau
d'intelligence de l'IA est suffisament élevé. Cela permet de modifier ce niveau à tout moment de la partie.
Comment jouer
Dans tout jeu de bataille navale, une première phase de jeu consiste à placer ses bateaux sur une grille. Une fois que chaque joueur a posé ses bateaux, chacun doit tirer sur la grille de l'adversaire et essayer de couler sa flotte. Bien entendu, il est impossible de savoir où sont les bateaux de l'adversaire avant de les atteindre d'un tir.
Notre jeu ne déroge pas à ces règles. Il comporte deux grilles (une par joueur), 5 bateaux de tailles différentes, et un menu comportant plusieurs options.
Les vidéos suivantes montrent ce que voit le joueur à travers le HMD (les deux yeux étant séparés). Les intéractions sont ici faites à l'aide du clavier, et non pas du matériel de réalité virtuelle, c'est pourquoi les mouvements sont linéaires et saccadés.
L'environnement de jeu
L'environnement de jeu comprend une "table" virtuelle sur laquelle repose une grille de jeu (de taille 10x10 cases). A gauche de la grille se trouvent 5 bateaux: un torpilleur de 2 cases, un sous-marin de 3 cases, un croiseur de 3 cases, une frégate de 4 cases, et un porte-avion de 6 cases. A droite de la grille se trouve un menu composé de 6 boutons (voir description plus bas). En face de la table, placée verticalement, se trouve la grille de l'adversaire (de taille 10x10 cases également).
Le joueur peut tourner autour de cet environnement comme il le souhaite, mis à part qu'il ne peut pas regarder sous la table. En effet, l'émetteur du Flock of Birds est au niveau de la grille horizontale, et le système ne peut pas interprêter correctement ce qui se passe lorsque le bird passe en dessous de l'émetteur.
Placer ses bateaux
Le joueur peut placer ses bateaux à la main, il lui suffit de placer sa main sur le bateau qu'il souhaite prendre. Lorsque c'est le cas, le bateau est "surligné" en jaune, le joueur sert alors le poing (ici, il appuie sur la touche P du clavier), le bateau suivra ensuite les mouvements de la main. Le joueur n'a plus alors qu'à déplacer sa main au dessus de la grille et relacher le bateau (ou appuyer sur la touche L). Le bateau tombera ensuite au bon endroit sur la grille.
A droite de la grille se trouve également une touche "Placement aléatoire" qui permet de positionner sur la grille les bateaux restants de façon aléatoire. Cette option permet au joueur de débuter la partie plus rapidement.
L'IA choisit également la position de ses bateaux, mais ceci se fait instantanément. Donc une fois que les bateaux du joueur sont placés, le jeu peut commencer immédiatement.
Tirer sur l'adversaire
Le but de la phase suivante consiste à tirer sur la grille de l'adversaire (grille verticale) en pointant du doigt la case visée. Le joueur valide le tir en touchant son index avec son pouce s'il porte le gant, en appuyant sur la touche M du clavier sinon. Si la case visée était disponible, alors le tir devient effectif, et une théière partant de la main du joueur vient s'écraser sur la case.
Si le joueur a atteint un bateau, il peut alors rejouer. Il lui suffit de remettre sa main en
position de repos, de viser une nouvelle case, et de tirer à nouveau.
Une fois que le joueur a tiré dans l'eau, c'est au tour de l'adversaire de joueur. L'IA
choisit une case en fonction de son niveau d'intelligence, et tire dessus.
Une thière apparait au dessus de la table virtuelle et tombe sur la case visée. Comme le joueur,
l'IA rejoue tant qu'elle touche un bateau du joueur. Si elle rate son coup, c'est à nouveau
au joueur de tirer.
Le jeu se poursuit jusqu'à ce qu'un des deux adversaires n'ait plus de bateaux en jeu. Le joueur peut ensuite soit refaire une partie, soit quitter le jeu, en utilisant les boutons à droite de sa grille.
Les options
Plusieurs boutons sont disponibles dans le menu de droite:
- Le bouton "Nouvelle partie" permet de réinitialiser le jeu, et de revenir dans la première phase, où le joueur place ses bateaux
- Le bouton "Placement aléatoire" a été décrit plus haut
- Les 3 boutons "Moussaillon", "Matelot" et "Capitaine" correspondent aux 3 niveaux de l'IA disponibles.
- Le bouton "Quitter" ferme le programme
Téléchargements
Nous avons modifié l'API-ARV fournie par nos encadrants de façon à ce que l'on puisse utiliser deux FOBs. Voici le patch et la procédure d'installation indispensable pour utiliser notre programme avec le matériel d'ARV.
- 1. Télécharger le patch
- 2. Mettre le patch.patch dans votre copie locale de l'api (qui doit être la copie exacte de /usr/local/api_arv dans les salles de RV)
- 3. Entrer dans votre copie locale de l'api (cd .../api_arv)
- 4. Lancer la commande "patch -p 1 < patch.patch" (si tout se passe bien, la liste des fichiers patchés apparaît)
Ensuite...
Soit:- 5. Recompiler la libfob
- 5. Télécharger la librairie statique déjà compilée
- 6. La copier dans votre copie locale (.../api_arv/lib/fob/lib)
Une fois ces modifications effectués, vous pouvez télécharger et utiliser le binaire de notre programme, compilé pour i686.
Retours sur le projet
Dans l'ensemble ce fut pour nous un projet très instructif, qui nous a permis de toucher à beaucoup d'aspects différents de la programmation utilisant la réalité virtuelle. Nous devions résoudre des problèmes aussi bien de "bas niveau" concernant le matériel, que des problèmes de "haut niveau" concernant l'IHM par exemple, la façon dont le joueur intéragira avec l'environnement et les retours d'informations nécessaires.
Le résultat final est à la hauteur de nos espérances. Le jeu fonctionne correctement, les graphismes n'ont pas été développés autant qu'on l'aurait voulu mais ils sont déjà très respectables (ceci est un jugement totalement subjectif).
Si nous devions regretter quelque chose, c'est de ne pas avoir eu assez de temps pour découvrir le matériel
et l'API avant de constituer notre cahier des charges, et particulièrement le planning.
Nous n'avions pas encore entrevu toutes les possibilités offertes par le matériel avant de proposer
notre idée de jeu de bataille navale.
Ensuite, nous avons été vraiment très optimistes en espérant une version utilisable de notre jeu fin novembre.
Nous avions très largement sous estimé la difficulté de la prise en main de l'API-ARV, et du temps
de travail global nécessaire.
Nous avons finallement obtenu une version jouable en janvier, soit avec presque deux mois de retard.