Arrêter le scintillement dans les swing quand j'ai repeint trop
Je fais un RPG avec une tilemap. Pour générer la tilemap je boucle par un 2 dimensions, tableau, mais cela signifie que lorsque je repeindre je dois le faire à chaque fois. Si je repeindre trop de l'écran scintille comment ai-je pu l'en empêcher.
package sexyCyborgFromAnOtherDimension;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class Game extends JPanel
{
KeyLis listener;
int mapX = 20;
int mapY = 20;
boolean up = false;
boolean down = false;
boolean right = false;
boolean left = false;
String[][] map;
public Game()
{
super();
try
{
map = load("/maps/map1.txt");
}
catch (IOException e)
{
//TODO Auto-generated catch block
e.printStackTrace();
}
listener = new KeyLis();
this.setFocusable(true);
this.requestFocus();
this.addKeyListener(listener);
Timer timer = new Timer();
TimerTask task = new TimerTask()
{
@Override
public void run()
{
if(up)
{
mapY++;
repaint();
}
if(down)
{
mapY--;
repaint();
}
if(right)
{
mapX--;
repaint();
}
if(left)
{
mapX++;
repaint();
}
}
};
timer.scheduleAtFixedRate(task, 0, 10);
}
public void paint(Graphics g)
{
super.paintComponent(g);
setDoubleBuffered(true);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (int x = 0; x < map.length; x++)
{
for (int y = 0; y < map[x].length; y++)
{
switch(map[x][y])
{
case "0":
g.setColor(Color.GREEN);
break;
case "1":
g.setColor(Color.GRAY);
break;
}
g.fillRect(y*20+mapX, x*20+mapY, 20, 20);
}
}
g.setColor(Color.BLACK);
g.fillRect(400, 400, 20, 20);
}
String[][] load(String file) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(file)));
int lines = 1;
int length = br.readLine().split(" ").length;
while (br.readLine() != null) lines++;
br.close();
BufferedReader br1 = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(file)));
String[][] map = new String[lines][length];
for (int i = 0; i < lines; i++)
{
String line = br1.readLine();
String[] parts = line.split(" ");
for (int y = 0; y < length; y++)
{
map[i][y] = parts[y];
}
}
br1.close();
return map;
}
private class KeyLis extends KeyAdapter
{
@Override
public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_UP:
up = true;
break;
case KeyEvent.VK_DOWN:
down = true;
break;
case KeyEvent.VK_LEFT:
left = true;
break;
case KeyEvent.VK_RIGHT:
right = true;
break;
}
}
@Override
public void keyReleased(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_UP:
up = false;
break;
case KeyEvent.VK_DOWN:
down = false;
break;
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_RIGHT:
right = false;
break;
}
}
}
}
Merci pour votre aide
Modifier
À l'aide de javax.swing.Timer
supprime tous scintillement, même avec un 10 ms de retard.
+1 pour votre nom de paquet.
en effet belle - mais de ne pas se conformer aux conventions de nommage java <g>
Ok je vais le changer pour com.sexyCyborgFromAnOtherDimension.
le domaine n'est pas le point: les noms de paquets ne devraient pas contenir des lettres majuscules 🙂
plusieurs machines de mal avec votre code (peut-être sans rapport avec le problème) a) remplacer paintComponent pour la peinture custom (pas peinture) b) ne pas modifier l'état du composant dans une méthode de peinture c) favoriser les Raccourcis clavier sur KeyListeners Autres que: 10ms ressemble à un très serrée boucle...
en effet belle - mais de ne pas se conformer aux conventions de nommage java <g>
Ok je vais le changer pour com.sexyCyborgFromAnOtherDimension.
le domaine n'est pas le point: les noms de paquets ne devraient pas contenir des lettres majuscules 🙂
plusieurs machines de mal avec votre code (peut-être sans rapport avec le problème) a) remplacer paintComponent pour la peinture custom (pas peinture) b) ne pas modifier l'état du composant dans une méthode de peinture c) favoriser les Raccourcis clavier sur KeyListeners Autres que: 10ms ressemble à un très serrée boucle...
OriginalL'auteur sanchixx | 2013-07-31
Vous devez vous connecter pour publier un commentaire.
Un certain nombre de petites choses qui sautent à moi.
Tout d'abord. Vous pourriez être mieux à l'aide de
javax.swing.Timer
au lieu dejava.util.Timer
, cela permettra au moins les événements à couler un peu mieux.Deuxièmement, 10 millisecondes est à une courte période de temps, sérieusement, vous n'avez pas besoin de 100fps, 60 im /s est d'environ 17 millisecondes, j'ai l'habitude d'utiliser de 40 millisecondes pour 25fps. Cela pourrait donner l'EDT un peu de répit pour réellement répondre aux demandes de peintures.
Troisièmement, vous devriez être en utilisant
paintComponent
au lieu depaint
. C'est suffisamment faible dans la chaîne d'appel à la garantie à double tamponQuatrièmement, vous devez éviter tout appel de méthode qui pourrait convenir d'un rendez -
repaint
(commesetDoubleBuffered
par exemple, dans le constructeur, si vous devez, mais, composants Swing sont double tampon par défaut)Cinquièmement, si possible, de la peinture tous les "statique" ou de ralentir la modification du contenu d'une sauvegarde de la mémoire tampon et de la peinture à la place. Cela permettra d'accroître la vitesse à laquelle
paint
peut fonctionner comme il ne reste pas coincée dans un grand nombre de petites boucles.Vous pouvez prendre un coup d'oeil à La peinture dans AWT et Swing pour plus de détails sur le processus de peinture
Quelques autres exemples...
Et parce que kléo me fait peur (et c'est aussi une bonne idée), vous devriez également prendre un coup d'oeil à Comment utiliser les raccourcis clavier, qui permettra de résoudre vos problèmes de focus avec le
KeyListener
Ok j'ai très peu de scintillement maintenant 🙂
Alors vous êtes encore en train de faire quelque chose de mal, il devrait y pas de scintillement. Si vous prenez le temps de regarder certains des exemples que j'ai lié, vous devriez trouver qu'aucun d'entre eux souffrent de tout scintillement à tous
Je n'ai pas plus de scintillement
OriginalL'auteur MadProgrammer
Vous avez défini le double buffering sur le panneau, mais les choses que vous dessinez sur vous-même ne sont pas double tampon. L'appel de
setDoubleBuffered(true)
ne s'applique mise en mémoire tampon pour enfant composants du contenant.Vous devez manuellement tampon choses que vous dessinez vous-même.
Je suggère de passer d'une
JPanel
et l'utilisation d'unCanvas
à la place. Jetez un oeil à la façon dont unCanvas
est utilisé avec un tampon de stratégie dans cette classe, où il peut gérer des centaines de choses dessiné à l'écran avec une fluidité et sans scintillement (le jeu fonctionne sur un 10ms sommeil boucle trop).Ou utiliser
paintComponent
au lieu depaint
où il est double tampon...et à l'aide dejavax.swing.Timer
ne serait pas mal non pluspas tout à fait vrai: le RepaintManager bulles repeindre la demande du plus proche parent qui est doubleBuffered. Un composite est donc, par défaut, même si elle est définie à ne pas doubleBuffered, le rootPane est 🙂
juste remarqué qu'il appelle
super.paintComponent()
de l'intérieurpaint()
:SEh bien, c'est d'aller à vis les choses 😛
OriginalL'auteur Qwerky
Pas vraiment sûr si cela résout votre problème, mais vous pouvez envisager d'utiliser un 1dimensional tableau.
quand
int width;
est la largeur de votre écran/vignette/tout ce que vous boucle etint height
est à la hauteur de petit plus ponctuellement effectuer les opérations suivantes:au lieu de cela, ce que vous faites:
vous pourriez passer par ce chemin
OriginalL'auteur Loki