Swing Snake repaint() "flackern"

Status
Nicht offen für weitere Antworten.

eQuest

Mitglied
Hallo Community,

ich habe Snake in Java programmiert. Steht zurzeit noch in den Kinderschuhen, aber die Steuerung & Bewegung funktioniert schonmal. Probleme habe ich jetzt noch mit dem zeichnen.

Dazu folgendes:
Ich habe also das Programm geschrieben, ausprobiert und voila, funktioniert. Ich kann die Schlange mit den Pfeiltasten herumsteuern. Aufgefallen ist mir halt dann, dass das, was vorher gezeichnet wurde, nicht verschwindet. "Achso, repaint vergessen..". Also schnell in den Thread ein repaint() gepackt und Run. Was ich dann sah, machte mir etwas stutzig. Am Besten kann man es wohl mit "flackern" beschreiben. Also so wie ich das erkennen konnte, wurde immer wieder neu gezeichnet, nur man sah die Schlange nur kurz aufflackern oder sogar nur einzelne Punkte o0
Ahm ja, ich dachte vl. ist es das DoubleBuffering und setzte dieses auf true.. denkste ...

Tja, soweit bin ich nun =\ Ich werde ma etwas Code posten, damit ihr euch das ma anschaun könnt. Wenn mir wer helfen könnte, wär das klasse 🙂

JPanel - Land:

Code:
public class Land extends JPanel{
	
	public void paint(Graphics g){
		Iterator<Punkt> it = Spiel.list.listIterator();
		Punkt temp;
		Startpunkt sp=(Startpunkt) it.next();
		Richtung dir_sp = sp.getDir();
		int x = sp.getX(), y = sp.getY(), tempx, tempy;
		
		if(dir_sp == Richtung.RIGHT)
			sp.setX(x+10);
		else if(dir_sp == Richtung.DOWN)
			sp.setY(y+10);
		else if(dir_sp == Richtung.LEFT)
			sp.setX(x-10);
		else if(dir_sp == Richtung.UP)
			sp.setY(y-10);
		
		g.drawOval(sp.getX(), sp.getY(), 10, 10);
		
		while(it.hasNext()){
			temp=it.next();
			tempx=temp.getX();
			tempy=temp.getY();
			temp.setX(x);
			temp.setY(y);
			x=tempx;
			y=tempy;
			g.drawOval(temp.getX(), temp.getY(), 10, 10);
		}
		
	}

}

MainThread - while(true)

Code:
		while(true){
			jf.repaint();
			land.paint(jf.getGraphics());
			
			//Verzögern
			try {
				Thread.sleep(sleeptime);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}

Wenn mehr benötigt wird, einfach sagen, glaube das sind so die wichtigsten Sachen.
 
Wenn man eine Klasse von JPanel ableitet überschreibt man nicht paint(), sonderen paintComponent und ruft dort super.paintComponent() auf.

Sollte etwas so aussehen:

[Java]
protected void paintComponent(Graphics g){

super.paintComponent(g);

//Restliche Anweisungen
}
[/Java]
 
Zuletzt bearbeitet:
Er hat oben bereits geschrieben, dass er das versucht hat ;-)

Stimmt 😀

Ich bin jetzt leider etwas überfragt, folgendes könnte ich mir noch vorstellen:

Du hast in deiner list noch die alten Werte drin, sodass dass die alten Punkte der Schlange auch gezeichnet werden.

Ne, das ist nicht der Fall. Die Werte werden in paintComponent() überschrieben.

Aber danke erstma für die Beiträge, hoffe wir kommen noch dahinter ^^"
 
> Die Werte werden in paintComponent() überschrieben.
Daran kann das flackern auch liegen, wenn du in paintComponent() die neuen Werte berechnest, da das auch eine gewisse Zeit in Anspruch nimmt und dadurch das Zeichnen verzögert wird.
Die ganzen Berechnung solten in deiner Game-Loop (MainThread) gemacht werden und in paintComponent() sollte nur gezeichnet werden.
 
Zuletzt bearbeitet:
habe es jetzt folgendermaßen umgebaut:
Leider ist der Fehler noch nicht behoben 🙁

paintComponent()
Code:
public void paintComponent(Graphics g, int x, int y){
				
		g.drawOval(x, y, 10, 10);
			
	}

MainThread - while(true)
Code:
while(true){
			
			it=Spiel.list.listIterator();
			sp=(Startpunkt) it.next();
			dir_sp=sp.getDir();
			x=sp.getX();
			y=sp.getY();
			
			if(dir_sp == Richtung.RIGHT)
				sp.setX(x+10);
			else if(dir_sp == Richtung.DOWN)
				sp.setY(y+10);
			else if(dir_sp == Richtung.LEFT)
				sp.setX(x-10);
			else if(dir_sp == Richtung.UP)
				sp.setY(y-10);
			
			jf.repaint();
			
			while(it.hasNext()){
				temp=it.next();
				tempx=temp.getX();
				tempy=temp.getY();
				temp.setX(x);
				temp.setY(y);
				x=tempx;
				y=tempy;
				land.paintComponent(jf.getGraphics(), sp.getX(), sp.getY());
			}

			//Verzögern
			try {
				Thread.sleep(sleeptime);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
 
Du musst in Land paintComponent(Graphics) überschreiben und nicht eine eigenen Methode paintComponent(Graphics, int, int) definieren. Dann kannst du in deiner Main-Loop nur noch land.repaint() aufrufen.
Wie du in paintComponent von Land an die benötigten Werte (Koordinaten) zum Zeichnen kommst musst du dir halt überlegen.
Folgendes Tutorial sollte für die Grundstruktur von so einem Spiel auch recht hilfreich sein:
Spieleprogrammierung Tutorial
 
...
land.paintComponent(jf.getGraphics(), sp.getX(), sp.getY());
...
Falls du da nicht Dinge machst, die du nicht machen solltest, solange du nich weißt, dass du da vermutlich Dinge machst, die du nicht machen solltest, machst du da etwas, was man nicht machen sollte: Man sollte fast NIE auf einer Component "getGraphics" aufrufen!

Poste am besten mal ein bißchen mehr Code. (Ideal ist was kleines compilierbares)
 
@andree111
danke dir, ich hab mir das runtergeladen und ma aufmerksam durchgelesen. Habe mein Programm nach dieser Vorlage umgeschrieben und voila, funktioniert perfekt ohne flackern ! 🙂

Danke auch an die Anderen für die Beteiligung 😉

Werde jetzt weitermachen und Snake ausbauen, falls wieder Fragen auftauchen erlaube ich es mir, die hier zu posten ;P
 
nein nicht ganz, ich verstehe immer noch nicht, warum es bei der alten Methode geflackert hat. Aber nicht so wichtig, jetz weiß ich ja, wie man das umgeht 🙂
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben