Bonjour à tous, et tout d’abord veuillez m’excuser s’il existe déjà un sujet à ce sujet ou si je ne suis pas dans la bonne section du forum. J’ai bien essayé de chercher pas mal depuis hier, mais je n’ai rien trouvé qui répondre à mon problème. Et veuillez aussi m’excuser de la longueur du message, mais j’ai cru comprendre qu’il était (naturellement) préférable d’exposer sa question clairement.
Voilà : actuellement je suis dans la programmation d’un mini-jeu vidéo ou un personnage contrôlé par le joueur doit éviter d’être vu par d’autres personnages contrôlés par l’ordinateur. Dans cette optique, j’ai donc la situation suivante :
1°) Sans grande originalité, j’utilise des Listeners (implements KeyListener) pour contrôler le personnage du joueur au clavier (récupération de la direction souhaitée via la méthode keyPressed).
2°) Souhaitant que mon IA déplace automatiquement les autres personnages, je pensais avoir recourt à une boucle infinie qui déplace à chaque itération les personnages ; ceci permet aussi de contrôler leurs vitesses respectives : si le personnage principal se déplace à chaque itération et les autres une itération sur deux, le personnage principale va deux fois plus vite.
Mais voilà… Evidemment le problème est que dans la boucle infinie (ou plus précisément, boucle qui ne finit que quand le niveau est terminé) les Listeners sont « sourds » (exécution du code de la boucle jusqu’à la fin, et donc impossible de se déplacer).
J’ai bien pensé à la solution suivante : avoir deux Threads, l’un avec les Listener pour l’intéraction, et l’autre avec la boucle de jeu ; le premier enregistrant la dernière touche utilisée par le joueur et le second, dans la boucle infini, traitant celle-ci pour déplacer le personnage dans la direction voulue, dans le genre (juste pour expliquer l’idée vulgarisée) :
Code Pseudocode : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 while(niveau_non_termine) { if(derniere_touche_lue_par_le_thread_listener == bas) { personnage_principal.move(bas) ; } /*Ensuite, déplacement des personnages contrôlés par lIA*/ }
Mais voilà… Malgré plusieurs années de programmation Java derrière moi, je dois bien reconnaître que je ne suis pas le meilleur (très très très très très très très [...] loin de là!!!) même si je suis pas non-plus un débutant... et notamment je me suis toujours débrouillé pour ne pas avoir recourt au Threads, ou presque, et donc c’est sans doute avec le Java embarqué l’un des points en Java où je suis le plus ignorant et donc incompétent (en gros ça veut dire que j’y connais que dalle, nada, nothing et moins que rien
). Résultat quand j’en ai besoin (ou crois en avoir besoin) je suis dans le pétrin. J’ai bien consulté les tutoriels et la FAQ Java pour me sortir de là, et bien que tout ceci est très bien fait et informatif, je n’ai rien trouvé qui, à mon sens, m’aidait à résoudre mon problème actuel ; ou alors je n’ai pas compris que ça pouvait m’aider et je suis passé à côté de la solution…
Bref, pour résumer plus clairement mes questions, celles-ci sont :
- L’utilisation des Threads pour résoudre ce problème vous semble t’il approprié, voire l’unique solution ? Y-a-t’il d’autres solutions ?
- Quelle structure je devrais avoir dans mon programme pour organiser mes Threads ? Si Threads il y a, bien entendu...
- Comment procéder pour assurer correctement la communication entre les Threads (car mon interface graphique communique énormément avec ma modélisation du niveau et du jeu) ?
J’espère avoir été le plus clair possible, et je suis plus qu'ouvert à ceux qui m'expliquent que j'ai fait complètement n'importe quoi et que c'est parceque j'ai conçu les choses à l'envers que ça ne tourne pas (). Et surtout MERCI d’avance !!!
Structure du programme :
Comme y a des J tout pleins, je suis effectivement en Swing... Je ne vais pas mettre mes milliers de lignes illisibles dans le post, mais la structure de mon programme concernant chaque niveau ressemble à :
Classe principale :
Lors du lancement d’un niveau, lecture d’un fichier de map et initialisation du mode d’affichage « in-game » et modélisation du niveau d’après les données lues.
Actuellement, c'est ma classe Main extends JFrame qui appelle son propre constructeur. Dedans se trouve donc aussi ma fonction keyPressed(KeyEvent e) et les fonctions permettant de dire que le joueur à perdu/gagné et de basculer l'affichage vers le menu, la fin du jeu, les options, des cinématiques et autres...
C'est donc le moteur logique.
Classe JPanel :
Héritée de JPanel, s’entend bien. Sorte de « mini moteur graphique isométrique ». Quand le niveau est lancé, affichage par la méthode paint() de celui-ci en lisant les informations (position, type de l’image, etc…) modélisées par des classes Case, Mur, Sol, Personnage, Objet, etc… L’appel à la méthode paint est forcé dès que des données sont modifiées (c'est-à-dire au déplacement du personnage) et ce pour simuler des animations. Et donc on redessine sur le Panel/Canvas régulièrement la carte modélisée au fur et à mesure que des choses y sont modifiées.
C'est donc le moteur graphique (même si c'est un bien grand mot pour ça).
Classes de modélisation :
Juste des classes classiques : une Classe Niveau qui comprend des lignes et des colonnes composées de classes Case elles-mêmes contenant un Sol, entre 0 et 4 Murs, éventuellement un personnage et des Items (objet en français ; c'est-à-dire des tables, des bureaux, distributeurs d’eau, etc…). Elles sont mises à jour si des modifications ont lieu au cours du jeu, et sont lues par la classe JPanel.
C'est donc la modélisation des éléments du jeu/niveau.
Partager