# GUI zum Spiel hinzufügen



## ebenich (26. Dez 2014)

Hallo Community,

ich habe nicht sehr viel Erfahrung mit Programmierung. Mithilfe einiger Tutorials habe ich mir das Spiel "Snake" zusammengebastelt, welches auch funktioniert. Nun möchte ich hier noch ein GUI hinzufügen. 
Ich arbeite mit Eclipse "Kepler" und würde gern den WindowBuilder für das GUI nutzen (ist schneller und einfacher denke ich mal  ). Meine Frage ist jetzt, wie kann ich das Spiel dahinein betten bzw. das GUI drumherum bauen?

Ich arbeite mit einem Windows PC (8.1)


----------



## Foxei (26. Dez 2014)

Es gibt natürlich sehr Viele Möglichkeiten ein UI mit einem Work-Flow zu kombinieren aber erst einmal woher weist du das Snake funktioniert wenn du kein UI hast? :noe:


----------



## Gucky (26. Dez 2014)

Du brauchst ein Fenster zum Anzeigen, ein Panel zum Malen und Buttons zum Steuern. Die ordnest du schön an und verknüpfst sie anschließend mithilfe von Listenern, Überschreibungen etc. mit der Programmlogik.


----------



## ebenich (26. Dez 2014)

Naja das Snake funktioniert weiß ich, weil es halt läuft, wenn ich es starte^^
Das hab ich erstmal so programmiert, dass es ohne gui zu steuern ist.

Also soll ich quasi erst das Interface an sich zusammenbasteln und dann wird das Programm (Snake) dareingeschoben oder wie?


----------



## Gucky (27. Dez 2014)

Die Logik muss unabhängig vom GUI agieren. Das ist dazu gut, dass das GUI ausgetauscht werden kann, ohne die Logik ändern zu müssen.

Aber GUI Tutorials gibt es im Netz zur Genüge. Hier kannst du konkrete Fragen zu konkreten Problemen stellen 

Es läuft halt, wenn du es startest: der Lüfter meines Rechners hat sich auch gedreht und trotzdem war die Festplatte kaputt. Das ist kein Argument 

"dareingeschoben": Wie meinst du das? Du kannst nichts einfach irgendwo reinschieben. Bei aller Abstraktion muss eine gewisse Abhängigkeit doch vorhanden sein.


----------



## ebenich (27. Dez 2014)

Snake habe ich ohne gui programmiert. Die Steuerung erfolgt über Tasten. Wenn ich das Programm Snake starte,  öffnet sich ein Fenster mit dem Spielfeld,  einer grünen Schlange die sich bewegt und wächst,  wenn sie die kleinen gelben Punkte  frisst ->  Spiel funktioniert 

Ich wollte jetzt auch nicht erklärt bekommen,  wie ich das gui zusammen baue, sondern nur, wie ich es zu dem bereits existierenden Spiel hinzufüge


----------



## Java20134 (27. Dez 2014)

Du fügst eine GUI hinzu indem du erst einmal eine erstellst und danach in deinem jetzigen Code eine Instanz von dieser Klasse erstellst und instanziierst und dann hast du es eigentlich schon! 

Wenn du weitere Hilfe brauchst müsstest du uns noch den Code geben!


----------



## Zitrus (27. Dez 2014)

> [...]Die Steuerung erfolgt über Tasten[...]
> [...]öffnet sich ein Fenster mit dem Spielfeld[...]



Hört sich ganz nach einer GUI an


----------



## ebenich (27. Dez 2014)

Zitrus hat gesagt.:


> Hört sich ganz nach einer GUI an



Hä? Ich dachte ´n GUI ist so ein extra Teil "neben" dem eigentlichen Programm, in welches man Buttons & Co. einfügt...


----------



## Java20134 (27. Dez 2014)

Ja, aber auch dein derzeitiges Programm. GUI heißt übersetzt Graphical User Interface, auf Deutsch kurz Grafische Benutzeroberfläche. Und das was du dann gemacht hast ist demnach auch eine GUI.


----------



## ebenich (27. Dez 2014)

Achso 
Na ich wollte jetzt noch diesen "extra Teil" machen, indem ich dann noch einige Buttons (Restart bspw.) und ne Punkteanzeige reinmache.


----------



## Java20134 (27. Dez 2014)

Verstehe, um das am besten zu realisieren müsste ich wissen, erbt deine Klasse von etwas und auf was zeichnest du. Oder am besten postest du den Quellcode. Wenn du kurz wartest kann ich dir ein kleines Menü erstellen.


----------



## Java20134 (27. Dez 2014)

Das ist das Menü:

```
package GUI;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Main extends JFrame implements ActionListener {

	private static final long serialVersionUID = -3952745723207919180L;
	private JButton btnStart, btnInfo, btnClose;
	
	public static void main(String[] args){
		Main frame = new Main(); 
		frame.setVisible(true);
	}
	
	public Main(){
		setTitle("Snake");
		setBounds(100, 100, 200, 200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		
		JPanel content = new JPanel();
		content.setBorder(new EmptyBorder(5,5,5,5));
		content.setLayout(null);
		setContentPane(content);
		
		btnStart = new JButton("Start"); 
		btnStart.setBounds(45, 30, 100, 25); 
		content.add(btnStart); 
		
		btnInfo = new JButton("Info"); 
		btnInfo.setBounds(45, 70, 100, 25); 
		content.add(btnInfo); 
		
		btnClose = new JButton("Close"); 
		btnClose.setBounds(45, 110, 100, 25); 
		content.add(btnClose); 
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		if(arg0.getSource() == btnStart){
			//Was soll gemacht werden, wenn der Button gedrückt wurde? 
		}
		else if(arg0.getSource() == btnInfo){
			//Was soll gemacht werden, wenn der Button gedrückt wurde? 
		}
		else if(arg0.getSource() == btnClose){
			//Was soll gemacht werden, wenn der Button gedrückt wurde? 
		}
	}
}
```
Und die Punkteanzeige machst du, indem du in der paint oder paintComponent Methode folgendes hinzufügst. 

```
g.drawString(i, x, y);
```
i ist dabei ein Integer, welches die Punktzahl repärsentiert und x und y jeweils die Position der linken oberen Ecke.


----------



## ebenich (27. Dez 2014)

Genau sowas hab ich gemeint 
und da wollte ich jetzt nur wissen, wie ich das mit dem bisherigen Spiel "verschmelze"


----------



## Java20134 (27. Dez 2014)

Um das zu sagen brauchen wir den Quellcode von dir. Du hast Standardwerte und diese muss man dem JButton bntStart hinzufügen, indem man in dem ActionListener bei dem einem Kommentar des JButtons diese Standardwerte setzt oder/und einfach ein neues Objekt von deiner Klasse erzeugst.


----------



## ebenich (27. Dez 2014)

Sry, dass es so lange gedauert hat. Es gab nur grad ein kleines Problem, aber wieder alles i.O.


```
package snake;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.Timer;
import javax.swing.JFrame;


public class Snake implements ActionListener, KeyListener  {
	
	public static Snake snake;
	public JFrame jframe;
	public RenderPanel renderPanel;
	public Timer timer = new Timer(20, this);
	
	public ArrayList<Point> snakeParts = new ArrayList<Point>();
	public int ticks = 0, direction = DOWN, score, BodyLength = 10;
	public static final int UP = 0, DOWN = 1, LEFT = 2, RIGHT = 3, SCALE = 10; 
	public Point head, food;
	public Random random; 
	public boolean over = false, paused;
	public Dimension dim; 
	
	public Snake() {
		dim = Toolkit.getDefaultToolkit().getScreenSize();
		jframe = new JFrame("Snake");
		jframe.setVisible(true);
		jframe.setSize(605, 629);
		jframe.setResizable(false);
		jframe.setLocation(dim.width / 2 - jframe.getWidth() / 2, dim.height
				/ 2 - jframe.getHeight() / 2 );
		jframe.add(renderPanel = new RenderPanel());
		jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jframe.addKeyListener(this);
		
		
		startGame();
	}
	
	public void startGame() {
		over = false;
		paused = false;
		score = 0;
		BodyLength = 2;
		ticks = 0;
		direction = DOWN;
		head = new Point(15, 15);
		random = new Random();
		snakeParts.clear();
		food = new Point(random.nextInt(59), random.nextInt(59));
		timer.start();
	}
	
	
	

	@Override
	public void actionPerformed(ActionEvent arg0) {
		renderPanel.repaint();
		ticks++;
			
		if (ticks % 5 == 0 && head != null && !over && !paused){
			snakeParts.add(new Point(head.x, head.y));	
			if (direction == LEFT)
				if (head.x - 1 >= 0 && noTailAt(head.x - 1, head.y))
					head = new Point(head.x - 1, head.y);
				else
					over = true;
			if (direction == RIGHT)
				if (head.x + 1 < 59 && noTailAt(head.x + 1, head.y))
					head = new Point(head.x + 1, head.y);
				else
					over = true;
			if (direction == UP)
				if (head.y - 1 >= 0 && noTailAt(head.x, head.y - 1))
					head = new Point(head.x, head.y - 1);
				else
					over = true;
			if (direction == DOWN)
				if (head.y + 1 < 59 && noTailAt(head.x, head.y + 1))
					head = new Point(head.x, head.y + 1);
					else
						over = true;	
				
			if (snakeParts.size() > BodyLength)
				snakeParts.remove(0);			
			if (food != null)	{
				if (head.equals(food)){
					score += 2;
					BodyLength++;
					food.setLocation(random.nextInt(59),random.nextInt(59));
				}
			}
	
		}
	}
		
	public boolean noTailAt(int x, int y) {
		for (Point point : snakeParts){
			if (point.equals(new Point(x, y))){
				return false;
			}
		}
		return true;
		
	}
	
	public static void main(String[] args) {
		snake = new Snake(); 
					
	}
	
	@Override
	public void keyPressed(KeyEvent e) {
		int i = e.getKeyCode();
		if (i == KeyEvent.VK_LEFT && direction != RIGHT)
			direction = LEFT;
		if (i == KeyEvent.VK_RIGHT && direction != LEFT)
			direction = RIGHT;
		if (i == KeyEvent.VK_UP && direction != DOWN)
			direction = UP;
		if (i == KeyEvent.VK_DOWN && direction != UP)
			direction = DOWN;
		if (i == KeyEvent.VK_SPACE)
			if (over)
			startGame();
		else
			paused = !paused;
	}
	
	@Override
	public void keyReleased(KeyEvent e) {
		
	}
	
	@Override
	public void keyTyped(KeyEvent e) {
		
	}
	
	
}
```
und das RenderPanel

```
package snake;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;

import javax.swing.BorderFactory;
import javax.swing.JPanel;


@SuppressWarnings("serial")
public class RenderPanel extends JPanel {
	
	public static Color farbe = new Color(11665408);

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(farbe); 
		g.fillRect(0, 0, 600, 600);
		setBorder(BorderFactory.createLineBorder(Color.BLACK,8));
		
		Snake snake = Snake.snake;
		g.setColor(Color.GREEN);
		for (Point point : snake.snakeParts){
			g.fillRect(point.x * Snake.SCALE, point.y * Snake.SCALE,
					Snake.SCALE, Snake.SCALE);
		}
		g.fillRect(snake.head.x * Snake.SCALE, snake.head.y * Snake.SCALE,
					Snake.SCALE, Snake.SCALE);
			g.setColor(Color.YELLOW);
			g.fillOval(snake.food.x * Snake.SCALE, snake.food.y * Snake.SCALE,
					Snake.SCALE, Snake.SCALE);
			g.setColor(Color.BLACK);
			
		    String string = "Score: " + snake.score + ", Länge"
		    				+ snake.BodyLength;
		    g.setColor(Color.BLACK);
		    g.drawString(string,  (int) (getWidth() / 2 - string.length() * 2.5f), 590);
		    string = "Game Over!";
		    if (snake.over)
		    	g.drawString(string, (int) (getWidth() / 1.8 - string.length() * 5f),
		    				 (int) snake.dim.getHeight() / 4);
		      
	}
	
}
```


----------



## Java20134 (27. Dez 2014)

Lass mal deine Klasse Snake von JFrame erben. 

```
public class Snake extends JFrame implements ... {}
```
Und dann erstellst du ja in deinem Haupkonstruktor ein JFrame. Dort wo du das JFrame definierst schreibst du 

```
Main frame = new Main();
```
Und dann müsstest du bei den unteren Methoden auch nicht mehr frame davor schreiben. Lass das setVisibile raus.  

Und in das Menü schreibst du noch folgendes:

```
package GUI;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Main extends JFrame implements ActionListener {

	private static final long serialVersionUID = -3952745723207919180L;
	private JButton btnStart, btnInfo, btnClose;
	
	public static void main(String[] args){
		Main frame = new Main(); 
		frame.setVisible(true);
	}
	
	public Main(){
		setTitle("Snake");
		setBounds(100, 100, 200, 200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		
		JPanel content = new JPanel();
		content.setBorder(new EmptyBorder(5,5,5,5));
		content.setLayout(null);
		setContentPane(content);
		
		btnStart = new JButton("Start"); 
		btnStart.setBounds(45, 30, 100, 25); 
		content.add(btnStart); 
		
		btnInfo = new JButton("Info"); 
		btnInfo.setBounds(45, 70, 100, 25); 
		content.add(btnInfo); 
		
		btnClose = new JButton("Close"); 
		btnClose.setBounds(45, 110, 100, 25); 
		content.add(btnClose);
		
		//NEU
		Snake sake = new Snake(); 
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		if(arg0.getSource() == btnStart){
			//NEU
			snake.setVisible(true); 
			snake.start();
		}
		else if(arg0.getSource() == btnInfo){
			//Was soll gemacht werden, wenn der Button gedrückt wurde? 
		}
		else if(arg0.getSource() == btnClose){
			//Was soll gemacht werden, wenn der Button gedrückt wurde? 
		}
	}
}
```


----------



## ebenich (27. Dez 2014)

Wenn ich die Klasse Snake von JFrame erben lasse, wird Snake gelb unterstrichen  mit der Meldung: The serializable class Snake does not declare a static final serialVersionUID field of type long. Was bedeutet das bzw. wie behebe ich das?


----------



## Java20134 (27. Dez 2014)

Menü: 

```
package GUI;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class Main extends JFrame implements ActionListener {

	private static final long serialVersionUID = -3952745723207919180L;
	private JButton btnStart, btnInfo, btnClose;
	
	public Snake frame; 
	
	public static void main(String[] args){
		Main frame = new Main(); 
		frame.setVisible(true);
	}
	
	public Main(){
		setTitle("Snake");
		setBounds(100, 100, 200, 200);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		
		JPanel content = new JPanel();
		content.setBorder(new EmptyBorder(5,5,5,5));
		content.setLayout(null);
		setContentPane(content);
		
		btnStart = new JButton("Start"); 
		btnStart.addActionListener(this);
		btnStart.setBounds(45, 30, 100, 25); 
		content.add(btnStart); 
		
		btnInfo = new JButton("Info"); 
		btnInfo.addActionListener(this);
		btnInfo.setBounds(45, 70, 100, 25); 
		content.add(btnInfo); 
		
		btnClose = new JButton("Close");
		btnClose.addActionListener(this);
		btnClose.setBounds(45, 110, 100, 25); 
		content.add(btnClose);
		
		frame = new Snake(); 
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		if(arg0.getSource() == btnStart){
			frame.startGame();
			frame.setVisible(true);
		}
		else if(arg0.getSource() == btnInfo){
			//Was soll gemacht werden, wenn der Button gedrückt wurde? 
		}
		else if(arg0.getSource() == btnClose){
			//Was soll gemacht werden, wenn der Button gedrückt wurde? 
		}
	}
}
```

RenderPanel: 

```
package GUI;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import javax.swing.BorderFactory;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class RenderPanel extends JPanel {
	public static Color farbe = new Color(11665408);
	public Snake snake; 
	
	public RenderPanel(Snake snake){
		this.snake = snake; 
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.setColor(farbe); 
		g.fillRect(0, 0, 600, 600);
		setBorder(BorderFactory.createLineBorder(Color.BLACK,8));

		g.setColor(Color.GREEN);
		for (Point point : snake.snakeParts){
			g.fillRect(point.x * Snake.SCALE, point.y * Snake.SCALE,
					Snake.SCALE, Snake.SCALE);
		}
		g.fillRect(snake.head.x * Snake.SCALE, snake.head.y * Snake.SCALE,
				Snake.SCALE, Snake.SCALE);
			g.setColor(Color.YELLOW);
			g.fillOval(snake.food.x * Snake.SCALE, snake.food.y * Snake.SCALE,
					Snake.SCALE, Snake.SCALE);
			g.setColor(Color.BLACK);
	    String string = "Score: " + snake.score + ", Länge"
		    				+ snake.BodyLength;
		    g.setColor(Color.BLACK);
	    g.drawString(string,  (int) (getWidth() / 2 - string.length() * 2.5f), 590);
		    string = "Game Over!";
		    if (snake.over)
		    	g.drawString(string, (int) (getWidth() / 1.8 - string.length() * 5f),
		    				 (int) snake.dim.getHeight() / 4);
	}
}
```

