IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

[Programmation évènementielle] Interaction clavier lors d'une boucle infinie


Sujet :

Java

  1. #1
    Nouveau candidat au Club
    Profil pro
    Étudiant
    Inscrit en
    Février 2009
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2009
    Messages : 2
    Par défaut [Programmation évènementielle] Interaction clavier lors d'une boucle infinie
    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 l’IA*/
    }

    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.

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    tu devrais, pour faire simple, avoir un Thread qui gère la boucle de jeu (gère toutes les règles de eu, fait avancer les choses).

    ensuite, tu dois effectivement utiliser (c'est le plus simple) de keylistener. quand t'as un évènement "keydown" tu enregistre la touche pressée quelque part. Dans le keyup, tu l'efface.

    Avec ça, ta boucle de jeu ressemblerai à ça:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    while(onJoue){
      faireJouerLesIa()
      if (toucheEnCoursDappui)
         faireBougerJoueur(touche);
      si (desChangementOntEuLieu)
        appelerRepaint();
      sleep(tempsRestantAvantBoucleSuivante);
    }
    Et tout devrais marcher.

  3. #3
    Nouveau candidat au Club
    Profil pro
    Étudiant
    Inscrit en
    Février 2009
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2009
    Messages : 2
    Par défaut
    Ok, merci beaucoup !

    J'ai fait un test, et je réussis à faire tourner mon Thread en parallèle de ma détection clavier... Ca devrait plouvoir finalement marcher !!!

    Reste plus qu'à insérer la boucle dans le jeu dans le Thread et à lui envoyer à la création les données dont il a besoin (l'instance de mon personnage ou de mes NPCs par example).

    Sinon, une question qui peut paraitre bête, mais vu qu'il s'agit de Thread... :

    D'après ce que j'ai compris, un Thread s'instancie, puis on le lance avec start, et il exécute sa méthode run() en parallèle du reste, jusqu'à ce qu'il finisse proprement (dans mon cas, j'enverrais sans doute une variable de fin de niveau dans ma classe extends Thread, et ce sera testé à chaque itération).

    Mais que ce passe-t'il après ? Est-il VRAIMENT mort après avoir fini l'exécution de run ? Le Thread est-il, comme toute bonne classe bien éduquée, devenu inactif pour servir de casse-croute au garbage collector ? Ou bien y a t'il quelque chose que l'on doit faire pour y mettre fin ?

    Je dis ça, parceque je vais instancier/lancer un Thread à chaque nveau de mon jeu... et je n'aimerais pas me retrouver avec des tonnes de Threads inactifs qui s'entassent pour faire de la sieste dans l'espace mémoire ....

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par Arnzousk Voir le message
    Le Thread est-il, comme toute bonne classe bien éduquée, devenu inactif pour servir de casse-croute au garbage collector ?
    Les objet Thread sont des objets comme les autres. Une fois qu'il n'y a plus de référence active à cet objet, le ramasse miette passe par là. La seule particularité, c'est que, tant qu'il tourne, la jvm garde une référence vers le Thread en question.

  5. #5
    Membre Expert Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 679
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 679
    Par défaut
    Il faut bien différencier le thread lui même et l'objet de type Thread qui fournit des information sur le thread et son point de départ.

    Une fois la méthode run terminée, le thread en lui même est terminé et les ressources qui lui étaient allouées sont rendues.

    L'objet thread qui le représente existe toujours, comme tout bon objet java, tant qu'il y a une référence dessus. Cependant, il n'occupera pas plus de mémoire ou de CPU que n'importe quel objet Java classique.

    Si tu veux que le GC puisse libérer ton objet de type thread, il suffit que tu mettes une autre valeur dans les variables qui le contiennent, ce que tu feras de toute facon en chargeant le niveau suivant.
    Sinon tu peux les remplir avec null pour perdre les références.

Discussions similaires

  1. [OL-2007] Erreur Array out of bounds lors d'une boucle For .. To ..
    Par IronBibs dans le forum VBA Outlook
    Réponses: 2
    Dernier message: 24/11/2009, 09h49
  2. Problème lors d'une boucle
    Par vdomnet dans le forum Langage
    Réponses: 11
    Dernier message: 04/04/2009, 19h15
  3. Programme qui ne repond plus durant une boucle
    Par Gorjeck dans le forum Windows Forms
    Réponses: 5
    Dernier message: 26/05/2008, 11h48
  4. insérer des données dans un tableau lors d'une boucle
    Par sissi25 dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 31/05/2007, 09h19
  5. Réponses: 12
    Dernier message: 21/02/2006, 11h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo