# Weiße, vertikale Streifen beim Scrollen auf der Map



## Gandave (24. Mai 2008)

Hallöchen!
Ich versuche derzeit ein kleines Rollenspiel zu programmieren. Angelehnt habe ich mich dabei an dieses tolle Tutorial von Quaxli "Spiele-Programmierung in Java".
Bisher hat alles ganz gut geklappt, aber jetzt habe ich ein Problemchen (logisch, sonst würde ich hier nicht um Hilfe bitten ...)

Im Spiel gibt es eine Klasse namens Map, die eine Karte darstellt, also einen zweidimensionalen Array von 'Tile's enthält und Befehle, um diese zu zeichnen. Die Klasse Tile symbolisiert eine rechteckige Platte auf der Karte (32 mal 32 Pixel). Dazu hat jedes Tile ein BufferedImage sowie Koordinaten.
Außerdem gibt es eine Klasse 'Character', die von der Klasse 'Sprite' abgeleitet ist und die Figur des Spielers darstellt, also wieder Bild und Koordinaten.

Bisher lief es so, dass paintComponent() unter anderem die Karte zeichnet (indem sie Map.drawObjects(Graphics g) aufruft) und dann den Character da drauf (mittels Character.drawObjects(Graphics g)). Dann überprüft das Programm, ob eine Pfeiltaste gedrückt wurde, bewegt ggfs. den Character und zeichnet erneut.
Wichtig dabei: die Map wird nicht bewegt, der Character schon.

Jetzt wollte ich aber nicht mehr den Character bewegen, sondern die Map, sodass man auch Maps erstellen kann, die größer als der Bildschirm sind und über die man trotzdem laufen kann. Die Map bewegt sich also immer so, dass der Character genau in der Mitte bleibt.

In der Map sieht es jetzt so aus:


```
public class Map
extends Rectangle
{
// gibt an, wie viel von dem äußersten Tile "abgeschnitten" werden muss
	protected int deltaX, deltaY;

	protected Tile[][] tiles;

// diverse Methoden zum Initalisieren	

// kurz gesagt: er berechnet, wo der Character steht und was man dann sehen muss
	public Point portCharToMap(String lastMap)
	{
		Point p = startpoints.get(lastMap);
		x = p.x-width/2;
		y = p.y-height/2;
		deltaX = (width % 2 == 0) ? 16 : 0;
		deltaY = (height % 2 == 0) ? 16 : 0;
		p = new Point(x+p.x*32, y+p.y*32);
		setPattern();
		return p;
	}

// diese Methode wird vom Spiel aufgerufen, um zu signalisieren, wie sich der Character bewegt hätte, also wie man die Map verschieben muss
	public void scroll(int deltaX, int deltaY)
	{
		this.deltaX += deltaX;
		if (this.deltaX > 32)
		{
			this.deltaX -= 32;
			x++;
		} else if (this.deltaX < 0)
		{
			this.deltaX += 32;
			x--;
		}

		this.deltaY += deltaY;
		if (this.deltaY > 32)
		{
			this.deltaY -= 32;
			y++;
		} else if (this.deltaY < 0)
		{
			this.deltaY += 32;
			y--;
		}
		
		setPattern();
	}

// den Tiles, die gezeichnet werden, wird gesagt, wo auf dem Bildschirm sie sich befinden
	private void setPattern()
	{
		for (int a = (x-1 < 0) ? 0 : x-1;
				a < ((x+width+1 >= tiles.length) ? tiles.length : x+width+2); a++)
			for (int b = (y-1 < 0) ? 0 : y-1;
				b < ((y+height+1 >= tiles[0].length) ? tiles[0].length : y+height+2); b++)
				tiles[a][b].setCoordinates((a-x)*32-deltaX, (b-y)*32-deltaY);
	}

// hier wird gezeichnet. die try-catch-Anweisung ist für den Fall, dass a und b außerhalb des Array-Bereichs sind, also wenn der Character sich am Rand der Map befindet. An diese Stelle wird dann nichts gezeichnet
	public void drawObjects(Graphics g)
	{
		for (int a = x-1; a < x+width+2; a++)
			for (int b = y-1; b < y+height+2; b++)
				try
				{
					tiles[a][b].drawObjects(g);
				} catch (Exception ex) {}
	}
}
```


Mein Problem:
Wenn ich jetzt auf der Karte laufe, flackern beim Laufen (nicht beim Stehen!) weiße, vertikale Striche zwischen den Tiles auf. Sie verschwinden zwar sofort wieder, aber das nervt natürlich!
Das Interessante dabei ist, dass diese Streifen nur beim nach links oder nach oben laufen erscheinen!
Außerdem erscheinen sie zufällig verteilt, also nicht immer an den selben Stellen.


Hat jemand eine Idee, wie ich dieses Problem lösen könnte, bzw. woher mein Problem kommt?
Ich vermute, dass die Tiles z.T. versetzt gezeichnet werden und im Zwischenraum dann weiß durchschimmert!

PS: Hier nochmal ein Bild, damit man sich das mit der Karte und den Tiles vorstellen kann:


----------



## Marco13 (25. Mai 2008)

Spontan geraten: Werden die Koordinaten der Tiles (z.B. in der setPattern-Methode) vielleicht von einem anderen Thread geändert als dem, der zeichnet (d.h. von einem anderen als dem Event-Dispatch-Trhead?). Dann könnte es sein, dass er gerade die Hälfte der Tiles schon gezeichnet hat, und ihm dann mittendrin die Koordinaten unter dem Hintern weg geändert werden... Evtl. muss man das ggf. im gleichen Thread machen, oder irgendwie synchronisieren....


----------



## Gandave (25. Mai 2008)

Ich habs nochmal überprüft, nein die einzige Methode die die Tiles verschiebt ist setPattern() und die wird auch nur von einer einzigen Methode während des Spiels aufgerufen (scroll()).
Könnte es vielleicht mit der Performance zu tun haben? Aber dann müsste ja das ganze Spiel hängen, oder?


----------



## EgonOlsen (25. Mai 2008)

Aber drawObjects() rufts du nicht direkt auf, sondern über paint() oder paintComponent(), oder? Und setPattern() direkt? In dem Fall hast du zwei Threads, nämlich deinen und den AWT Event Thread, der zeichnet. Wenn sich beide überlappen (und das tun sie, wenn du nichts dagegen unternimmst), dann zeichnest du Zwischenstände, wo nicht alle Tiles verschoben sind.


----------



## Gandave (26. Mai 2008)

Hm, also ich umgehe das Problem jetzt, indem ich beim Betreten der Map ein großes BufferedImage erstelle, bei dem alle Tiles nebeneinander gemalt werden und beim 'drawObjects()'-Befehl mittels 'getSubImage()' dann der entsprechende Teil, der gerade sichtbar ist.
Ich muss noch ein bisschen dran rum testen, aber es scheint zu funktionieren!


----------

