2009-10-31 13 views
2

J'apprends Java en faisant un petit jeu dans un JApplet. J'ai eu un petit problème avec l'animation de mon sprite.Comment se débarrasser du scintillement qui apparaît pendant mon animation?

Voici le code:

this.sprite.setBounds(0,0,20,17); 

this.sprite.setIcon(this.rangerDown); 
for(int i = 0; i< 16;i++) 
{ 
    this.sprite.setBounds(this.sprite.getX(), this.sprite.getY()+1, 20, 17); 
    this.sprite.update(this.sprite.getGraphics()); 

    try{ 
     Thread.currentThread().sleep(100); 
    }catch(InterruptedException e){ 
} 

}

Il a laissé un peu de scintillement lors de l'animation. Une fois l'animation terminée, le scintillement disparaît, mais c'est plutôt moche ... Je suppose qu'il y a un pas que j'ai manqué. J'utilise cette méthode parce qu'elle donne le meilleur résultat pour l'instant, mais je voudrais rester sans AWT si possible, en utilisant Swing à la place.

Des idées pour se débarrasser du scintillement?

Merci d'avoir lu.

Screenshoot (Impossible de publier des images, désolé).

Répondre

2

Ce n'est pas une ombre. C'est la frontière de votre sprite. Il arrive juste d'être noir et apparaît comme une ombre. Si vous changez le montant que vous déplacez votre sprite (disons par 50 pixels, pas seulement 1), vous verrez ce que je veux dire. Pour résoudre ce problème, vous devez dessiner l'arrière-plan à chaque fois que vous mettez à jour l'emplacement de votre image-objet. Bien que cela produira probablement des scintillements.

La manière correcte de le faire est de changer la façon dont vous dessinez vos objets. Vous devez remplacer la méthode paintComponent de votre panneau, puis appeler simplement repaint chaque fois que vous avez mis à jour les emplacements de vos sprites.

EDIT:

Voir cet exemple de code pour l'utilisation de base. NOTE: Ce n'est pas comme ça que vous devriez écrire une animation en utilisant Threads. J'ai écrit cela pour vous montrer ce qui se passe dans la méthode paintComponent et j'ai écrit l'animation Thread pour vous montrer que l'ombre que vous avez mentionnée est partie. Ne JAMAIS avoir une boucle d'exécution non terminale dans un thread :)

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 


public class Test { 

    public static void main(String[] args) { 
     JFrame f = new JFrame("Test"); 
     MyPanel c = new MyPanel(); 
     f.getContentPane().add(c); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setSize(350, 100); 
     f.setVisible(true); 
    } 

} 

class MyPanel extends JPanel { 

    int x = 0; 
    boolean toTheRight = true; 

    public MyPanel() { 
     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       while (true) { 
        x = (toTheRight)?x+5:x-5; 
        if (x>300) 
         toTheRight = false; 
        if (x<0) 
         toTheRight = true; 
        repaint(); 
        try { 
         Thread.sleep(50); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     }).start(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     Graphics2D g2 = (Graphics2D)g.create(); 
     g2.setPaint(Color.white); 
     g2.fillRect(0, 0, getWidth(), getHeight()); 
     g2.setPaint(Color.red); 
     g2.fillOval(x-2, 50, 4, 4); 
    } 

} 
+0

Merci pour la réponse. Y a-t-il un moyen de le faire avec Swing? Cela semble une méthode assez complexe pour une chose simple. –

+0

Il s'agit de la méthode par défaut pour dessiner des objets personnalisés sur des panneaux avec swing. Vous remplacez paintComponent qui vous fournit un objet Graphics que vous pouvez convertir en un objet Graphics2D en toute sécurité et faire votre chose. Cette méthode garantit également que votre dessin sera à double tampon afin que vous n'ayez pas à vous soucier de scintillement. –

+0

Ok, le mot 'scintillement' me permet de trouver des infos sur Google. Je vais continuer à chercher une solution simple. Merci encore. –

2

Le problème est le double tampon. Dans les applets: Le double tampon est effectué presque automatiquement. Appelez repaint() au lieu de paint dans votre méthode.

Dans Swing, il y a plusieurs façons de le faire. Je vais généralement pour la route BufferStrategy. Lorsque vous initialiser votre cadre, faites ceci:

JFrame frame; 
... code to init frame here 
frame.createBufferStrategy(2); 

ensuite dans vos méthodes de dessin:

Graphics g = getBufferStrategy().getDrawGraphics(); 
..code to do drawing here... 
g.dispose(); 
getBufferStrategy().show(); 
+0

Si je change "this.sprite.update (this.sprite.getGraphics());" "this.sprite.repaint()", il n'y a pas d'animation: seul le sprite de la dernière position est visible. Je crois que la méthode repaint() n'est vraiment utilisée que lorsque le programme n'a rien d'autre à faire. Cependant, j'ai vu cette solution ailleurs, donc je n'utilise probablement pas correctement la méthode repaint(). C'est dans un JApplet, je n'ai jamais utilisé JFrame (n'est-ce pas getContentPane() le remplacement de JFrame dans JApplets?). Eh bien, j'utilise update() parce que ça donne le meilleur résultat, mais j'aimerais rester autant que possible avec Swing. –