Afficher des images avec double-buffering

Résolu
deli2025 Messages postés 40 Date d'inscription vendredi 14 mars 2008 Statut Membre Dernière intervention 4 mai 2020 - 11 nov. 2012 à 00:08
deli2025 Messages postés 40 Date d'inscription vendredi 14 mars 2008 Statut Membre Dernière intervention 4 mai 2020 - 12 nov. 2012 à 00:26
Bonjour,

je suis entrain de créer une plateforme en 2D isométrique et je rencontre quelques problème pour afficher la map.

Pour commencer, j'avais créer une class qui héritait de JPanel et je dessinais dessus avec paintComponent. Cela fonctionnait très bien, jusqu’au moment ou j'ai voulu déplacer cette map... (Il y avait des écarts entre mes cases...)

Après avoir effectuer quelques recherches, la solution parait être le double-buffering hardware. J'ai donc voulu adapter ma class JPanel mais je n'y suis pas arrivé et tous les exemples que j'ai trouvé, héritait non pas de JPanel mais de JFrame.

J'ai donc créer une nouvelle Class JFrame pour faire des testes et effectivement le problème est résolu mais un autre est apparu... Maintenant, quand je déplace la map, je vois toujours son ancienne position !



Je souhaiterais donc avoir votre avis sur la bonne manière de procéder... Sachant que j'aurais préférer avoir une Class scene héritant de JPanel e contenant le desin de la map...

Mais je galère ;) (Je débute en Java et en orienté object)

Merci d'avance pour votre aide !

PS: je vous joins les Class et n'hésitez pas à me conseiller sur le reste aussi ;)

Ma nouvelle Class héritant de JFrame
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package game;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;

/**
 *
 * @author D3L1
 */
public class Game extends JFrame implements MouseListener, MouseMotionListener, KeyListener
{
    private Map map;
    
    // boucle d'affichage
    RafraichissementThread rafraichissement = new RafraichissementThread(); 
    // variable permettant d'utiliser la mémoire VRAM
    BufferStrategy strategy; 
    // buffer mémoire où les images et les textes sont appliqués
    Graphics buffer; 
  

    
    public Game()
    {
        creerFenetre();
        
        map = new Map();

        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        this.addKeyListener(this);

        createBufferStrategy(2); 

        strategy =getBufferStrategy();
        
        buffer =strategy.getDrawGraphics();
        
        rafraichissement.start();

        Thread deplacementMap = new Thread(map);
        deplacementMap.start();
    }
    
    private void creerFenetre()
    {
        this.setTitle("Mon Jeu");
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setSize(1024, 600);
        this.setLocationRelativeTo(null);
        this.setBackground(Color.DARK_GRAY);
        this.setIgnoreRepaint(true);
        this.setVisible(true);
    }
    
    public class RafraichissementThread extends Thread
    {
        @Override
        public void run()
        {
            while(true)
            {
                try  
                {
                    graphicalRender();
                    this.sleep( 5);
                   
                } 
                catch( Exception e){}
            }
        }
    }

    
    public void graphicalRender()
    {
        for(int x = 0; x < Constantes.LARGEUR_MAP; x++)
        {
            for(int y = 0; y < Constantes.HAUTEUR_MAP; y++)
            {
                Point coordonneeEcran = new Point(0, 0);

                coordonneeEcran.x = ((x - y) * Constantes.LARGEUR_DEMI_TILE) - map.getMap()[x][y].getDemiWidth();
                coordonneeEcran.y = ((x + y) * Constantes.HAUTEUR_DEMI_TILE) - map.getMap()[x][y].getHeight();
                
                buffer.drawImage(map.getMap()[x][y].getImage(), coordonneeEcran.x + Constantes.POSITION_DEPART_X, coordonneeEcran.y + Constantes.POSITION_DEPART_Y, this);
            }
        }
        
        strategy.show(); 
    }
    
    @Override
    public void mouseClicked(MouseEvent e) 
    {
        Constantes.Mx = e.getX();
        Constantes.My = e.getY(); 
        
        System.out.println(map.coordEcranEnCoordTile());

        System.out.println(map.infoTile());
    } 

    @Override
    public void mouseReleased(MouseEvent e){}
    
    @Override
    public void mousePressed(MouseEvent e)
    {
        Constantes.Mx = e.getX();
        Constantes.My = e.getY(); 
    }
    
    @Override
    public void mouseMoved(MouseEvent e){}
   
    @Override
    public void mouseExited(MouseEvent e){}

    @Override
    public void mouseEntered(MouseEvent e){}

    @Override
    public void mouseDragged(MouseEvent e)
    {
        Constantes.Mx = e.getX();
        Constantes.My = e.getY(); 
        map.getMap()[map.coordEcranEnCoordTile().x][map.coordEcranEnCoordTile().y] = map.herbe;
 
    } 

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) 
    {
        int KeyCode = e.getKeyCode();

        switch(KeyCode)
        {
            case KeyEvent.VK_UP: map.KeyPressed(e);
                break;
            case KeyEvent.VK_DOWN: map.KeyPressed(e);
                break;
            case KeyEvent.VK_LEFT: map.KeyPressed(e);
                break;
            case KeyEvent.VK_RIGHT: map.KeyPressed(e);
                break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) 
    {
        int KeyCode = e.getKeyCode();

        switch(KeyCode)
        {
            case KeyEvent.VK_UP: map.KeyRelease(e);
                break;
            case KeyEvent.VK_DOWN: map.KeyRelease(e);
                break;
            case KeyEvent.VK_LEFT: map.KeyRelease(e);
                break;
            case KeyEvent.VK_RIGHT: map.KeyRelease(e);
                break;
        }
    }
}



Mon ancienne Class héritant de JPanel
package game;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JPanel;
import javax.swing.Timer;


/**
 *
 * @author D3L1
 */
public class Scene extends JPanel implements MouseListener, MouseMotionListener, KeyListener, ActionListener
{
    public Map map;
    Timer temps;
    
    
    RenderingThread renderingThread = new RenderingThread();
    Graphics buffer;
    Image image;

    
    public Scene()
    {
        map = new Map();
        
        this.setLayout(null);
        this.setFocusable(true);
    
        /*
         * Ajoute les listener sur le JPanel
         */
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        this.addKeyListener(this);
        
        
        Thread deplacementMap = new Thread(map);
        deplacementMap.start();
        
        temps = new Timer(0, this);
        temps.start();  
    }
    
    /*
     * Dessine la map
     */
    @Override
    public void paintComponent(Graphics g)
    {   
       super.paintComponent(g);
       
       image = createImage(1024,600);
       
       buffer = image.getGraphics();
        
        for(int x = 0; x < Constantes.LARGEUR_MAP; x++)
        {
            for(int y = 0; y < Constantes.HAUTEUR_MAP; y++)
            {
                Point coordonneeEcran = new Point(0, 0);

                coordonneeEcran.x = ((x - y) * Constantes.LARGEUR_DEMI_TILE) - map.getMap()[x][y].getDemiWidth();
                coordonneeEcran.y = ((x + y) * Constantes.HAUTEUR_DEMI_TILE) - map.getMap()[x][y].getHeight();
                
                buffer.drawImage(map.getMap()[x][y].getImage(), coordonneeEcran.x + Constantes.POSITION_DEPART_X, coordonneeEcran.y + Constantes.POSITION_DEPART_Y, this);
            }
        } 
        
        g.drawImage(image, 0, 0, this);
    }
    
    @Override
    public void mouseClicked(MouseEvent e) 
    {
        Constantes.Mx = e.getX();
        Constantes.My = e.getY(); 
        
        System.out.println(map.coordEcranEnCoordTile());

        System.out.println(map.infoTile());
    } 

    @Override
    public void mouseReleased(MouseEvent e){}
    
    @Override
    public void mousePressed(MouseEvent e)
    {
        Constantes.Mx = e.getX();
        Constantes.My = e.getY(); 
    }
    
    @Override
    public void mouseMoved(MouseEvent e){}
   
    @Override
    public void mouseExited(MouseEvent e){}

    @Override
    public void mouseEntered(MouseEvent e){}

    @Override
    public void mouseDragged(MouseEvent e)
    {
        Constantes.Mx = e.getX();
        Constantes.My = e.getY(); 
        map.getMap()[map.coordEcranEnCoordTile().x][map.coordEcranEnCoordTile().y] = map.herbe;
        repaint();
    } 

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) 
    {
        int KeyCode = e.getKeyCode();

        switch(KeyCode)
        {
            case KeyEvent.VK_UP: map.KeyPressed(e);
                break;
            case KeyEvent.VK_DOWN: map.KeyPressed(e);
                break;
            case KeyEvent.VK_LEFT: map.KeyPressed(e);
                break;
            case KeyEvent.VK_RIGHT: map.KeyPressed(e);
                break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) 
    {
        int KeyCode = e.getKeyCode();

        switch(KeyCode)
        {
            case KeyEvent.VK_UP: map.KeyRelease(e);
                break;
            case KeyEvent.VK_DOWN: map.KeyRelease(e);
                break;
            case KeyEvent.VK_LEFT: map.KeyRelease(e);
                break;
            case KeyEvent.VK_RIGHT: map.KeyRelease(e);
                break;
        }
    } 

    @Override
    public void actionPerformed(ActionEvent e) 
    {
        repaint();  
    }
}        
  


Et ma Class map au cas ou ^^
package game;

import java.awt.Point;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Scanner;
import tiles.*;


/**
 *
 * @author D3L1
 */
public final class Map implements Runnable
{
    public final static Tile[][] mapTile = new Tile[Constantes.LARGEUR_MAP][Constantes.HAUTEUR_MAP];
    private final static String[] mapLettre = new String[Constantes.LARGEUR_MAP * Constantes.HAUTEUR_MAP];
    private Scanner fichierMap;

    int xDirection;
    int yDirection;

    /*
     * On défini les tiles constituant la map
     */
    public Eau eau = new Eau();
    public Herbe herbe = new Herbe();
    public Pave pave = new Pave();
    public Arbre arbre = new Arbre();
    public Terre terre = new Terre();
    public Bat batiment = new Bat();
    
    /*
     * Constructeur
     */
    public Map()
    {
        this.ouvrirFichierMap();
        this.lireFichierMap();
        this.fermerFichierMap();
    }
    
    /*
     * Ouvre le fichier
     */
    public void ouvrirFichierMap()
    {
        try
        {
            fichierMap = new Scanner(new File(Constantes.dossierMap));
        }
        catch(Exception e)
        {
            System.out.println("Erreur pendant le chargement de la map.");
        }
    }
    
    /*
     * Lit le fichier et constitue la map
     */
    public void lireFichierMap()
    {
        int j = 0;
        
        for(int x = 0; x < Constantes.LARGEUR_MAP ; x++)
        {
            for(int y = 0; y < Constantes.HAUTEUR_MAP ; y++)
            {
                mapLettre[j] = fichierMap.next();

                String index = mapLettre[j].substring(j, j + 1);
                
                switch(index)
                {
                    case "A": mapTile[x][y] = arbre;
                        break;
                    case "B": mapTile[x][y] = batiment;
                        break;
                    case "E": mapTile[x][y] = eau;
                        break;
                    case "H": mapTile[x][y] = herbe;
                        break;
                    case "P": mapTile[x][y] = pave;
                        break;
                    case "T": mapTile[x][y] = terre;
                        break;
                    default: mapTile[x][y] = herbe;;
                }
            }
        }
    }
    
    /*
     * Ferme le fichier
     */
    public void fermerFichierMap()
    {
        fichierMap.close();
    }
    
    /*
     * Envoi la map
     */
    public Tile[][] getMap()
    {
        return mapTile;
    }
    
    /*
     * ToString de Tile
     */
    public String infoTile()
    {
        return this.getMap()[coordEcranEnCoordTile().x][coordEcranEnCoordTile().y].toString();    
    }
    
    /*
     * Transforme une position écran en position d'une tile
     */
    public Point coordEcranEnCoordTile()
    {
        float x =  Constantes.Mx - Constantes.POSITION_DEPART_X;
        float y =  Constantes.My - Constantes.POSITION_DEPART_Y;
 
        Point position = new Point();
 
        position.x = (int)((float)Math.floor((y / Constantes.HAUTEUR_TILE) + (x / Constantes.LARGEUR_TILE +1)));
        // Math.floor : Arrondi à l'entier inférieur | +1 : 
            
        position.y = (int)((float)(int)Math.ceil((y / Constantes.HAUTEUR_TILE) - (x / Constantes.LARGEUR_TILE))); 
        // Math.ceil : Arrondi à l'entier supérieur
            
        return position;
    }
    
    /*
     * Main de test
     */
    public static void main(String[] args)
    {
        Map map = new Map();
        map.getMap();
        System.out.println(map.infoTile());
    }

    public void deplacement()
    {
        Constantes.POSITION_DEPART_X += xDirection;
        Constantes.POSITION_DEPART_Y += yDirection;
    }
    
    public void setDirectionX(int dX)
    {
        xDirection = dX;
    }
    
    public void setDirectionY(int dY)
    {
        yDirection = dY;
    }
    
    public void KeyPressed(KeyEvent e)
    {
        int KeyCode = e.getKeyCode();

        switch(KeyCode)
        {
            case KeyEvent.VK_UP: setDirectionY(+2);
                break;
            case KeyEvent.VK_DOWN: setDirectionY(-2);
                break;
            case KeyEvent.VK_LEFT: setDirectionX(+2);
                break;
            case KeyEvent.VK_RIGHT: setDirectionX(-2);
                break;
        }
    }
    
    public void KeyRelease(KeyEvent e)
    {
        int KeyCode = e.getKeyCode();

        switch(KeyCode)
        {
            case KeyEvent.VK_UP: setDirectionY(0);
                break;
            case KeyEvent.VK_DOWN: setDirectionY(0);
                break;
            case KeyEvent.VK_LEFT: setDirectionX(0);
                break;
            case KeyEvent.VK_RIGHT: setDirectionX(0);;
                break;
        }
    }
    
    @Override
    public void run()
    {
        try
        {
            while(true)
            {
                deplacement();
                Thread.sleep(5);
            }
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}

4 réponses

deli2025 Messages postés 40 Date d'inscription vendredi 14 mars 2008 Statut Membre Dernière intervention 4 mai 2020
12 nov. 2012 à 00:26
Bon... avant de redessiner la map, je dessine un rectangle de fond et la plus de trace de la map mais le problème que j'avais avec JPanel est de nouveau présent (écart entre les tiles quand je déplace la map)...


Je vois pas ce que je peux faire...
3
Utilisateur anonyme
11 nov. 2012 à 18:14
Bonsoir

Je n'ai rien trouvé mais je pense que si vous posez votre question sur Java-Gaming, vous aurez très rapidement une réponse. J'utilise peu Java2D pour les jeux bien que ce soit tout à fait possible. Je pense que vous utilisez mal la BufferStrategy et une instance de java.awt.Canvas suffirait pour dessiner tout ça, libre à vous de la mettre dans un JPanel par la suite. Jetez un coup d'oeil ici et ici.















T.U.E.R (First Person Shooter créé par Julien Gouesse)
0
deli2025 Messages postés 40 Date d'inscription vendredi 14 mars 2008 Statut Membre Dernière intervention 4 mai 2020
11 nov. 2012 à 19:58
Merci pour ta réponse.

Sinon j'ai utilisé BufferStrategy comme l'exemple montré dans les FAQ de ce site...

Je vais allé voir un peu sur java-gaming mais mon anglais risque de me poser problème ^^
0
deli2025 Messages postés 40 Date d'inscription vendredi 14 mars 2008 Statut Membre Dernière intervention 4 mai 2020
11 nov. 2012 à 22:26
... Je viens de le faire avec Canvas plutôt qu'un JPanel mais toujours le même problème, on voit encore l'ancienne position de la map. Il y aurait t'il moyen d'éffacer le canvas avant de redessiner dessus ?

package game;

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;


/**
 *
 * @author D3L1
 */
public class GameCanvas extends Canvas implements Runnable, MouseListener, MouseMotionListener, KeyListener
{
    private BufferedImage image = new BufferedImage(Constantes.LARGEUR_MAP, Constantes.HAUTEUR_MAP, BufferedImage.TYPE_INT_RGB);
    private BufferStrategy bufferStrategy;
    private boolean running = false;

    
    private Map map;

    public GameCanvas()
    {
        map = new Map();
        
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        this.addKeyListener(this);

        Thread deplacementMap = new Thread(map);
        deplacementMap.start();
    }
    
    private void start()
    {
        running = true;
        new Thread(this).start();
    }
    
    @Override
    public void run()
    {
        while(running)
        {
            render();
        }
    }
    
    public void stop()
    {
        running = false;
    }
    
    /*
     * Dessine la map
     */
    public void render()
    {
        bufferStrategy = getBufferStrategy();
        
        if(bufferStrategy == null)
        {
            createBufferStrategy(3);
            requestFocus();
            return;
        }
        
        Graphics g = bufferStrategy.getDrawGraphics();
        
        for(int x = 0; x < Constantes.LARGEUR_MAP; x++)
        {
            for(int y = 0; y < Constantes.HAUTEUR_MAP; y++)
            {
                Point coordonneeEcran = new Point(0, 0);

                coordonneeEcran.x = ((x - y) * Constantes.LARGEUR_DEMI_TILE) - map.getMap()[x][y].getDemiWidth();
                coordonneeEcran.y = ((x + y) * Constantes.HAUTEUR_DEMI_TILE) - map.getMap()[x][y].getHeight();
                
                g.drawImage(map.getMap()[x][y].getImage(), coordonneeEcran.x + Constantes.POSITION_DEPART_X, coordonneeEcran.y + Constantes.POSITION_DEPART_Y, this);
            }
        }
        
        g.dispose();
        
        bufferStrategy.show();
    }
    
    @Override
    public void mouseClicked(MouseEvent e) 
    {
        Constantes.Mx = e.getX();
        Constantes.My = e.getY(); 
        
        System.out.println(map.coordEcranEnCoordTile());

        System.out.println(map.infoTile());
    } 

    @Override
    public void mouseReleased(MouseEvent e){}
    
    @Override
    public void mousePressed(MouseEvent e)
    {
        Constantes.Mx = e.getX();
        Constantes.My = e.getY(); 
    }
    
    @Override
    public void mouseMoved(MouseEvent e){}
   
    @Override
    public void mouseExited(MouseEvent e){}

    @Override
    public void mouseEntered(MouseEvent e){}

    @Override
    public void mouseDragged(MouseEvent e)
    {
        Constantes.Mx = e.getX();
        Constantes.My = e.getY(); 
        map.getMap()[map.coordEcranEnCoordTile().x][map.coordEcranEnCoordTile().y] = map.herbe;
 
    } 

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) 
    {
        int KeyCode = e.getKeyCode();

        switch(KeyCode)
        {
            case KeyEvent.VK_UP: map.KeyPressed(e);
                break;
            case KeyEvent.VK_DOWN: map.KeyPressed(e);
                break;
            case KeyEvent.VK_LEFT: map.KeyPressed(e);
                break;
            case KeyEvent.VK_RIGHT: map.KeyPressed(e);
                break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) 
    {
        int KeyCode = e.getKeyCode();

        switch(KeyCode)
        {
            case KeyEvent.VK_UP: map.KeyRelease(e);
                break;
            case KeyEvent.VK_DOWN: map.KeyRelease(e);
                break;
            case KeyEvent.VK_LEFT: map.KeyRelease(e);
                break;
            case KeyEvent.VK_RIGHT: map.KeyRelease(e);
                break;
        }
    }
    
    public static void main(String[] args) 
    {
        GameCanvas game = new GameCanvas();
        
        JFrame frame = new JFrame();
        frame.add(game);
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   
        frame.setSize(1024, 600);
        frame.setLocationRelativeTo(null);
        frame.setResizable(true);
        frame.setVisible(true);

        game.start();
    }
}        
  
0
Rejoignez-nous