Snake: 

```
package GUI;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.Timer;
import javax.swing.JFrame;

public class Snake extends JFrame implements ActionListener, KeyListener {
	
	private static final long serialVersionUID = -8164435299404436288L;
	public static Snake snake; 
	public RenderPanel renderPanel;
	public Timer timer = new Timer(20, this);
	public ArrayList<Point> snakeParts = new ArrayList<Point>();
	public int ticks = 0, direction = DOWN, score, BodyLength = 10;
	public static final int UP = 0, DOWN = 1, LEFT = 2, RIGHT = 3, SCALE = 10; 
	public Point head, food;
	public Random random; 
	public boolean over = false, paused;
	public Dimension dim; 
	
    public Snake() {
		dim = Toolkit.getDefaultToolkit().getScreenSize();
		setTitle("Snake"); 
		setSize(605, 629);
		setResizable(false);
		setLocation(dim.width / 2 - getWidth() / 2, dim.height
				/ 2 - getHeight() / 2 );
		add(renderPanel = new RenderPanel(this));
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		addKeyListener(this);

		startGame();
	}
    
	public void startGame() {
		over = false;
	    paused = false;
	    score = 0;
		BodyLength = 2;
		ticks = 0;
		direction = DOWN;
		head = new Point(15, 15);
		random = new Random();
		snakeParts.clear();
		food = new Point(random.nextInt(59), random.nextInt(59));
		timer.start();
	}
	@Override
	public void actionPerformed(ActionEvent arg0) {
		renderPanel.repaint();
		ticks++;
		if (ticks % 5 == 0 && head != null && !over && !paused){
			snakeParts.add(new Point(head.x, head.y));	
			if (direction == LEFT)
			if (head.x - 1 >= 0 && noTailAt(head.x - 1, head.y))
					head = new Point(head.x - 1, head.y);
				else
					over = true;
		if (direction == RIGHT)
				if (head.x + 1 < 59 && noTailAt(head.x + 1, head.y))
				head = new Point(head.x + 1, head.y);
				else
					over = true;
			if (direction == UP)
			if (head.y - 1 >= 0 && noTailAt(head.x, head.y - 1))
					head = new Point(head.x, head.y - 1);
				else
				over = true;
			if (direction == DOWN)
				if (head.y + 1 < 59 && noTailAt(head.x, head.y + 1))
					head = new Point(head.x, head.y + 1);
				else
					over = true;	
			if (snakeParts.size() > BodyLength)
				snakeParts.remove(0);			
		if (food != null)	{
			if (head.equals(food)){
				score += 2;
					BodyLength++;
					food.setLocation(random.nextInt(59),random.nextInt(59));
				}
			}
		}
	}

	public boolean noTailAt(int x, int y) {
		for (Point point : snakeParts){
			if (point.equals(new Point(x, y))){
				return false;
			}
		}
		return true;
	}
	
	@Override
	public void keyPressed(KeyEvent e) {
		int i = e.getKeyCode();
	if (i == KeyEvent.VK_LEFT && direction != RIGHT)
			direction = LEFT;
		if (i == KeyEvent.VK_RIGHT && direction != LEFT)
			direction = RIGHT;
		if (i == KeyEvent.VK_UP && direction != DOWN)
			direction = UP;
	if (i == KeyEvent.VK_DOWN && direction != UP)
			direction = DOWN;
		if (i == KeyEvent.VK_SPACE)
			if (over)
			startGame();
		else
			paused = !paused;
	}

	@Override
	public void keyReleased(KeyEvent e) {}
	
	@Override
	public void keyTyped(KeyEvent e) {}
}
```

Wenn du eine E-Mail hast, kann ich dir das auch per zip schicken und verbessere nebenbei noch etwas.


----------



## Gucky (27. Dez 2014)

@ebenich
Übersetze die Fehlermeldung ins Deutsche und du wirst einen großen Schritt weiter sein.


----------

