Compteur :
Java 3D - Chapitre 11 : Programmation d'un petit jeu en 3D

Retour table des matières Java 3D

 

Dans cette dernière partie consacrée à Java 3D nous allons terminer en beauté avec l'écriture d'un petit jeu en 3D. Le principe consiste à envoyer des boules sur un masque de foire en mouvement afin de le toucher. A priori, le thème n'est guère passionnant mais nous allons pouvoir mettre en oeuvre un certains nombre de techniques de programmation Java 3D que nous avons étudiées dans les chapitres précédents.
On peut citer entre autres, la construction d'objets, le positionnement de la caméra, les éclairages, les animations, les comportements avec notamment un bel exemple sur les collisions et le Billboard, le Switch, le chargement d'objets au format Wavefront ...
Enfin, nous allons également nous intéresser à améliorer la jouabilité de l'application en détaillant l'algorithme de l'action de l'utilisateur dur le canon chargé d'envoyer les boules.
Nous de détaillerons bien sûr pas chaque partie individuellement puisque nous reprenons des notions déjà étudiées en détails dans les chapitres précédents, le but simple de ce dernier chapitre consiste à montrer un exemple d'utilisation de toutes ces notions ensemble dans un petit programme déjà conséquent. Nous allons procéder progressivement comme un jeu de construction dans lequel nous montons les briques les unes après les autres.

 

 

1. Exécution du jeu

 

Avant de procéder à l'élaboration de notre jeu, nous pensons qu'il est utile que l'utilisateur ait une vue d'ensemble sur le résultat à obtenir. Pour cela rien de mieux qu'une petite archives .jar exécutable du jeu.
Le canon se dirige grâce aux flèches droite et gauche du clavier, et le lancement des boules s'effectue lorsqu'on clique sur la barre d'espace.

Le jeu dans sa version finale

L'archive Jeu.zip contient le jar exécutable Jeu.jar permettant de lancer l'application dans sa version finale ainsi que les fichiers de ressources (objets Wavefront et librairie de matériaux) associés.
Sauvegarder l'archive Jeu.zip dans un répertoire du disque dur, extraire les fichiers et exécuter l'archive Jeu.jar.

 

2. Positionnement du point de vue (caméra)

 

Pour commencer, nous allons construire les premières briques du canon, à savoir un objet de type Box pour le corps et un objet de type Cylinder pour le canon proprement dit.
Le canon est positionné le long de l'axe Y vertical et la caméra (par défaut positionné le long de l'axe Z vers les Z négatifs) sera positionnée selon un axe incliné de 45 degrés par rapport au plan [OXY], axe qui se situe dans le demi plan supérieur (Z > 0)

Montage du canon et positionnement de la caméra

Le fichier Jeu.java présente le code source complet de cet exemple.
L'archive Jeu.jar est un jar exécutable permettant de lancer l'application

 

3. Montage du canon (suite)

 

Pour donner une apparence un peu plus réaliste à notre canon, nous allons lui attribuer un matériau ainsi que l'éclairage qui va avec. Pour que toutes les couleurs du matériau soient visibles, nous allons mettre une source lumineuse ambiante et une source lumineuse directive.

Le canon avec matériau et éclairage

Le fichier Jeu.java présente le code source complet de cet exemple.
L'archive Jeu.jar est un jar exécutable permettant de lancer l'application

 

4. Construction du masque

 

Dans ce paragraphe, nous allons nous consacrer à la construction du masque. Pour cela nous allons utiliser un objet de type Wavefront que nous avons construit avec le logiciel gratuit Blender. En fait, il faut construire deux masques : un masque intact de couleur bleu et un masque de couleur rouge lorsqu'il a été touché par un obus.
Pour créer ces deux masques nous allons utiliser un objet de type Switch qui contiendra les deux masques, la bascule d'un objet vers l'autre se fera lorsqu'un obus aura atteint le masque. Les deux objets qui sont au format .obj de Wavefront partagent une librairie qui contient deux matériaux : un pour le masque intact et un autre pour le masque touché.
Enfin, on utilise un comportement de type Billboard pour que les masques (intact et touché) fassent toujours face à la caméra.

Apparition du masque (ici seulement le masque intact est affiché)

Le fichier Jeu.java présente le code source complet de cet exemple.
L'archive Jeu.zip contient le jar exécutable Jeu.jar permettant de lancer l'application ainsi que les fichiers de ressources (objets Wavefront et librairie de matériaux) associés.
Sauvegarder l'archive Jeu.zip dans un répertoire du disque dur, extraire les fichiers et exécuter l'archive Jeu.jar.

 

