Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 28/12/2012, à 20:13

compte supprimé

Gérer des événements, gérer la concurrence. [Résolu]

Bonsoir tout le monde.

Alors voici mon problème, j'essaie de faire un petit programme test dans lequel je déplace un cercle sur l'écran à partir des flèches directionnelles.
Et quand je me mets à faire n'importe quoi, j'obtiens évidemment des problèmes de concurrence.. je les catch, bref, je les ignore.. (grave?)
Mais là o`u je ne contrôle plus rien, c'est quand j'obtiens cette exception:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1

J'utilise une arrayList dans laquelle je stocke les touches claviers qui nous intéressent(A, Flèche Gauche, droite, etc.)
Je suppose que c'est dangereux quand on a ce genre d'erreur? (un débordement de tampon réalisable? :s)

Si vous voulez le programme, je peux vous l'envoyer(y a pas bcq de lignes).


J'aimerais faire quelque chose de "propre".. vous pouvez m'aider? Merci.

Dernière modification par ChrisLeturc (Le 23/01/2013, à 15:38)

#2 Le 29/12/2012, à 00:55

ssdg

Re : Gérer des événements, gérer la concurrence. [Résolu]

Si tu utilise une ArrayList simple pour stocker des données auxquelles tu accède depuis plusieurs threads différents, c'est sur que ça va mal se passer. (l'arraylist n'est pas "thread safe", à savoir fiable dans le cadre d'accès concurrents).

La solution la plus rapide serait de remplacer tes arraylists par des Vector, évidement, il y a sans doute plus efficace dans ton contexte (je crois que c'est souvent la pire solution en termes de perfs, mais comme je n'ai pas le temps de me rafraîchir la mémoire,...) mais cela te permettra de vérifier tes hypothèses, et ensuite, tu pourra faire des recherches pour améliorer la réactivité de ton programme (il vaut mieux mettre en oeuvre ton idée et l'optimiser après que passer ton temps à optimiser et ne jamais réussir à faire ce que tu veux)


s'il n'y a pas de solution, c'est qu'il n'y a pas de problème... ou pas.

Hors ligne

#3 Le 01/01/2013, à 16:14

compte supprimé

Re : Gérer des événements, gérer la concurrence. [Résolu]

Merci pour cette réponse et désolé pour le retard.

Donc les Vector sont "thread safe" contrairement aux ArrayList.
Juste pour me repérer par rapport au C/C++, les vector, est-ce bien l'équivalent des malloc(simple allocation dynamique d'une zone mémoire, un tableau dynamique).
Mais donc quand je rajoute un élément à ce tableau dynamique, je réécris à chaque fois en mémoire toutes les cases du tableau, non? Donc une perte de temps contrairement aux ArrayList qui n'utilisent que des pointeurs sur les éléments suivants. Dis moi si je me trompe.

Le contexte est le suivant:
J'ai un thread qui gère les événements du clavier.
Et un autre qui contrôle le déroulement du jeu(une simple boucle qui va afficher les modifications, j'utilise 0 pattern, ce sont des tests d'intégration) en utilisant les messages qui ont été traités dans la partie ci-dessus.
Dans la liste, j'ajoute juste les touches appuyées. Lorsqu'elles sont relâchées, je les remove.


Un nouveau problème se pose pour la gestion des niveaux de mon jeu de plates-formes.
Je pensais là, justement utiliser un objet vector<Plateforme> pour toutes les plates-formes.
Peux-tu me dire ce que tu en penses, s'il te plait?

Dernière modification par ChrisLeturc (Le 01/01/2013, à 16:15)

#4 Le 02/01/2013, à 14:12

ssdg

Re : Gérer des événements, gérer la concurrence. [Résolu]

Nop
Vector = une pseudo(le concept est le même, mais  arraylist ou à peu près tout (voire tout) les appels de méthode sont "synchronized". C'est à dire qu'avant chaque accès au Vector, le thread doit attendre d'obtenir un "laissez passer" qu'un seul thread peut obtenir à la fois. (en fait, il pose un "verrou" sur l'instance de Vector qu'il veut utiliser)

Tu te trompe (mais pas de beaucoup) sur deux points:
Une ArrayList et un Vector fonctionnent tout les deux en allouant (malloc) un tableau d'une taille donnée et en en allouant un nouveau quand cette taille est atteinte. L'idée est que par défaut Java alloue une taille (disons) importante et lorsque cette taille est atteinte, il alloue encore un tableau plus grand, avec une autre marge d'erreur importante. Donc les pertes de temps lors de la copie ne sont forcément un problème.
Ce que tu décris est une LinkedList.

Dans ton cas, c'est plus la lecture et la suppression du premier élément (ou l'ajout au début) qui pose problème puisque ça consiste à décaler d'une case mémoire tout le tableau. (et donc plus ton tableau est remplis, plus tu perd de temps à chaque lecture).

Sinon, tu peux aussi utiliser une LinkedList, en utilisant le résultat de l'appel de cette méthode:
http://docs.oracle.com/javase/1.4.2/doc … il.List%29
List maListe=Collections.synchronizedList(new LinkedList());
N'hésite pas à ajouter les paramètres de type qui vont bien.

Pour ta dernière question, je ne vois pas trop ce que tu appelle une plateforme. (un "sol" sur lequel peut marcher ton héros?)
[*]En l'absence de plus d'informations et de temps pour y réfléchir trop (c'est ton jeu hein wink ? ), je peux te donner deux conseils généraux:
La gestion des accès concurrents sont coûteux en temps, si tu es certain que ta collection ne sera utilisée que par un unique thread à la fois, ne met pas de verrou dessus (Donc, pas de Vector, pas de Collections.Synchronized, etc...)[/*]
[*]Tes collections (pas forcément directement un type tout près de Java) sont un point important de ton programme, si tu la choisit/implémente bien, cela simplifiera ta vie par la suite et fera gagner un temps fou à ton programme.
Si tu pense que tu as besoin d'accèder à ta liste de plateformes par l'ordre dans lequel elles apparâitrons sur ton écran, tu peux simplement faire une List, si tu pense que devra fournir les coordonnées de ton écran (les 4 coins) et obtenir toutes les plateformes, il te faudra un système plus compliqué. (exemple: 4 Maps à deux niveau (une map de maps) que tu accèdera ainsi: mapDesPointsEnHautAGauche.get(x).get(y), (pour tout les X et Y de l'écran))
[/*]


s'il n'y a pas de solution, c'est qu'il n'y a pas de problème... ou pas.

Hors ligne

#5 Le 02/01/2013, à 18:59

compte supprimé

Re : Gérer des événements, gérer la concurrence. [Résolu]

J'ai pris en compte tout ce que vous m'avez dit. Merci.

Pour parler un peu du projet. Je développe un jeu de plates-formes en 2D, un peu comme Mario.
(je considère comme plate-forme,  un sol sur lequel le héros peut se déplacer)

Là, je suis en train de modéliser la gravité. J'ai développé plusieurs systèmes me permettant de la modéliser.

Ma méthode: j'applique le PFD(principe fondamental de la dynamique) pour établir les trajectoires des sauts en fonction de l'inclinaison de la vitesse initiale du héros.
J'obtiens les équations de la trajectoire et je les applique en incrémentant à chaque fois d'un delta t(pour chaque position suivante). Je vérifie à chaque fois si le héros est en contact avec un de ces obstacles. Si il est en contact avec un obstacle, je modifie les conditions initiales et je réadapte la trajectoire.

Pour développer le système de la caméra qui suit le héros.
En fonction de la vitesse du héros, j'adapte la position des obstacles affichés à l'écran.

Vous en pensez quoi?

PS: pour exécuter le saut du héros dans le panel des actions à effectuer: je lance

new DoJump();

et le saut est effectué dans le constructeur de cette sous-classe.

Dernière modification par ChrisLeturc (Le 03/01/2013, à 04:04)

#6 Le 03/01/2013, à 23:31

ssdg

Re : Gérer des événements, gérer la concurrence. [Résolu]

Pour le systeme de sauts, je ne sais pas trop quoi penser. (je n'ai jamais fait quoi que ce soit d'approchant dans le passé)
Pour le "DoJump" je trouve ça bizarre (et à vrai dire pas très catholique) d'avoir un nom de classe qui soit une action. (en général, les actions sont gérés par les méthodes et les objets ont des noms de choses "Heros", "Gestionnaire de Saut", "Niveau", "Plateforme". Par contre, tu peux avoir gestionnaire.makeJump(myHero);

Les actions dans les constructeurs donne généralement un code moins agréable à lire et en général, tu ne t'attends pas à ce qu'un constructeur aie un effet sur le reste des objets du programme. (autre détail, une méthode ne devrait faire que ce que son nom laisse penser qu'elle fait sinon, quand quelqu'un d'autre ou toi (après quelques temps) repasse dessus, tu découvre que "doJump" s'occupe aussi de précharger la prochaine plateforme ou gère les conditions de victoire (ou un truc du genre). Et là, tu perdra un temps fou.


s'il n'y a pas de solution, c'est qu'il n'y a pas de problème... ou pas.

Hors ligne

#7 Le 05/01/2013, à 15:33

compte supprimé

Re : Gérer des événements, gérer la concurrence. [Résolu]

merci.

Là ce sont que des tests.. j'implémente aucun design pattern. Je comptais pour la suite, utiliser un MVC pour la structure générale et après.. je sais pas trop dans les détails, c'est tout récent pour moi les patterns. Donc si vous pouviez me conseiller, je suis preneur.

Sinon mes sauts fonctionnent, j'ai corrigé quelques trucs vraiment non "catholiques" comme tu l'as dit. tongue (Par contre j'ai pas encore incorporé les chocs avec les obstacles. Mais j'ai déjà tout en tête)

J'ai commenté les parties importantes des scripts. En particulier la classe TestGravity

par contre, y a un truc que je saisis pas.. pourquoi au bout d'un certain temps mon programme lague à donf? Si vous pouviez me dire, s'il vous plait?

Les deux premières classes ne sont pas intéressantes.
L'objet plateforme.( Il s'agit des coordonnées d'un obstacle)

import java.lang.Math;

import java.util.*;


public class Plateforme{
   private int x;
   private int y;
   private int w;
   private int h;
   
   
   public Plateforme(int x, int y, int w, int h){
      this.x = x;
      this.y = y;
      this.w = w;
      this.h = h;
   }
   
   public int getX(){return x;}
   public int getY(){return y;}
   public int getW(){return w;}
   public int getH(){return h;}
   
}

Panneau, dans lequel on gère l'affichage du héros(la boule) et des obstacles.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GradientPaint;
import javax.swing.JPanel;

import java.lang.Math;

import java.util.*;
 /**Panneau dans lequel on affiche le héros et les obstacles*/
public class Panneau extends JPanel {
  private int posX = 300;
  private int posY = 300;
  
  private int vX = 0; //10px/s shift pour accélérer la bouboule! :D vXMax=
  private int vY = 0;
  
  private double theta = (Math.PI)/4; 
  
  private Vector<Plateforme> obs = new Vector<Plateforme>();

  
  public Panneau(){
   //initialisation des obstacles
    obs.add(new Plateforme(300, 350, 500, 100));
    
    obs.add(new Plateforme(30, 30, 220, 300));
    
    
    obs.add(new Plateforme(400, 400, 260, 350));
    
    obs.add(new Plateforme(700, 200, 200, 100));
    
    obs.add(new Plateforme(300, 100, 200, 100));
  }
  
  public void paintComponent(Graphics g){
    //On choisit une couleur de fond pour le rectangle
    Graphics2D g2d = (Graphics2D) g;
    GradientPaint gp1 = new GradientPaint(0, 0, Color.RED, this.getWidth(), this.getHeight(), Color.CYAN, true);
    g2d.setColor(Color.white);
    g2d.setPaint(gp1);
    //On le dessine de sorte qu'il occupe toute la surface
    g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
    //On redéfinit une couleur pour le rond
    g2d.setColor(Color.red);
  
    //On le dessine aux coordonnées souhaitées
    g2d.fillOval(posX, posY, 50, 50);  
    
   
    //Plateforme tmp = new Plateforme(300, 350, 500, 100);
    //g2d.fillRect(tmp.getX(), tmp.getY(), tmp.getW(), tmp.getH());
    
    /*
    g2d.fillRect(300, 350, 500, 100);
    
    g2d.fillRect(30, 30, 220, 300);
    
    
    g2d.fillRect(400, 400, 260, 350);
    
    g2d.fillRect(700, 200, 200, 100);
    
    g2d.fillRect(300, 100, 200, 100);*/
    
    //obs.add(new Plateforme(300, 350, 500, 100));
    //obs.add(new Plateforme(100, 30, 200, 100));
    
    obs.add(new Plateforme(300, 350, 500, 100));
    
    obs.add(new Plateforme(30, 30, 220, 300));
    
    
    obs.add(new Plateforme(400, 400, 260, 350));
    
    obs.add(new Plateforme(700, 200, 200, 100));
    
    obs.add(new Plateforme(300, 100, 200, 100));
    
    
    Iterator it = obs.iterator();
    Plateforme tmp;
    while(it.hasNext()){
      tmp = (Plateforme)it.next();
      g2d.fillRect(tmp.getX(), tmp.getY(), tmp.getW(), tmp.getH());
    }
    
  }

  public int getPosX() {
    return posX;
  }

  public void setPosX(int posX) {
    this.posX = posX;
  }

  public int getPosY() {
    return posY;
  }

  public void setPosY(int posY) {
    this.posY = posY;
  }
  
  
  public int getVX() {
    return vX;
  }

  public void setVX(int vX) {
    this.vX = vX;
  }
  
  public int getVY() {
    return vY;
  }

  public void setVY(int vY) {
    this.vY = vY;
  }
  
   public double getTheta() {
    return theta;
  }

  public void setTheta(double theta) {
    this.theta = theta;
  }
  
  public Vector<Plateforme> getObs(){return obs;}
}}


Pseudo controler: (Tout se passe ici, le main, la fonction saut. ) J'ai mis des commentaires.

import java.util.ArrayList;
import java.util.Iterator;

import java.util.*;
import java.lang.Math;

import java.awt.Frame;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.TextField;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;


import java.awt.Panel;

import java.awt.BorderLayout;



/**
   *Classe dans laquelle se trouve le main. 
   *
*/



public class TestGravity extends Frame{
         /**
            *Constante permettant de tester différentes valeurs pour contrôler l'amplitude du saut. L'accélération etc. 
            *
         */
        static final int dep = 1; //constante pour le déplacement.
        static final double inc = 0.1;
        static final int vMax = 50; //1
        static final int vXDefaut = 10; //10
        static final int vYDefaut = 20;
        
        
        static final double g = 9.81;
        
        /**@deprecated*/
        static final int n = 10; //nombre d'images durant un saut.
        
        
        /**@deprecated*/
        static final int hJump = 200;
        static final long serialVersionUID = 1l; // Mauvaise facon mais j'aime pas les Warnings
        private TextField tf;
        /**@deprecated*/
        private Thread t;
        private Thread tJump;
        /**@deprecated*/
        private int sleepTime; //Temps pour lequel on rafraîchit la page.
        
        
        /**Liste des touches appuyées*/
        protected Vector<Integer> listeTouches = new Vector<Integer>();
        /**Objet panneau contenant les coordonnées des obstacles et du héros.*/
        private Panneau pan = new Panneau();
        
        /**Faut-il continuer l'animation?*/
        private boolean animated = true;
       
       
       /**Initialisation de la fenêtre et des composants.*/
        public TestGravity(){
                this.setLayout(new BorderLayout()); // Layout
                
                this.setTitle("Titre de ma fenêtre Test.");
                
                this.setBackground(Color.gray);
                this.tf = new TextField(); // Un textfield
                this.tf.setEditable(false); // non editable
                this.tf.addKeyListener(new RecepteurClavier()); // auquel on rajoute un recepteur clavier
                this.add(this.tf, BorderLayout.NORTH); // Ajout de ce textfield a la fenetre
                
                
                //this.pan.addKeyListener(new RecepteurClavierPan());
                this.add(this.pan, BorderLayout.CENTER);
                
                //this.pack(); // adaptation de la taille
                
                this.addWindowListener(new WindowAdapter(){ // Permet de fermer la frame
                        public void windowClosing(WindowEvent e){System.exit(0);}
                });
                
                
                
                this.setVisible(true); // affichage
                
                this.setSize(900,600);
                
                PlayMoving pm = new PlayMoving();
                pm.run();
                 //t.start();
        }
        /**textfield dans lequel on affiche la touche en cours d'execution..*/
        public TextField getTf(){return this.tf;}
        
        /**getteur du panneau*/
        public Panneau getPan(){return this.pan;}
         /**main..*/
        public static void main(String[] args){ 
            TestGravity t = new TestGravity();   
        
             
            //t.setSize(300,300);
        }
       
       
       /**Recepteur du clavier.
         *
         *On ajoute les touches appuyées à la liste et on retire celles lâchées.
         *
       */
        public class RecepteurClavier implements KeyListener{
                /**
                 * Touche enfoncée
                 * @param event
                 */
                public void keyPressed(KeyEvent event){
                        int source = event.getKeyCode();
                        
                        if(listeTouches.indexOf(source)==-1)
                        {
                           if(source==KeyEvent.VK_RIGHT){
                                  listeTouches.add(source);
                           }
                           if(source==KeyEvent.VK_LEFT){
                                   listeTouches.add(source);
                           }
                           if(source==KeyEvent.VK_A){
                                   listeTouches.add(source);
                           }
                           if(source==KeyEvent.VK_ESCAPE){
                                   listeTouches.add(source);
                           }
                           if(source==KeyEvent.VK_SPACE){
                                   listeTouches.add(source);
                           }
                           if(source==KeyEvent.VK_SHIFT){
                                   listeTouches.add(source);
                           }
                        }
                      
                        
                 }
               
                /**
                 * Touche relachée. Quelques exceptions.. Par exemple quand on lâche la touche d'accélération.
                 * @param event
                 */
                 public void keyReleased(KeyEvent event){
                        int source = event.getKeyCode();
                        int i = -1;
                        
                        TestGravity testActu = TestGravity.this;
                        
                        if(source == KeyEvent.VK_SPACE){ //Déjà supprimé..
                        
                        }
                        else
                        {
                           if(source == KeyEvent.VK_SHIFT){
                              if(((listeTouches.indexOf(KeyEvent.VK_RIGHT)!=-1)||(listeTouches.indexOf(KeyEvent.VK_LEFT)!=-1))&&((!(listeTouches.indexOf(KeyEvent.VK_RIGHT)!=-1))&&(!(listeTouches.indexOf(KeyEvent.VK_LEFT)!=-1)))) //Si une touche directionnelle est appuyée et si les deux touches ne sont pas appuyées en même temps alors.. la vX = 10
                              {
                                  
                                   testActu.getPan().setVX(vXDefaut);
                              }
                              else
                              {
                                   
                                   testActu.getPan().setVX(0);
                              }
                              
                           }
                           //Si c'est une touche directionnelle qui vient d'être relâchée.
                           //if((source == KeyEvent.VK_RIGHT)|(source == KeyEvent.VK_LEFT)){testActu.getPan().setVX(0);}
                           if((i = listeTouches.indexOf(source))!=-1){
                              listeTouches.remove(i);
                           }
                        }
                 }
                
                 /**
                  * Cractere tappé
                  * @param event
                  */
                 public void keyTyped(KeyEvent event){
                 }
               
        }
        
        
        /**
          *Classe dans laquelle il y a la boucle du programme.. On execute la/les touches appuyées, on effectue les modifications d'affichage.
          *
        */
        
        public  class PlayMoving implements Runnable{
          public PlayMoving(){}
          public void run() {
             TestGravity testActu = TestGravity.this;
             int index = 0;
                while(animated)
                {
                  try{
                       /** Saut.. Est-il dirigé vers la droite/la gauche ou ni l'un ni l'autre.*/
                    if((index=listeTouches.indexOf(KeyEvent.VK_SPACE))!=-1){
                             testActu.getTf().setText("SPACE JUMPING!");
                             
                             listeTouches.remove(index);
                             if((listeTouches.indexOf(KeyEvent.VK_RIGHT)!=-1)&&(listeTouches.indexOf(KeyEvent.VK_LEFT)!=-1))
                                 DoJump(false, false);
                             else if(listeTouches.indexOf(KeyEvent.VK_RIGHT)!=-1)
                                 DoJump(false, true);
                             else if( listeTouches.indexOf(KeyEvent.VK_LEFT)!=-1)
                                 DoJump(true, false);
                             else
                                 DoJump(false, false);
                                 
                             
                     }
                     /**Déplacement vers la droite ou vers la gauche..*/
                     if((listeTouches.indexOf(KeyEvent.VK_RIGHT)!=-1)){
                             if((testActu.getPan().getVX()<vXDefaut))
                                 testActu.getPan().setVX(vXDefaut);
                             
                             if(listeTouches.indexOf(KeyEvent.VK_SHIFT)!=-1){
                                      if(testActu.getPan().getVX()<vMax)
                                          testActu.getPan().setVX(testActu.getPan().getVX()+dep);       
                              }
                             testActu.getTf().setText("Droite");
                             testActu.getPan().setPosX(testActu.getPan().getPosX()+testActu.getPan().getVX());
                     }
                     if(listeTouches.indexOf(KeyEvent.VK_LEFT)!=-1){
                             if(-vXDefaut<testActu.getPan().getVX())
                                 testActu.getPan().setVX(-vXDefaut);
                             testActu.getTf().setText("Gauche");
                             testActu.getPan().setPosX(testActu.getPan().getPosX()+testActu.getPan().getVX());
                             if(listeTouches.indexOf(KeyEvent.VK_SHIFT)!=-1){
                                 if(testActu.getPan().getVX()<vMax)
                                     testActu.getPan().setVX(testActu.getPan().getVX()-dep);       
                              }
                     }
                     //Ne sert absolument à rien..
                     if(listeTouches.indexOf(KeyEvent.VK_A)!=-1){
                             testActu.getTf().setText("A");
                     }
                     //Pour arrêter le flux d'execution du programme. (deprecated) 
                     if(listeTouches.indexOf(KeyEvent.VK_ESCAPE)!=-1){
                             testActu.getTf().setText("ESCAPE");
                             animated=false;
                     }
                     
                    
                     //Affichage des touches appuyées.
                     Iterator<Integer> itr = listeTouches.iterator();
                     while (itr.hasNext()) {
                        Integer element = itr.next();
                        System.out.print(element.intValue() + " ");
                      }
                      System.out.println();
                      
                     
                     testActu.getPan().repaint(); 
                     
                        
                     //On fait dormir le thread
                     try {
                       Thread.sleep(10);
                     } catch (InterruptedException e) {
                       e.printStackTrace();
                     }
                    
                  } catch(ConcurrentModificationException e){System.err.println("~Concurrence!~");}
                }
      
           }
        } 
      
      /**Partie du code gérant le saut.*/
          private boolean isJumping = false;
          private boolean isUp = true;
          private int initPosX; 
          private int initPosY; 
          
          private int initVX; 
          private int initVY; 
          private double initTheta; 
          
          private int numEtape; //numéro de la position du saut.
          private double nE; //numéro de la position du saut.
          private double deltaT;
          
          //Paramètres permettant d'avoir des informations sur le saut. (cf. mes démonstrations pour plus de renseignements)
          private double tJ;
          private double hMax;
          
          
          //Fonction du saut.. (les arguments sont la direction du saut.)
          public void DoJump(boolean left, boolean right) {
             TestGravity testActu = TestGravity.this;
          
               
             //Valeurs initiales du saut. position et vitesse initiale. (projection sur abscisses et ordonnées)
               
             initPosX = testActu.getPan().getPosX();
             System.out.println("initPosX="+initPosX);
             initPosY = testActu.getPan().getPosY();
             System.out.println("initPosY="+initPosY);
             
             
             //Vitesse initiale du héros.
             initVX = testActu.getPan().getVX();
             
              testActu.getPan().setVY(10);
             initVY = testActu.getPan().getVY();
             System.out.println("initVX="+initVX);
             initTheta = testActu.getPan().getTheta();
             System.out.println("initTheta="+initTheta);
             
             //On calcule le temps théorique que mettra le saut par ma formule. (deprecated.. ne sert à rien dans cette version du test)
             if((left&&right)||((!(left))&&(!(right))))
             {
                //On calcule le temps théorique que mettra le saut par ma formule:
                tJ = (double) ((2 *vXDefaut)/g);
                
                deltaT = (double) (tJ / n);
                
                //hMax = -(1/g) * Math.pow((initVX*Math.tan(initTheta)),2) + initPosY;
                hMax = (1/g) * Math.pow(vXDefaut,2);
             }
             else
             {
                tJ = (double) ((2 * initVX * Math.tan(initTheta))/g);
                
                deltaT = (double) (tJ / n);
                
                //hMax = -(1/g) * Math.pow((initVX*Math.tan(initTheta)),2) + initPosY;
                hMax = (1/g) * Math.pow((initVX*Math.tan(initTheta)),2);
             }
             
             
             //Temps d'attente pour contrôler la vitesse. Ce temps est inversement proportionnel à la vitesse du héros. Ne sert pas dans cette version de la gravité.
             sleepTime=10;
             
             System.out.println("n="+n);
             
             System.out.println("tJ="+tJ);
             System.out.println("deltaT="+deltaT);
             
             System.out.println("hMax="+hMax);
             //Le saut n'a pas encore commencé!
             numEtape = 0; 
             System.out.println("vérife:"+(1/2*g*Math.pow((tJ),2)-initVX*Math.sin(initTheta)*(tJ)+initPosY));
             System.out.println("~~~~");
             
             double valY;
             double valX;
             
             isJumping=true;
             
             nE=0;
             
             //Tant que le saut doit être executé on continue le calcul de la trajectoire que doit prendre le héros.
             while(isJumping){
               if((left&&right)||((!(left))&&(!(right))))
               {
                  
                  
                  numEtape++;
                  nE=nE+inc;
                  System.out.println("numEtape="+numEtape);
                  
                  
                  //testActu.getPan().setTheta(Math.PI/2);
                  
                  
                  valY = (g*Math.pow(nE,2)-vXDefaut*nE*10+initPosY);//1/2*
                  System.out.println("valY="+valY+";(int)"+(int)valY);
                  
                  System.out.println("~~~~");
                  
                  
                  testActu.getPan().setPosY((int)valY);
                 
                  
                  
                  if(valY>=initPosY)
                     isJumping=false;
                     
                  //Permet de contrôler la vitesse du héros sans qu'il y ait de discontinuité.
                    // isJumping=false;
                   /* if((testActu.getPan().getVX())!=0)
                        sleepTime = (int)(1000/testActu.getPan().getVY());
                     else
                        sleepTime=1;*/
                        
                        
                   System.out.println("sleepTime="+sleepTime);
                   
                   try {
                        //Thread.sleep(sleepTime);
                        Thread.sleep(1);
                     } catch (InterruptedException e) {
                       e.printStackTrace();
                     }
               }
               else if(right)
               {//Saut vers la droite
                  
                  //System.out.println("Saut en train d'être executé!");
                  //On passe à l'image suivante. (Pour ne pas avoir le problème de la position initiale aussi considérée comme une fin de boucle!)
                  numEtape++;
                  System.out.println("numEtape="+numEtape);
                  nE=nE+inc;
                  
                  //On ajuste la position de l'image.
                  valX = (initVX*(nE)*6+initPosX);
                  System.out.println("valX="+valX+";(int)"+(int)valX);
                  
                  
                  //valY = (1/2g*Math.pow((numEtape*deltaT),2)-initVX*Math.sin(initTheta)*(numEtape*deltaT)+initPosY);
                  
                  valY = (g*Math.pow((nE),2)-initVY*(nE)*10+initPosY);
                  System.out.println("valY="+valY+";(int)"+(int)valY);
                  
                  System.out.println("~~~~");
                  
                  
                  testActu.getPan().setPosY((int)valY);
                  testActu.getPan().setPosX((int)valX);
                  
                  
                  if(testActu.getPan().getPosY()>=initPosY){
                     isJumping=false;
                     testActu.getPan().setPosY(initPosY);
                  }
                     
                  //if(testActu.getPan().getPosY()<=hMax)
                    // isJumping=false;
                    if((testActu.getPan().getVX())!=0)
                        sleepTime = (int)(1000/testActu.getPan().getVX());
                     else
                        sleepTime=1;
                        
                        
                   System.out.println("sleepTime="+sleepTime);
                   
                   try {
                        //Thread.sleep(sleepTime);
                        Thread.sleep(1);
                     } catch (InterruptedException e) {
                       e.printStackTrace();
                     }
                  
               }
               else if(left)
               {
                  //Saut vers la gauche
                  
                  //System.out.println("Saut en train d'être executé!");
                  //On passe à l'image suivante. (Pour ne pas avoir le problème de la position initiale aussi considérée comme une fin de boucle!)
                  numEtape++;
                  System.out.println("numEtape="+numEtape);
                  nE=nE+inc;
                  
                  //On ajuste la position de l'image.
                  valX = (initVX*(nE)*6+initPosX);
                  System.out.println("valX="+valX+";(int)"+(int)valX);
                  
                  
                  //valY = (1/2g*Math.pow((numEtape*deltaT),2)-initVX*Math.sin(initTheta)*(numEtape*deltaT)+initPosY);
                  
                  valY = (g*Math.pow((nE),2)-initVY*(nE)*10+initPosY);
                  System.out.println("valY="+valY+";(int)"+(int)valY);
                  
                  System.out.println("~~~~");
                  
                  
                  testActu.getPan().setPosY((int)valY);
                  testActu.getPan().setPosX((int)valX);
                  
                  
                  if(testActu.getPan().getPosY()>=initPosY){
                     isJumping=false;
                     testActu.getPan().setPosY(initPosY);
                  }
                     
                  //if(testActu.getPan().getPosY()<=hMax)
                    // isJumping=false;
                    if((testActu.getPan().getVX())!=0)
                        sleepTime = (int)(1000/testActu.getPan().getVX());
                     else
                        sleepTime=1;
                        
                        
                   System.out.println("sleepTime="+sleepTime);
                   
                   try {
                        //Thread.sleep(sleepTime);
                        Thread.sleep(1);
                     } catch (InterruptedException e) {
                       e.printStackTrace();
                     }
                  
               }
               testActu.getPan().repaint(); 
               
               try {
                  Thread.sleep(1);
               } catch (InterruptedException e) {
                 e.printStackTrace();
               }
               //System.out.println("isJumping: "+isJumping);
               
             }
         
             
             
          
          
          
      } 
      
      
      public boolean getIsJumping(){return isJumping;}
      
               
}   
       

#8 Le 06/01/2013, à 13:57

ssdg

Re : Gérer des événements, gérer la concurrence. [Résolu]

Là, tu me perd un peu (je n'ai pas fait d'interface graphique (non web) depuis un moment et j'avoue avoir beaucoup perdu. (par exemple sur repaint, je ne me souviens plus des pours et des contres de plein de choses.

Par contre, en survolant rapidement, j'ai l'impression que ta liste de touches enfoncées grandit, grandit, grandit...
J'aurais plutot fait une sous-boucle qui prends et supprime de la liste l'élement le plus ancien et le traite. (mais après, j'ai vraiment beaucoup survollé) Comme ça, tu évite les parcours multiples des listes par boucles (index-of) qui sont plus couteux que de faire un saut vers le bon if (voire un switch en fonction de comment sont représentées les touches appuyées par java)


s'il n'y a pas de solution, c'est qu'il n'y a pas de problème... ou pas.

Hors ligne

#9 Le 07/01/2013, à 15:01

compte supprimé

Re : Gérer des événements, gérer la concurrence. [Résolu]

Tu peux compiler sans problème avec. ^^

javac *.java

et executer

java TestGravity

(je n'ai pas encore géré la collision dans mon moteur graphique)


Sinon dans le débogage je me charge d'afficher tout le temps le contenu de la liste.
Et elle se vide bien.

Du coup, tu penses peut être que le problème viendrait du .repaint()?
C'est déjà une piste dans laquelle je peux me lancer.

Merci

#10 Le 08/01/2013, à 15:50

ssdg

Re : Gérer des événements, gérer la concurrence. [Résolu]

Tout ce que je peux dire sur le repaint, c'est que ce n'est pas à appeler à la légère. mais pour le reste, il faudrait que je creuse dans de la doc.

PS: Dans l'idée, j'aimerai bien rester un peu extérieur à ton projet, j'ai déjà un paquet de projets à moi qui prennent la poussière. wink


s'il n'y a pas de solution, c'est qu'il n'y a pas de problème... ou pas.

Hors ligne

#11 Le 19/01/2013, à 10:51

compte supprimé

Re : Gérer des événements, gérer la concurrence. [Résolu]

Merci je comprends. smile

J'ai refait d'une manière plus propre ces tests.
En décomposant le Model, la Vue et le Contrôleur par trois gros threads qui décomposent les différentes actions en de nouveaux threads.
Avec le multithreading plus aucun problème de lague. tongue

Sinon d'autres problèmes surviennent alors.. lorsqu'on saute d'une plate-forme à l'autre sans trop savoir pourquoi parfois.. le personnage se téléporte à des années lumières de la map.
Humhum!

Merci en tout cas.

Dernière modification par ChrisLeturc (Le 19/01/2013, à 10:51)

#12 Le 20/01/2013, à 23:42

ssdg

Re : Gérer des événements, gérer la concurrence. [Résolu]

ça peut être du à trop d’événements clavier d'un coup (tu peux en avoir un paquet de stockés et lorsqu'ils sont traités tous en même temps, ton personnage va très très vite. (tu peux faire en sorte de ne vérifier l'état du clavier que tout les x millisecondes)
Une variable dont la taille aurait été dépassée, par exemple, un byte peut stocker un entier, mais il ne va, si je ne m'abuse que jusqu'a 128, après, si tu ajoute 1, il passe à -127. (ou alors je confond avec le C), C'est valable pour à peut près tout les types numériques )

ça peut être autre chose big_smile (mais je ne sais pas quoi)


s'il n'y a pas de solution, c'est qu'il n'y a pas de problème... ou pas.

Hors ligne

#13 Le 21/01/2013, à 11:40

compte supprimé

Re : Gérer des événements, gérer la concurrence. [Résolu]

Intéressant! smile
Mais comment fais-tu pour mettre un petit délai d'attente entre les événements reçus?

Dans le thread qui récupère les événements(Controleur.java) je le fais dormir avec un

try {
		       Thread.sleep(10);
		     } catch (InterruptedException e) {
		       e.printStackTrace();
		     }

Mais c'est pas suffisant.

Ce que j'ai du mal à comprendre aussi c'est pourquoi à partir d'un certain nombre de sauts, je ne peux plus exécuter aucun saut.
(pour chaque saut, je crée un nouveau Thread effectuant les instructions pour faire sauter le joueur. Bien en entendu, ce nouveau Thread vérifie que le joueur n'est pas déjà en train d'effectuer un saut ou en train de tomber. )


EDIT: Bon, mon code semble très "artisanal" mais j'ai enfin un gameplay jouable et un minimum propre. J'ai réglé les problèmes de concurrence.. Maintenant faudra que j'implémente mon code avec des patterns.

Dernière modification par ChrisLeturc (Le 23/01/2013, à 15:37)

#14 Le 27/01/2013, à 12:09

ssdg

Re : Gérer des événements, gérer la concurrence. [Résolu]

Ne connaissant pas trop ce qui se fait de ce coté là. (en général, je fais du web, et du web "entreprise" avec des formulaires, pas des lectures au clavier directement) Ce que je vais dire tiens plus du point de vue extérieur que tu conseil de sage:
Si tu dispose d'un moyen de demander l'état actuel des touches, tu peux interroger ce moyen à intervalles constantes. (un while(true){getCommandes();sleep(sometime);}
Sinon, tu peux placer un boolean (avec les précautions d'accès concurrent qui vont bien) à vrai toutes les "x" secondes et à false une fois une commande lue. Tant que ce boolean est false, tu ignore les appels du clavier. quand il est vrai, tu les traite.


s'il n'y a pas de solution, c'est qu'il n'y a pas de problème... ou pas.

Hors ligne