Threads et affichage fluide

cs_Keldar Messages postés 1 Date d'inscription dimanche 6 décembre 2009 Statut Membre Dernière intervention 6 décembre 2009 - 6 déc. 2009 à 20:15
kirua12 Messages postés 1155 Date d'inscription samedi 17 janvier 2004 Statut Membre Dernière intervention 29 avril 2011 - 7 déc. 2009 à 12:28
Bonjour,

Je fais un projet pour ma formation. C'est un jeu qui consiste à faire un maximum de points en alignant 3 boules ou plus d'une grille. Pas de soucis, mon jeu marche sans problèmes d'affichage visuel.
Cependant, lorsque j'ajoute un thread pour faire une pause (qui puisse être vue par l'œil) entre deux étapes, le temps d'affichage nécessaire juste après le thread est plus important et on voit donc s'afficher les éléments les uns après les autres. Même si c'est assez rapide, c'est pas très esthétique.

Donc j'ai essayé pas mal de choses mais rien n'a vraiment marché...

je vous donne les deux classes concernées :

Voici la classe ou se passe le jeu et ou il y a un problème d'affichage :

package jeu;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

public class AireDeJeu extends JPanel implements MouseListener{
private static final int NBCOLONNES=8, NBLIGNES=8;	//Classe de traitement du jeu et des boules
private int score;
int nbBoules, nbCombinaisons;	//Paramètres pour le calcul du score à chaque action.

private Boule boules[][];
private List combinaison;
private Boule boule1, boule2;		//Les deux boules échangées
private int ligneEcouteur, colonneEcouteur;			//La ligne et la colonne de l'écouteur ou l'on a cliqué

private AireStats aireStats;
boolean partieEnCours;			//Indique si on peut échanger des boules ou non .
private GridBagConstraints constraint;

/////////////////CONSTRUCTEURS///////////////////////////////////////////////////////////////////
public AireDeJeu(AireStats aireStats){
aire(aireStats);
}

public void aire(AireStats aireStats){
//initialisation des variables
partieEnCours=true;
this.aireStats=aireStats;
setPreferredSize(new Dimension(450, 450));
setLayout(new GridBagLayout());
constraint= new GridBagConstraints();
score=0;

//		Initialisation du tableau des boules.
boules= new Boule[NBLIGNES][NBCOLONNES];
for(int ligne=0; ligne<NBLIGNES; ligne++)
for(int colonne=0; colonne<NBCOLONNES; colonne++)
boules[ligne][colonne]=new Boule(ligne, colonne);

combinaison=new ArrayList();	//On initialise la liste des combinaisons

//On supprime les combinaisons déjà existantes
for(int l=NBLIGNES-1; l>=0; l--)
for(int c=NBCOLONNES-1; c>=0; c--)
combinaison(boules[l][c]);
supprimer();
score=0;	//On met le score à zéro pour le début de la partie.

setOpaque(false);
afficher();
}

///////////////////METHODES D AFFICHAGE///////////////////////////////////////////////////////////////
public void afficher(){
removeAll();	//On supprime tous les composants qui étaient présents

//Affichage des boules et mise en place de leurs écouteurs.
for(int ligne=0; ligne<NBLIGNES; ligne++){
constraint.gridy=ligne*2+1;
for(int colonne=0; colonne<NBCOLONNES; colonne++){
constraint.gridx=colonne*2+1;
add(boules[ligne][colonne], constraint);
}
}

//mise en place des écouteurs entre les boules.
EntreBoules entre;
for(int ligne=1; ligne<NBLIGNES*2; ligne++){
constraint.gridy=ligne;
if(ligne%2==1)
for(int colonne=2; colonne<NBCOLONNES*2; colonne+=2){
constraint.gridx=colonne;
entre=new EntreBoules(ligne, colonne);
entre.addMouseListener(this);
add(entre, constraint);
}
else for(int colonne=1; colonne<NBLIGNES*2; colonne+=2){
constraint.gridx=colonne;
entre=new EntreBoules(ligne, colonne);
entre.addMouseListener(this);
add(entre, constraint);
}
validate();	//On affiche la nouvelle disposition des boules
}
}

public void paintComponent(Graphics g){
//On entoure l'aire de jeu par un cadre et on met la transparence
super.paintComponent(g);
setOpaque(false);

g.drawLine(0, 0, this.getWidth(), 0);
g.drawLine(0, 0, 0, this.getHeight());
g.drawLine(0, this.getHeight()-1, this.getWidth()-1, this.getHeight()-1);
g.drawLine(this.getWidth()-1, 0, this.getWidth()-1, this.getHeight()-1);
}
/////////////////////////GESTION EVENEMENTS////////////////////////////////////////////////////////////////////////////////
public void mousePressed(MouseEvent e) {
if(e.getSource() instanceof EntreBoules && partieEnCours){	//Si le joueur a cliqué entre deux boules et que la partie n'est pas terminée
EntreBoules ecouteur=(EntreBoules) e.getSource();
ligneEcouteur=ecouteur.getLigne();
colonneEcouteur=ecouteur.getColonne();

nbBoules=0;			//On initialise les paramètres de calcul du score au début du tour
nbCombinaisons=0;
combinaison=new ArrayList();	//On réinitialise la liste des combinaisons pour cet échange

if(ligneEcouteur%2==0){	//On les intervertit
boule1=boules[ligneEcouteur/2-1][colonneEcouteur/2];
boule2=boules[ligneEcouteur/2][colonneEcouteur/2];
deplacer(boule1, ligneEcouteur/2, colonneEcouteur/2);
deplacer(boule2, ligneEcouteur/2-1, colonneEcouteur/2);
}
else{
boule1=boules[ligneEcouteur/2][colonneEcouteur/2-1];
boule2=boules[ligneEcouteur/2][colonneEcouteur/2];
deplacer(boule1, ligneEcouteur/2, colonneEcouteur/2);
deplacer(boule2, ligneEcouteur/2, colonneEcouteur/2-1);
}
afficher();
bloquerPartie();		//On empeche le joueur d'échanger d'autres boules pendant l'affichage des combiniasons 
new TempsPause(this); // On affiche un petit moment l'action avant de continuer
}
}

public void continuerTraitement() {
combinaison(boule1);	//On regarde si l'échange a crée des combinaisons
combinaison(boule2);

if(combinaison.size()>0){//S'il y a une combinaison, on supprime
supprimer();

}
else{		//Sinon, on ré-échange les boules pour les remettre a leur place d'origine.
if(ligneEcouteur%2==0){	//On les remet dans les positions initiales
deplacer(boule1, ligneEcouteur/2-1, colonneEcouteur/2);
deplacer(boule2, ligneEcouteur/2, colonneEcouteur/2);
}
else{
deplacer(boule1, ligneEcouteur/2, colonneEcouteur/2-1);
deplacer(boule2, ligneEcouteur/2, colonneEcouteur/2);
}
}

//A la fin du tour, on calcule le nombre de points obtenus et on l'ajoute au score.
score+=nbBoules*nbCombinaisons;
aireStats.afficher(score, nbBoules, nbCombinaisons);//On affiche les différents paramètres voulus

afficher();
reprendrePartie();
}

public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}

