CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[Java] Deplacer une image "proprement"

Trodroll
Trodroll
Niveau 7
02 novembre 2011 à 18:06:06

Bonjour :oui:

Alors, voilà le problème en gros : Je me suis créé une classe Sprite, qui manipule une classe Graphics2D et un objet de classe BufferedImage, qui se charge depuis un fichier. L'intérêt est de me faciliter la manipulation d'une image puis de l'intégrer dans une autre classe qui permettra de jouer des animations.

Seulement, voilà le problème, à chaque fois que je fais subir un déplacement ou une transformation à mon sprite, je suis obligé de le redessiner, j'utilise donc successivement les méthodes Graphics2D.clearRect(), qui efface l'image à sa position précédente, et Graphics2D.drawImage() qui la redessine à sa nouvelle position. Sans ça, mon image se fait redessiner par dessus l'ancienne image.

Mais voilà, faire ça, c'est lent, et du coup, à chaque transformation, deplacement etc, l'effaçage est visible à l'oeil nu, et c'est très moche, l'image clignote :hap: .

Je précise que mon Graphics2D utilise le contexte graphique d'un JPanel.

Donc voilà, j'aimerais savoir comment m'affranchir de ce clignotement très moche :svp:

Voilà mon code (désolé pour l'indentation) :

Ici, la classe Sprite :

package graphismes;

import javax.imageio.*;
import java.awt.image.*;
import java.awt.*;
import java.io.*;
import javax.swing.*;

/**
*
* @author Onche
*/
public class Sprite {

private BufferedImage imgMemoire;
private Graphics2D g;
private int posX, posY, posXPrec, posYPrec, gX, gY;
private double rotation;

public Sprite(String lien, JPanel supportDessin){
super();

try{
imgMemoire = ImageIO.read(new File(lien));
}catch(IOException e) {
System.out.println("Impossible de charger " + lien + " " + e.getMessage() );
}
finally{
posX = 0;
posY = 0;
posXPrec = 0;
posYPrec = 0;
gX = imgMemoire.getWidth()/2;
gY = imgMemoire.getHeight()/2;
rotation = 0;
g = (Graphics2D) supportDessin.getGraphics();
}
}

/**
* Modifie la position acutelle du sprite, et met à jour sa position
* précédente. Ne redessine pas le sprite, pour cela, utiliser deplacer().
*
* @param x : nouvelle position x sur le JFrame.
* @param y : nouvelle position y sur le JFrame.
*/
public void setPosition(int x, int y){
posXPrec = posX;
posYPrec = posY;
posX = x;
posY = y;
gX = posX + imgMemoire.getWidth()/2;
gY = posY + imgMemoire.getHeight()/2;
}

/**
* Dessine le sprite à sa position actuelle.
*/
public void dessiner(){
g.drawImage(imgMemoire, posX, posY, null);
}

/**
* Efface le sprite à sa position actuelle.
*/
public void effacer(){
g.clearRect(posX, posY, imgMemoire.getWidth()+1, imgMemoire.getHeight()+1);
}
/**
* Efface le sprite à sa position précédente.
*/
public void effacerPrecedent(){
g.clearRect(posXPrec, posYPrec, imgMemoire.getWidth()+1, imgMemoire.getHeight()+1);
}

/**
* Déplace le sprite à la position désirée sur le JFrame. La différence
* avec setPosition() est qu'il dessine la sprite à sa nouvelle postion.
*
* @param x : nouvelle position x sur le JFrame.
* @param y : nouvelle position x sur le JFrame.
*/
public void deplacerA(int x, int y){
setPosition(x, y);
effacerPrecedent();
dessiner();
}

/**
* Fait tourner le sprite autour de son origine.
*
* @param angle : rotation angulaire à ajouter.
*/
public void tourner(double angle){
effacer();
g.rotate(Math.toRadians(angle), gY, gX);
dessiner();
rotation += angle;
}

/**
* Fait tourner le sprite autour d'un point.
*
* @param angle : rotation angulaire à ajouter.
* @param x : position x du centre de rotation.
* @param y : position y du centre de rotation.
*/
public void tourner(double angle, int x, int y){
effacer();
g.rotate(Math.toRadians(angle), x, y);
dessiner();
rotation += angle;
}

public void setPositionAngulaire(double angle){
effacer();
g.rotate(Math.toRadians(angle) - Math.toRadians(rotation), gX, gY);
dessiner();
rotation = angle;
}

/**
* Etale ou rétrécit l'image en largeur et/ou hauteur.
*
* @param larg : coefficient de redimensionnement en largeur.
* @param haut : coefficient de redimmensionnement en hauteur
*/
public void redimmensionner(double larg, double haut){
effacer();
g.scale(larg, haut);
gX = imgMemoire.getWidth()/2;
gY = imgMemoire.getHeight()/2;
dessiner();
}

}

:d) Ma clase principale (sert de test) : :g)

