# JPanel wechseln & Neu starten - SnakeSpiel



## kamm12 (11. Mai 2015)

Ahoihoi Leute, beim programmieren von einem Snake Klon stellen sich mir zwei Frage, die wohl in die Kategorie Swing/GUI fallen!

Bevor ich das Spiel in der Board Klasse starte würde ich gerne für ca. 1-2 Sekunden das JPanel aus der Intro Klasse darstellen.
Es soll also Intro zunächst geladen und dann wieder durch entfernt und durch Board ersetzt werden.
Habe hier mit Thread.sleep() und Timern mit delay probiert, dann lief jedoch immer das ganze Programm nicht mehr...


Außerdem würde ich das Spiel nach dem GameOver gerne wieder aus diesem heraus neustarten ohne das Fenster schließen und das Spiel neu aufrufen zu müssen. Kann ich irgendwie den Konstruktor erneut aufraufen und so alles neuaufbauen?

Vielen Dank im Voraus!

Main:


```
public class Snake extends JFrame {
	
	public Board board = new Board();
	public Intro intro = new Intro();
	
	public Snake() {
		initUI();
	}
	
	private void initUI() {
		
		add(board);
		
		setResizable(false);
		pack();
		
		setVisible(true);
		setTitle("Snake");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLocation(200, 200);

		/**
		 * In board läuft das Spiel selber. Spielfeld setzt sich aus 4 kleineren Feldern zusammen, die int[] sind.
		 * 
		 * Habe versucht über Thread.sleep() und einen Timer, der nach 2 Sekunden startet
		 * das intro JPanel zu löschen und mit board zu ersetzen. Hat aber irgendwie nicht richtig funktioniert ,
		 * das komplette Programm lief einfach nichtmehr zB bei:
		 * remove(intro);
		 * add(board);
		 * 
		 * Kann man das Intro Fenster 1-2 Sekunden zeigen und dann mit dem Spiel (also dem board beginnen?)
		 * 
		 *  
		 * Wie kann ich ein neues Spiel starten ohne das Programm neu zu starten?
		 * Wenn ich die Schlange gegen die Wand setzte kommt ja mein GameOver Screen aber wie 
		 * kann ich das Spielfeld nochmal neuaufbauen? Die Methode oder was auch immer man braucht
		 * kann ich ja einfach über einen KeyListener aufrufen, aber wie könnte diese aussehen??
		 * 
		 */
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Snake();
	}
}
```


Vereinfachte Board Klasse mit der Spiellogik

```
public class Board extends JPanel implements ActionListener {

	private boolean ingame;
	Timer timer;

	private int delay = 150;
	private final int BOARD_X = 600;
	private final int BOARD_Y = 600;
	private final int PIXEL_SIZE = 20;
	private boolean changedDirection = false;
	private int length;
	private int appleX;
	private int appleY;

	private boolean right = true;
	private boolean left = false;
	private boolean up = false;
	private boolean down = false;

	private int[] x = new int[900]; // X Koordinate des [i]ten Körperteils der
									// Schlange
	private int[] y = new int[900]; // Y Koordinate des [i]ten Körperteils der
									// Schlange

	private String[] gameOver = Data.getGameOvers();
	int[] kachel1 = Data.getSubField();

	int[] mauer = new int[900];

	public Board() {
		initUI();
	}

	private void initUI() {
		addKeyListener(new meinKeyListener()); // Pfeiltasten steuern die
												// Schlange
		setFocusable(true);
		setBackground(Color.LIGHT_GRAY);
		setDoubleBuffered(true);
		ingame = true;
		setPreferredSize(new Dimension(600, 600));

		initSnake();
		initMauern();
		updateApple();

		timer = new Timer(delay, this);
		timer.start();

	}

	private void initSnake() {
	}

	private void updateApple() {
	}

	private void initMauern() {
	}

	private void checkCollisions() {

		// Schlange Fensterrahmen
		if (x[0] >= BOARD_X || x[0] < 0) {
			ingame = false;
		}
		if (y[0] >= BOARD_Y || y[0] < 0) {
			ingame = false;
		}

		// Schlange Kopf Körper
		for (int i = 1; i < length; i++) {
			if (x[0] == x[i] && y[0] == y[i]) {
				ingame = false;
			}
		}

		// Schlange Apfel
		if (x[0] == appleX && y[0] == appleY) {
			updateApple();
			length++;
		}

		// Schlange Mauer
	}

	private void moveSnake() {
	}

	private void increaseDifficulty() {
	}

	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;

		if (ingame) {
			Graphics2D g2dBody = (Graphics2D) g;
			Graphics2D g2dHead = (Graphics2D) g;
			Graphics2D g2dApple = (Graphics2D) g;
			Graphics2D g2dMauer = (Graphics2D) g;

			g2dHead.setColor(Color.RED);
			g2dHead.fillOval(x[0], y[0], PIXEL_SIZE, PIXEL_SIZE);

			g2dBody.setColor(Color.WHITE);
			for (int i = 1; i < length; i++) {
				g2dBody.fillOval(x[i], y[i], PIXEL_SIZE, PIXEL_SIZE);
			}

			g2dApple.setColor(Color.GREEN);
			g2dApple.fillOval(appleX, appleY, PIXEL_SIZE, PIXEL_SIZE);

			for (int i = 0; i < (BOARD_Y / PIXEL_SIZE); i++) {
				for (int j = 0; j < (BOARD_X / PIXEL_SIZE); j++) {
					if (mauer[i * (BOARD_Y / PIXEL_SIZE) + j] == 1) {
						g2dMauer.setColor(Color.ORANGE);
						g2dMauer.fillRect(j * PIXEL_SIZE, i * PIXEL_SIZE,
								PIXEL_SIZE, PIXEL_SIZE);
					}
				}
			}
		} else {
			timer.stop();
			String msg = gameOver[(int) (Math.random() * 19)];
			Font small = new Font("Helvetica", Font.BOLD, 24);
			FontMetrics metr = this.getFontMetrics(small);
			g.setFont(small);
			g.drawString(msg, (int) ((BOARD_X - metr.stringWidth(msg)) / 2),
					(int) (BOARD_Y / 2));
		}
		g2d.setColor(Color.WHITE);
		g2d.setFont(new Font(Font.MONOSPACED, Font.BOLD, 20));
		g2d.drawString("Länge: " + length, 5, 18);

	}

	@Override
	public void actionPerformed(ActionEvent e) {

		increaseDifficulty();
		checkCollisions();
		moveSnake();
		changedDirection = false;
		repaint();

	}

	private class meinKeyListener extends KeyAdapter {
	}

}
```


Die Intro Klasse, die ich gerne kurz einblenden würde

```
public class Intro extends JPanel {

	Image intro;

	public Intro() {
		setFocusable(true);
		setBackground(Color.LIGHT_GRAY);
		setDoubleBuffered(true);
		setPreferredSize(new Dimension(600, 600));

		ImageIcon ii = new ImageIcon("img/intro.jpg");
		intro = ii.getImage();

	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);

		Graphics2D g2d = (Graphics2D) g;
		g2d.drawImage(intro, 0, 0, this);
		g2d.drawString("Intro", 300, 300);

	}
}
```


----------



## Enceladus271 (13. Mai 2015)

Falls du es nicht schon selber gelöst hast: Das mit dem Timer müsste funktionieren:

```
add( intro );

        final Timer timer = new Timer( 2000, new ActionListener() {

            @Override
            public void actionPerformed( ActionEvent e ) {
                Snake.this.remove( intro );
                Snake.this.add( board );
                Snake.this.revalidate();
            }
        } );
        timer.setRepeats( false );
        timer.start();
```

Ich tippe mal darauf dass du das revalidate vergessen hast (Muss immer nach Änderungen am Layout aufgerufen werden wenn die Komponente schon mal angezeigt wurde).

Nach dem GameOver könntest du so in etwa vorgehen:


```
public void reinitAfterGameOver() {
  remove( board );
  add( intro );
  revalidate();
  board = new Board();
  // TODO: timer starten
}
```


----------



## kamm12 (14. Mai 2015)

Hatte jetzt das Problem umgangen indem ich einfach alles in der Board Klasse zurückgesetzt habe.

Werde aber mal ausprobieren ob das ganze mit revalidate() funktioniert. Vielen Dank!


----------