/////////////////////////////OPERATIONS SUR LES BOULES////////////////////////////////////////////////////////////////////////
public void deplacer(Boule boule, int ligne, int colonne){	//Déplace une boule à la ligne et à la colonne indiquée.
boules[ligne][colonne]=boule;	//On déplace la boule dans le tableau
boule.setLigne(ligne);		//Et on modifier ces références
boule.setColonne(colonne);
}

public void combinaison(Boule boule){	//Détecte les différentes combinaisons à partir d'une boule.
int ligne=boule.getLigne(), colonne=boule.getColonne();
int combinaisonAvant=combinaison.size(), combinaisonEntre;

// Combinaisons verticales
if(ligne-1>=0 && comparer(boule, boules[ligne-1][colonne])){	//Si on ne dépasse pas du champ de jeu, on teste l'alignement des couleurs
if(ligne-2>=0 && comparer(boule, boules[ligne-2][colonne])){//Si on en a trois d'alignés
ajouter(combinaison, boules[ligne-1][colonne]);
ajouter(combinaison, boules[ligne-2][colonne]);//On les ajoute comme combinaison 

for(int i=ligne-3; i>=0; i--)
if(comparer(boule, boules[i][colonne]))	//Et on regarde s'il n'y a pas de combinaison de plus de trois dans cette direction
ajouter(combinaison, boules[i][colonne]);
else break;
}
if(ligne+1<8 && comparer(boule, boules[ligne+1][colonne])){
ajouter(combinaison, boules[ligne-1][colonne]);
ajouter(combinaison, boules[ligne+1][colonne]);
}
}
if(ligne+1<8 && comparer(boule, boules[ligne+1][colonne])){
if(ligne+2<8 && comparer(boule, boules[ligne+2][colonne])){
ajouter(combinaison, boules[ligne+1][colonne]);
ajouter(combinaison, boules[ligne+2][colonne]);

for(int i=ligne+3; i<8; i++)
if(comparer(boule, boules[i][colonne]))	
ajouter(combinaison, boules[i][colonne]);
else break;
}
}
if(combinaison.size()>combinaisonAvant)
nbCombinaisons++;//On ajoute une combinaison pour le calcul du score.
combinaisonEntre=combinaison.size();

//Combnaisons horizontales
if(colonne-1>=0 && comparer(boule, boules[ligne][colonne-1])){	
if(colonne-2>=0 && comparer(boule, boules[ligne][colonne-2])){
ajouter(combinaison, boules[ligne][colonne-1]);
ajouter(combinaison, boules[ligne][colonne-2]);

for(int i=colonne-3; i>=0; i--)
if(comparer(boule, boules[ligne][i]))	
ajouter(combinaison, boules[ligne][i]);
else break;
}
if(colonne+1<8 && comparer(boule, boules[ligne][colonne+1])){
ajouter(combinaison, boules[ligne][colonne-1]);
ajouter(combinaison, boules[ligne][colonne+1]);
}
}
if(colonne+1<8 && comparer(boule, boules[ligne][colonne+1])){
if(colonne+2<8 && comparer(boule, boules[ligne][colonne+2])){
ajouter(combinaison, boules[ligne][colonne+1]);
ajouter(combinaison, boules[ligne][colonne+2]);

for(int i=colonne+3; i<8; i++)
if(comparer(boule, boules[ligne][i]))	
ajouter(combinaison, boules[ligne][i]);
else break;
}
}
if(combinaison.size()>combinaisonEntre)
nbCombinaisons++;//On ajoute une combinaison pour le calcul du score.

if(combinaison.size()>combinaisonAvant){
ajouter(combinaison, boule);	//Si il y a une (ou plusieurs) combinaisons, on ajoute la boule d'origine
}
}

public boolean comparer(Boule bouleOrigine, Boule boule){	//renvoie si la couleur est la même entre lesdeux boules, ou pas.
if(bouleOrigine.getCouleur().equals(boule.getCouleur()))
return true;
else return false;
}

public void ajouter(List liste, Boule boule){	//On ajoute la boule dans la liste demandée si elle n'y est pas déjà
boolean dansListe=false;
for(Boule bouleTmp:liste)
if(bouleTmp==boule)
dansListe=true;

if(dansListe==false)
liste.add(boule);
}

public void supprimer(){	//On supprime les combinaisons
int ligne;
int colonne;
List repercution=new ArrayList();

for(Boule boule : combinaison){
ligne=boule.getLigne();
colonne=boule.getColonne();

while(ligne>0){	//Tant qu'on peut, on fait descendre les boules.
deplacer(boules[ligne-1][colonne], ligne, colonne);
ajouter(repercution, boules[ligne][colonne]);	//En réorganisant les boules, on récupère celles qu'on déplace pour les tester.
ligne--;
}
boules[ligne][colonne]=new Boule(ligne, colonne);	//Puis on fait apparaitre une boule en haut.
ajouter(repercution, boules[ligne][colonne]);
}
nbBoules+=combinaison.size();//On ajoute le nombre de boules de cette étape pour le score.
combinaison=new ArrayList();	//On réinitialise les combinaison qui ont étés traitées.

for(Boule boule : repercution)	//On regarde si le déplacement des boule a provoqué de nouvelles combinaisons.
combinaison(boule);
if(combinaison.size()>0)	//Si c'est le cas, on réajuste les boules.
supprimer();
}


public void bloquerPartie() {
partieEnCours=false;
}

public void reprendrePartie() {
partieEnCours=true;
}

public int getScore() {
return score;
}

public int getNbBoules() {
return nbBoules;
}

public int getNbCombinaisons() {
return nbCombinaisons;
}
}


et le thread :

package jeu;

public class TempsPause implements Runnable{
private AireDeJeu aireDeJeu;

public TempsPause(AireDeJeu aireDeJeu){
this.aireDeJeu=aireDeJeu;
new Thread(this).start();
}

public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
aireDeJeu.continuerTraitement();
}

}


Merci d'avance !

1 réponse

kirua12 Messages postés 1155 Date d'inscription samedi 17 janvier 2004 Statut Membre Dernière intervention 29 avril 2011 7
7 déc. 2009 à 12:28
Salut,

je ne sais pas si c'est la cause mais ton application ne respecte pas l'EDT (le thread unique de swing). Tu demandes à modifier l'IHM sans être dans le thread et ça c'est pas bon (cause principale des ralentissement d'ihm).
A quel moment est exécuté ton thread ? comment est il appelé ?
Essaye un truc du style :
public void run() {
  try {
    Thread.sleep(500);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  SwingUtilities.invokeLater(new Runnable(){
    public void run(){
      aireDeJeu.continuerTraitement();
    }
  }
}
0
Rejoignez-nous