public class Robots {

/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception{

Fenetre FenetrePrincipale = new Fenetre(100,100,640,480,"Robots");

int i,j;
String repertoireCourant = System.getProperty("user.dir").replace("\\", "/");
System.out.println(repertoireCourant);
i = 0;

Sprite toast = new Sprite( repertoireCourant + "/src/ressources/graph/sprites/robot.png", FenetrePrincipale.getJPanel() );

toast.dessiner();
toast.deplacerA(60, 60);

while (i<=500){
Thread.sleep(25);
toast.deplacerA(i,50);
i++;
}
toast.setPositionAngulaire(90);
toast.setPositionAngulaire(-50);

}

XKCD
XKCD
Niveau 10
02 novembre 2011 à 18:20:25

Mets ton code sur Pastebin vieux, là ça fait mal aux yeux :noel:

Trodroll
Trodroll
Niveau 7
02 novembre 2011 à 18:25:39

Merci pour le site, car j'avoue, ça pique :hap: :

classe Sprite :

http://pastebin.com/ksKUA1Ju

classe principale, (le run, quoi) :

http://pastebin.com/qCf06xSV

Merci :hap:

tbop2
tbop2
Niveau 10
02 novembre 2011 à 21:43:27

Aaaaaaaaaah la documentation inutile qui sert à rien et qui multiplie par deux la taille de ton code. Erk ça m'a saoulé j'ai pas regardé plus de 5 secondes du coup.

godrik
godrik
Niveau 30
02 novembre 2011 à 22:39:59

tu veux du double buffering et de l'acceleration materielle certainement. Donc certainement tu ne veux pas de swing mais de primitive 2d de bas niveau. (swing c'est completement une usine a gaz)

Trodroll
Trodroll
Niveau 7
04 novembre 2011 à 10:06:14

Merci mais les primitives 2D de bas niveau, ça permet d'afficher une image?

_skip
_skip
Niveau 10
04 novembre 2011 à 13:46:03

Tbop2 Voir le profil de Tbop2
Posté le 2 novembre 2011 à 21:43:27 Avertir un administrateur
Aaaaaaaaaah la documentation inutile qui sert à rien et qui multiplie par deux la taille de ton code. Erk ça m'a saoulé j'ai pas regardé plus de 5 secondes du coup.

:d) Il document l'interface publique de sa classe, si choquant que ça?

Arkwolf
Arkwolf
Niveau 29
04 novembre 2011 à 15:58:32

chaud d'être choqué par de la javadoc :(

Aldebran
Aldebran
Niveau 10
04 novembre 2011 à 16:13:44

Je ne suis pas un boss en interface graphique mais est-ce qu'il ne vaudrait pas mieux appeler toutes les méthodes drawImage dans la fonction paintComponent de ta classe JPanel puis appeller repaint de JFrame dans ton while plutôt que de faire tout ça (effacer, redessiner, etc.) ?

"Aaaaaaaaaah la documentation inutile qui sert à rien et qui multiplie par deux la taille de ton code. Erk ça m'a saoulé j'ai pas regardé plus de 5 secondes du coup."

Sérieux sans les commentaires je n'aurais pas pu regarder plus de 5 secondes.

Trodroll
Trodroll
Niveau 7
05 novembre 2011 à 17:00:25

Je te remercie de ta réponse, j'essaierai ça dès que je pourrais :-d . C'est pas facile de se repérer dans java2D, y'a tellement de méthodes et façons de faire pour une chose.

Sinon, désolé pour le collage sur JVC, j'espère que vous avez tous vu le pastebin.

Sous forums
  • Aide à l'achat Mac
  • Création de Jeux
  • Linux
  • Programmation
  • Création de sites web
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment