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

2D Java Discussion :

animation saccade swing


Sujet :

2D Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 98
    Par défaut animation saccade swing
    Bonjour,

    j'ai un problème de saccade lors d'une animation (très simple : une balle qui bouge horizontalement) avec Swing.

    Je précise que si je remplace mes JFrame et JPanel par les classes AWT Panel et Frame cela fonctionne correctement (au problème d'absence de double Buffering près).

    Ma question est donc comment faire en SWING pour avoir quelquechose de fluide. Je vous poste mon code ci dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    import javax.swing.*;
    import java.awt.*;
     
    public class CasseBrique {
     
     
    	public CasseBrique(){
     
    		JFrame frame = new JFrame("Casse brique v1.0");
    		frame.setSize(new Dimension(800,600));
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		Jeu jeu = new Jeu(100,100,2,0);
    		frame.add(jeu);
    		frame.setVisible(true);
    		jeu.init();
    	}
     
    	public static void main(String[] arg){
    		new CasseBrique();
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.*;
     
     
    public class Jeu extends JPanel{
     
    	private int x,y;
    	private int vx,vy;
    	private Timer timer;
    	ActionListener moveBall;
     
    	public Jeu(int x, int y, int vx, int vy){
    		this.x=x;
    		this.y=y;
    		this.vx=vx;
    		this.vy=vy;
     
    		moveBall = new ActionListener() {
     
    			@Override
    			public void actionPerformed(ActionEvent e) {
    				calculerPosition();
    				repaint();
    			}
    		};
    	}
     
    	public void paint(Graphics g){
    		super.paint(g);
    		g.fillOval(x, y, 40, 40);
    	}
     
    	public void init(){
    		this.setBackground(Color.BLACK);
    		this.setForeground(Color.BLUE);
    		timer= new Timer(40, moveBall);
    		timer.start();
    	}
     
    	private void calculerPosition() {
    		if (x<0 ||x>=800-10)
    			vx=-vx;
     
    		if (y<0 || y>=600-10)
    			vy=-vy;
     
    		x+=vx;
    		y+=vy;
    	}
    }

  2. #2
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 901
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 901
    Billets dans le blog
    54
    Par défaut
    Pour ma part c'est fluide.

    J'ai fait cependant quelques changements :
    1. Lancement de l'application dans l'EDT.
    2. Quand on appelle repaint() ca demande un re-affichage complet. Ici j'ai rappelle des repaint() localises sur l'ancien et le nouvel emplacement de la boule. Au final la zone de clip du Graphics lors du prochain affichage sera l'union de ces deux zones. A noter que j'ai mis un peu de marge autour ce qui est toujours utile quand on fait de l'anti-alias.
    3. Renomme paint() en paintComponent() (paint() c'est pour l'AWT).
    4. Le rendu se fait desormais en fonction de la zone de clip du Graphics.
    5. Egalement on cree un nouveau Graphics2D a partir de l'ancien, ca permet de modifier sa config ou de lui appliquer des transformations sans que cele ne bousille l'ancien (ou que l'on soit oblige de restorer/annuler ces transformations). La zone de clip du nouveau Graphics est compatible avec celle de l'ancien.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package animation;
     
    import javax.swing.*;
    import java.awt.*;
     
    public class CasseBrique {
     
        public CasseBrique() {
     
            JFrame frame = new JFrame("Casse brique v1.0");
            frame.setSize(new Dimension(800, 600));
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Jeu jeu = new Jeu(100, 100, 2, 0);
            frame.add(jeu);
            frame.setVisible(true);
            jeu.init();
        }
     
        public static void main(String[] arg) {
            // Lancement dans l'EDT.
            SwingUtilities.invokeLater(new Runnable() {
     
                /**
                 * {@inheritDoc}
                 */
                @Override
                public void run() {
                    new CasseBrique();
                }
            });
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
     
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package animation;
     
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.*;
     
    public class Jeu extends JPanel {
     
        private int x,  y;
        private int vx,  vy;
        private Timer timer;
        ActionListener moveBall;
     
        public Jeu(int x, int y, int vx, int vy) {
            this.x = x;
            this.y = y;
            this.vx = vx;
            this.vy = vy;
     
            moveBall = new ActionListener() {
     
                /**
                 * {@inheritDoc}
                 */
                @Override
                public void actionPerformed(ActionEvent e) {
                    int margin = 2;
                    // Effacement de l'ancienne position de la boule.
                    repaint(Jeu.this.x - margin, Jeu.this.y - margin, 40 + 2 * margin, 40 + 2 * margin);
                    calculerPosition();
                    // Affichage du nouvel emplacement de la boule.
                    repaint(Jeu.this.x - margin, Jeu.this.y - margin, 40 + 2 * margin, 40 + 2 * margin);
                }
            };
        }
     
        /**
         * {@inheritDoc}
         */
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Shape clip = g.getClip();
            if (clip.intersects(x, y, 40, 40)) {
                Graphics2D g2d = (Graphics2D) g.create();
                //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                try {
                    g2d.fillOval(x, y, 40, 40);
                } finally {
                    g2d.dispose();
                }
            }
        }
     
        public void init() {
            this.setBackground(Color.BLACK);
            this.setForeground(Color.BLUE);
            timer = new Timer(40, moveBall);
            timer.start();
        }
     
        private void calculerPosition() {
            if (x < 0 || x >= 800 - 10) {
                vx = -vx;
            }
     
            if (y < 0 || y >= 600 - 10) {
                vy = -vy;
            }
     
            x += vx;
            y += vy;
        }
    }
    Mais bon, c'etait quand meme fluide avant ces changements.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 98
    Par défaut
    Bonjour,

    je viens de voir que j'avais une réponse donc tout d'abord merci de t'être donné la peine de tester et pour tes suggestions.

    J'ai tout d'abord une question quel est l'intérêt de lancer le code dans l'EDT ?

    Sinon en fait j'ai pas mal potassé depuis ce post.

    Effectivement j'ai retesté en SWING après avoir fait un détour par AWT et l'animation me parait correct et fluide, j'avais peut être poussé le bouchon un peu loin !

    Sinon concernant le code après avoir constaté qu'avec mon programme si j'augmentais la resolution les temps de réponse devenaient désastreux, j'ai effectivement dans un premier temps fait comme toi en ajoutant une zone de clipping. Cela fonctionne très bien.

    Le seul truc qui m'a dérangé en fait c'est la structure du code : être obligé de redéfinir la méthode Paint qui ne prends pas de paramètres autre que Graphic, je ne trouve vraiement pas cela pratique quand tu souhaites faire quelque chose d'un peu plus conséquent. Etant donné que je débute la méthode pour écrire mon code élégament m'a peut être échappée mais je n'ai pas trouvé!

    La deuxième solution que j'ai testé pour faire du double buffering, c'est la technique du "page flipping". Et si j'ai bien compris comment cela fonctionne, avec le page flipping tu ne peux pas faire du clipping (la je veux bien avoir confirmation) vu que tu as uniquement un pointeur sur ta mémoire vidéo et un pointeur sur ta zone d'affichage et que tu ne fais que switcher les deux. Cela semble ne pas trop mal marcher mais je pense qu'il faut encore que je convertisse le format de mes images au format natif pour atteindre une meilleur vitesse.
    De plus je trouve qu'avec cette technique tu n'as pas à redéfinir la méthode paint et que donc l'écriture du code est beaucoup plus aisée.

    Voili voilou, si vous pouvez confirmer ou infirmer mes propos cela m'interesserait, étant donné que je n'ai aucune certitude sur ce que je viens d'ennoncer

  4. #4
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    En ce qui concerne els images natives il faut procéder de la façon suivante pour en créer une à partir de n'importe quelle image

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      public static BufferedImage loadCompatibleImage(URL resource) throws IOException {
        BufferedImage image = ImageIO.read(resource);
        GraphicsConfiguration configuration = GraphicsEnvironment.
          getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
        BufferedImage compatibleImage = configuration.createCompatibleImage(image.getWidth(),
                                                                            image.getHeight());
        Graphics g = compatibleImage.getGraphics();
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return compatibleImage;
      }
    Sinon t'es tu intéressé aux bibliothèques destinées à l'animation telles que le timingframework

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2007
    Messages
    98
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 98
    Par défaut
    Merci pour le code.

    Pour le framework je viens juste de voir la réponse que tu faisais à gifffftane qui semble avoir le même problème que moi et j'allais justement m'y interresser.

  6. #6
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 901
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 901
    Billets dans le blog
    54
    Par défaut
    Ce n'est pas tant qu'elle soit native mais qu'elle est dans le meme format interne que la carte video et donc cela evite une etape de convertion au niveau de l'affichage (et donc l'affichage en est plus rapide).

    De maniere generale, mieux vaut rester avec une solution semi-soft (qui peut quand meme avoir une acceleration materielle via OpenGL ou Direct3D) utilisant BufferedImage. Effectuer un changement d'image offscreen peut s'apparenter a du pageflipping.

    Sinon cote pure materielle il faut voir du cote de BufferStrategy ou de VolatileImage mais c'est moins evident a mettre en place et il y a des contraintes au niveau de la GUI. Changer le buffer actif dans la strategie est la maniere de faire du pageflipping.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

Discussions similaires

  1. Probleme rafraichissement animation avec Swing
    Par Philinux dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 01/07/2010, 02h53
  2. Problème d'animations saccadées
    Par DV2.0 dans le forum GTK+ avec C & C++
    Réponses: 0
    Dernier message: 02/06/2009, 12h49
  3. Animation java + saccade
    Par cysboy dans le forum Ubuntu
    Réponses: 2
    Dernier message: 19/03/2008, 10h31
  4. Lancer une anim flash dans une appli Swing ?
    Par elitost dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 20/07/2006, 20h57
  5. [SWING] Animation à partir de jpg
    Par Deaf dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 11/07/2006, 18h25

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