5. Fabrication des obus

 

Nous allons maintenant construire les obus qui vont servir de munitions au canon. En fait, nous allons construire deux obus pour que la cadence de tir du canon soit plus rapide mais nous ferons en sorte (voir le paragraphe 8 consacré au lancement des obus) qu'un seul et unique obus soit vu simultanément dans le canvas 3D. Nous attribuons une couleur d'émission rouge, nous gardons les couleurs diffuses et spéculaires qui sont blanches par défaut. Ces obus seront bien eclairés par les lumières que nous avons mises en place dans le paragraphe 3.

Le fichier Jeu.java présente le code source complet de cet exemple.
L'archive Jeu.zip contient le jar exécutable Jeu.jar permettant de lancer l'application ainsi que les fichiers de ressources (objets Wavefront et librairie de matériaux) associés.
Sauvegarder l'archive Jeu.zip dans un répertoire du disque dur, extraire les fichiers et exécuter l'archive Jeu.jar.

 

6. Animation du masque

 

Pour animer le masque nous allons utiliser un interpolateur de type PositionInterpolator qui fera apparaître le masque de façon aléatoire soit sur la gauche, soit sur la droite du canvas 3D.
L'animation sera gérée dans un thread à part nommé AnimationThread. Ce thread va gérer la position de départ du masque (gauche ou droite) dans une boucle infinie. A chaque itération de cette boucle infinie, le masque aura un mouvement animé soit de droite à gauche, soit de gauche à droite. Il est indispensable de gérer cette animation dans un thread à part afin que l'application ne soit pas bloquée part cette boucle infinie.

Le fichier Jeu.java présente le code source complet de cet exemple.
L'archive Jeu.zip contient le jar exécutable Jeu.jar permettant de lancer l'application ainsi que les fichiers de ressources (objets Wavefront et librairie de matériaux) associés.
Sauvegarder l'archive Jeu.zip dans un répertoire du disque dur, extraire les fichiers et exécuter l'archive Jeu.jar

 

7. Mise en place des actions utilisateur sur le canon

 

Nous allons nous préoccuper ici d'implémenter les actions utilisateur sur le canon. En particulier, nous allons écrire le comportement associé aux flèches droite et gauche du clavier qui vont faire tourner le canon vers la droite ou vers la gauche.
Nous allons créer pour cela une nouvelle classe nommée CanonBehavior qui étend bien sûr la classe Behavior. La condition qui va déclencher le comportement est de type :
new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED
Le mouvement angulaire du canon sera limité dans l'intervalle [-45,45] degrés pour plus de réalisme.

Le mouvement du canon obéit à l'appui de l'utilisateur sur les flèches droite et gauche du clavier

L'archive src.zip présente le code source complet de cet exemple.
L'archive Jeu.zip contient le jar exécutable Jeu.jar permettant de lancer l'application ainsi que les fichiers de ressources (objets Wavefront et librairie de matériaux) associés.
Sauvegarder l'archive Jeu.zip dans un répertoire du disque dur, extraire les fichiers et exécuter l'archive Jeu.jar

On remarque une petite limitation dans cette animation du canon. En effet lorsqu'on appuie sur la flèche droite pour faire tourner le canon à droite par exemple et qu'on maintient la pression, le canon commence à tourner, puis s'arrête et enfin le mouvement de rotation devient continu. Ceci est dû à la gestion des évènements liés au clavier et qui peut se vérifier dans n'importe quelle application. En effet, dans un traitement de texte par exemple, lorsqu'on appuie sur la touche 'a' du clavier et qu'on la maintient enfoncée, il y a une latence entre l'affichage du premier 'a' et du second. Ensuite, les autres 'a' vont s'afficher les uns après les autres régulièrement.
Nous sommes confontés à ce même problème pour le mouvement du canon, nous allons le résoudre dans le paragraphe 9 consacré à l'optimisation des actions utilisateur sur le canon.

 

8. Lancement des obus

 

Nous allons nous intéresser ici au lancement des obus. Un obus sera lancé dans la direction de pointage du canon à chaque fois que l'utilisateur appuiera sur la barre d'espace. Cependant, le canon ne peut tirer que deux obus à la fois et on va faire en sorte que seulement un obus soit visible simultanément dans le canvas 3D. Pour cela on fait en sorte que l'obus animé ne soit plus visible dans le canvas 3D lorsque le timer alpha relatif à l'obus est supérieur à 0.5.

L'obus est lancé lorsqu'on appuie sur la barre d'espace

L'archive src.zip présente le code source complet de cet exemple.
L'archive Jeu.zip contient le jar exécutable Jeu.jar permettant de lancer l'application ainsi que les fichiers de ressources (objets Wavefront et librairie de matériaux) associés.
Sauvegarder l'archive Jeu.zip dans un répertoire du disque dur, extraire les fichiers et exécuter l'archive Jeu.jar

Nous remarquons également une autre petite limitation dans la gestion des évènements du clavier. En effet, lorsqu'on fait tourner le canon en maintenant une des deux touches flèches enfoncées et que l'on appuie sur la barre d'espace pour lancer un obus, la rotation du canon s'arrête. Ceci est normal, cela est dû à la gestion des évènements du clavier : pour poursuivre le mouvement de rotation du canon après avoir lancé un obus il faut réappuyer sur la flèche. Ce comportement n'est pas acceptable dans le cadre d'un jeu vidéo.
Nous allons proposer une solution à ce problème dans le paragrpahe 9 consacré à l'optimisation des actions utilisateur sur le canon.

 

9. Optimisation des actions utilisateur sur le canon

 

Pour éviter les petits désagréments liés à la gestion des évènements du clavier que nous avons rencontrés dans les paragraphes 7 et 8, nous allons changer d'algorithme. La jouabilité du jeu va s'en trouver grandement améliorée.
L'idée consiste ici à gérer les actions du clavier dans un thread à part que nous avons nommé KeyActionThread. Lorsqu'on gardait une touche du clavier appuyée, cela revenait à appuyer plusieurs fois consécutivement et très rapidement sur cette touche, le mouvement du canon obéissait alors à cette répétition naturelle de l'appui sur la touche.
Maintenant nous allons déclencher deux évènements uniques :
l'appui sur une touche (considéré comme un seul et unique évènement, la répétition de l'appui est ignorée) et la relâche d'une touche.
Cet appui et cette relâche des touches du clavier vont commander le thread indépendant KeyActionThread, ce qui va nous affranchir des problèmes que nous avons rencontrés dans les paragraphes 7 et 8.
Lorsqu'on appuie ou que l'on relâche une des trois touches (flèche gauche, droite et barre d'espace) la méthode processStimulus() de la classe CanonBehavior va initialiser des booléens correspondants :
keyPressedLeftArr : true si flèche gauche enfoncée, false si flèche gauche relachée
keyPressedRightArr : true si flèche droite enfoncée, false si fl_che droite relachée
keyPressedSpace : true si barre d'espace enfoncée, redevient false automatiquement dès qu'un obus a été lancé
Le thread KeyActionThread va donc diriger les actions sur le canon (mouvement plus tir) en fonction de l'état de ces trois booléens.
Enfin, nous avons rajouté une dernière petite optimisation qui consiste à placer la boule juste à la sortie du canon avant qu'elle ne soit lancée, afin que le joueur ait l'impression que la boule sorte vraiment du bout du canon plutôt que de son centre. Ce petit désagrément est particulièrmeent visible lorsqu'on tire en même temps que l'on tourne le canon.

Toutes les améliorations par rapport aux deux paragraphes précédents se situent dans la classe CanonBehabior qui intègre donc une nouvelle classe interne : KeyActionThread.

L'archive src.zip présente le code source complet de cet exemple.
L'archive Jeu.zip contient le jar exécutable Jeu.jar permettant de lancer l'application ainsi que les fichiers de ressources (objets Wavefront et librairie de matériaux) associés.
Sauvegarder l'archive Jeu.zip dans un répertoire du disque dur, extraire les fichiers et exécuter l'archive Jeu.jar

Vous constaterez par vous-même comment la jouabilité a été améliorée tellement tout paraît plus fluide et naturel !

 

10. Interaction du masque avec les obus

 

Enfin, il manque le plus beau pour terminer ce chapitre : changer le type de masque affiché lorsque celui-ci est touché par un obus. En effet, lorsque le masque intact (bleu) en mouvement est touché par une boule, il doit changer d'aspect et devenir rouge tout en se renversant.
Pour obtenir cet effet, la meilleure façon consiste à créer un comportement de type collision. Ceci est très simple, nous avons créé une nouvelle classe nommée DetecteurCollision dont la méthode processStimulus() va simplement changer l'objet masque dans le groupe de type Switch qui, on le rappelle, contient les deux masques : celui intact et celui touché.

Le masque change d'aspect dès qu'il a été touché par une boule

Le jeu complet peut être téléchargés à la fin du premier paragraphe de ce chapitre.
Le code source du jeu complet se trouve dans l'archive src.zip

 

Retour haut de page

Chapitre 10 : Utilisation de Java 3D au sein d'une application utilisant AWT et Swing <<