# [Problem] layeredPane bzw. Viewport



## Samake03 (22. Jan 2012)

Hallo ihr,

sorry dass ich mal wieder ein Problem habe welches ich seit 3 Tagen nicht gelöst bekomme. Mittlerweile weiß ich auch nicht mehr wo ich ansetzen soll. Ich bitte euch darum um ein paar rettende Ideen. 

Ich bastel immernoch an meinem Mini-Spielchen weiter, jedoch war mir das alles zu statisch und so wollte ich ein wenig Bewegung in die Sache bringen und mit scrollenden Background ein wenig Tiefe simulieren. 

Das klappt soweit für die erste Version sehr gut, jedoch haben sich Probleme ergeben an welche ich vorher nicht gedacht habe. 

Hier mal zum testen was ich mit der simulierten Tiefe und meinem Problem meine: eLapse_test_01.jar _(Mit "Enter" könnt ihr starten)_

Das Problem ist, dass im Grunde nur suggeriert wird sich in einem größeren Raum zu befinden, sobald aber andere Objekte dazukommen bleiben die logischerweise mit in meinem Frame und bewegen sich mit mir. Logisch da im Prinzip ja nur eine Ebene vorhanden ist.

Also wollte ich mir eine Art "Viewport" basteln und dazu layeredPane verwenden, wodurch ich mehrere Ebenen haben könnte und gleichzeitig auch das Level wirklich vergrößern könnte um mich dann nur noch mit meinem Port über den Hintergrund und die tatsächlichen Koordinaten scrolle.

Jedoch zeigen sich nun neue Probleme und ich weiss nichtmal ob ich das so richtig mache. Hier mal meine auf´s Minimum reduzierte Test-Klasse:


```
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;


public class GameMainTest extends JFrame implements Runnable{

	private static final long serialVersionUID = 1L;
	JLayeredPane viewport;
    JPanel backgroundPanel, actionPanel;
    
    public static Integer LAYER_ONE = JLayeredPane.FRAME_CONTENT_LAYER + 1;
    public static Integer LAYER_TWO = LAYER_ONE + 1;

	Image background = loadTextures("textures/backgrounds/background.png");
    Image logo = loadTextures("textures/logo/logo.png");
	
    
	public static void main(final String[] args){
    	new GameMainTest(800, 600);
    }
	
    public GameMainTest(int w, int h) {
        super("eLapse");
        setSize(w, h);
        setLocationRelativeTo(null);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
       
        backgroundPanel = new JPanel();
        backgroundPanel.setBounds(0, 0, 400, 300);

        actionPanel = new JPanel();
        actionPanel.setBounds(200, 150, 400, 300);
       
        viewport = getLayeredPane();
        viewport.add(backgroundPanel, LAYER_ONE, 0);
        viewport.add(actionPanel, LAYER_TWO, 0);
        
        Thread th = new Thread(this);
		th.setName("MainGameThread");
		th.start();
    }
    

	@Override
	public void run() {

		while (super.isVisible()) {
			
			repaint();

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

	
	public void paint(Graphics g){//FIXME
		//super.paint(g);
		g.drawImage(background, 0, 0, backgroundPanel);
		g.drawImage(logo, 100, 100, actionPanel);
		
	}


	
	private Image loadTextures(String path) {

		java.net.URL pic_url = getClass().getClassLoader().getResource(path);

		BufferedImage image = null;
		try {
			image = ImageIO.read(pic_url);
		} catch (IOException e) {
		}
		return image;
	}
}
```

*1. Problem:*

Sobald ich in der Methode paint(g) ein zweites Objekt hinzufüge flackert dieses. Zu sehen auch hier: eLapse_problem.jar

Wenn ich "super.paint(g);" dazunehme flackert sogar alles. Woran liegt das und wie kann ich das umgehen?

*2. Problem:* 

Wie kann ich gezielt über die Methode paint(g) auf die verschiedenen Layer Objekte malen? Woran erkenne ich dass sie wirklich auf der gewünschten Ebene gezeichnet werden? Ist da mein Ansatz richtig? Ich habe das Gefühl dass die Objekte zwar da sind aber nicht auf den gewünschten Layern.

Zum Testen hier nochmal der Source mit Bildern: Source

Ich danke schon einmal für eure Mühe das lesen und hoffe auf ein paar gute Ratschläge für einen motivierten Anfänger. 

Grüße Maik


----------



## Helgon (22. Jan 2012)

paintComponent(Graphics g) ?


----------



## Samake03 (22. Jan 2012)

Egal ob ich paint(Graphics g), paintAll(Graphics g), paintComponents(Graphics g) verwende, alles nach dem ersten Objekt flackert. 

Dazu kommt "paintComponent(Graphics g)" lässt er gar nicht zu sondern verlangt dass ich in "paintComponent*s*(Graphics g)" ändere. Ich steh irgendwie voll auf dem Schlauch .


----------



## Fu3L (22. Jan 2012)

paintComponents ist die dümmste Methode, die es gibt... Ich hab keine Ahnung was sie macht, ich weiß nur, dass sie mir mal ne halbe Stunde Bug-Jagd gebracht hat, nur weil ein s mit reingerutscht ist -.-

Im Prinzip würde ich empfehlen, dass du von JPanel erbst und nicht von JFrame, weil im JFrame wird evtl. noch mehr Magie betrieben in den Zeichenmethoden.
Ansonsten ist die Bewegung von anderen Objekten nicht soo das Problem auch ohne 2 Layers.

Hier ein Beispiel, wenn der Boden aus immer gleichen Kacheln besteht:


```
int xOffset = game.getPlayer().x - WIDTH / 2 + game.getPlayer().getCurrentSprite().getHeight() / 2;
int yOffset = game.getPlayer().y - HEIGHT / 2 - game.getPlayer().getCurrentSprite().getHeight() / 2;
Rectangle2D viewport = new Rectangle2D.Double(xOffset, yOffset, WIDTH, HEIGHT);

int gw = ground.getWidth(); //BodenTiles
int gh = ground.getHeight();
int beginX = WIDTH - (xOffset + WIDTH) % gw;
int beginY = HEIGHT - (yOffset + HEIGHT) % gh + gh;
for(int i = beginX; i + gw > 0; i -= gw) { //Male den Boden
	for(int n = beginY; n + gh > 0; n -= gh) {
		screen.draw(ground, i, n, null); //müsste 1:1 mit g.draw() ersetzbar sein.
	}
}

for(Entity e : entities) { //Male die Gegner
	Bitmap s = e.getCurrentSprite();
	if(viewport.intersects(e.getVisibleRect())) { //Wenn die Objekte von Rectangle erben, kann natürlich hier direkt e übergeben werden
		screen.draw(s, e.x - xOffset, e.y - yOffset, null)
	}
}

//Hier dann den Spieler malen. Oder mittendrin, wenn die Objekte nach der Tiefe sortiert sind
```


----------

