intro Java Spiel 8_vasabii_Fotolia_70882828

Java Spiel Programmieren Tutorial – Teil 8: Einen Einstellungsdialog erstellen


Nun wünschen wir euch viel Spaß beim achten Teil unseres Java Spiel Programmieren Tutorials. Los geht’s!

1. Vorbereitung des Quellcodes für den Dialog

Android Apps Programmieren Online-Kurs

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

Wir werden nun einige Änderungen an den Klassen GamePanel und GameWindow vornehmen.

Mit diesen Quellcodeänderungen bereiten wir unser Java Spiel für den Einstellungsdialog vor. Über diesen Dialog wird es später möglich sein, die Farben des Panzerturms und der Kanone des Spielerpanzers auszuwählen.

Die notwendigen Änderungen sind nicht sehr umfangreich und erstrecken sich über die folgenden Arbeitsschritte:

  1. Einfügen der getPlayersTank() Methode in die GamePanel-Klasse – Über die öffentliche Methode getPlayersTank() können wir von außen auf den Spielerpanzer zugreifen. Dies ist notwendig, um die Farben des Panzers über den Dialog ändern zu können.
  2. Anlegen des Menüeintrags des Einstellungsdialogs in der GameWindow-Klasse – In dem Spielfenster legen wir einen weiteren Menüeintrag an, über den wir später den Einstellungsdialog aufrufen werden.

Das sind alle notwendigen Änderungen, um unser Spiel auf den Einstellungsdialog vorzubereiten. Beginnen wir nun mit dem ersten Arbeitsschritt.


1.1 Einfügen der getPlayersTank() Methode in die GamePanel-Klasse

Der erste Schritt ist schnell gemacht. Wir öffnen zunächst die Klassendatei GamePanel.java im Editorfenster der NetBeans IDE. Anschließend fügen wir in den Methodenbereich der GamePanel-Klasse die folgenden markierten Zeilen ein:

GamePanel.java

.
.
.

public class GamePanel extends JPanel{
    
    public static final String IMAGE_DIR = "images/";
    
    private final Dimension prefSize = new Dimension(1180, 780);
    
    private ImageIcon backgroundImage;
    private final String[] backgroundImages= new String [] {"bg_mud.jpg", 
                                                            "bg_snow.jpg", 
                                                            "bg_sand.jpg"};
    
    private boolean gameOver = false;
    private int tanksDestroyedCounter = 0;
    
    private Timer t;  
    
    private Tank playersTank = null;
    private EnemyTank enemyTank = null;
    
    private List<Missile> missiles;  
    
    
    public GamePanel() {        
        setFocusable(true);
        setPreferredSize(prefSize);
        
        initGame();         
        startGame();
    }

    public Tank getPlayersTank() {
        return playersTank;
    }

.
.
.

Im oberen Quellcode ist die neu eingefügte Methode getPlayersTank() markiert. Sie liefert das Tank-Objekt, welches den Spielerpanzer repräsentiert, als Rückgabewert zurück. Wir benötigen dieses Objekt später, um die Farben des Spielerpanzers von außerhalb ändern zu können.

In NetBeans sollte der geänderte Bereich der Klasse GamePanel nun wie folgt aussehen:

java spiel vorbereitung gamepanel

Der Quellcode der Klasse GamePanel mit der vorgenommenen Änderung

Die vorgenommene Änderung ist in der oberen Abbildung mit einem blauen Rahmen (A) markiert worden.

Da keine weiteren Änderungen an der GamePanel-Klasse vorgenommen werden müssen, können wir nun mit dem nächsten Arbeitsschritt beginnen.

1.2 Den Menüeintrag des Dialogs in der GameWindow-Klasse anlegen

Auch der zweite Schritt ist sehr einfach. Wir öffnen zuerst die Klassendatei GameWindow.java im Editorfenster der NetBeans IDE. Anschließend fügen wir in die Methode addPrefMenuItems() der GameWindow-Klasse die folgenden markierten Zeilen ein:

GameWindow.java

.
.
.

    private void addPrefMenuItems(JMenu prefMenu) {
        
        JMenuItem changeColorItem = new JMenuItem("Change Tank's Colors...");
        prefMenu.add(changeColorItem);
       
        changeColorItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                
                panzerGamePanel.getPlayersTank().setTurretColor(java.awt.Color.YELLOW);
                
            }
        });
        
        JMenu submenu = new JMenu("Choose Background");
        prefMenu.add(submenu);

        JMenuItem menuItem = new JMenuItem("Mud Area");
        submenu.add(menuItem);
        menuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panzerGamePanel.setBackgroundImage(0);
                repaint();
            }
        });

        menuItem = new JMenuItem("Snow Area");
        submenu.add(menuItem);
        menuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panzerGamePanel.setBackgroundImage(1);
                repaint();
            }
        });
        
        menuItem = new JMenuItem("Desert Area");
        submenu.add(menuItem);
        menuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panzerGamePanel.setBackgroundImage(2);
                repaint();
            }
        });
    }

.
.
.

Mit den eingefügten Zeilen 7 bis 17 legen wir einen neuen Menüeintrag in dem Preferences-Menü an. Der neue Menüeintrag trägt die Bezeichnung Change Tank’s Colors… und über ihn soll später der Einstellungsdialog geöffnet werden.

Zu Testzwecken haben wir den ActionListener des Menüeintrags mit einer Test-Anweisung ausprogrammiert, durch welche die Farbe des Panzerturms des Spielerpanzers geändert wird. Weitere Änderungen haben wir nicht an der Klasse GameWindow vorgenommen.

In NetBeans sollte die GameWindow-Klasse nun wie folgt aussehen:

java spiel vorbereitung gamewindow

Der Quellcode der Klasse GameWindow mit der vorgenommenen Änderung

Die vorgenommene Änderung an der GameWindow-Klasse ist in der oberen Abbildung mit einem blauen Rahmen (A) markiert worden.

Wir haben nun die Vorbereitungen abgeschlossen und können mit dem Implementieren des Einstellungsdialogs beginnen. Bevor wir dies jedoch in Angriff nehmen, werden wir die bisher vorgenommenen Änderungen erste einmal testen.

Dazu führen wir im nächsten Unterabschnitt unser Java Spiel in NetBeans aus.

1.3 Testen des angelegten Menüeintrags

Wir führen nun unser Java Projekt mit einem Klick auf das Run Project-Symbol aus.

java spiel entwickeln projekt starten

Starten unseres Java Projekts über den Run Projekt Button

Im Hintergrund wird jetzt unser Java Spiel von der NetBeans IDE erstellt und anschließend ausgeführt.

Wir prüfen nun, ob unsere Änderungen am Quellcode korrekt durchgeführt wurden. Dazu klicken wir mit der linken Maustaste auf den Menüeintrag Preferences in der oberen Menüleiste des Spielfensters. Anschließend klicken wir auf den ersten Eintrag: Change Tank’s Colors… in dem sich öffnenden Untermenü.

Nun sollte sich die Farbe des Panzerturms von Grün auf Gelb geändert haben.

java spiel change turret color

Das Spielfenster unseres Java Spiels. Wir haben testweise die Farbe des Panzerturms geändert.

In der oberen Abbildung ist der neue Menüeintrag Change Tank’s Colors… des Preferences-Menüs zu sehen. Wir haben bereits einmal auf diesen mit der linken Maustaste geklickt, daher erscheint der Panzerturm nun in der Farbe Gelb.

Da die Farbe des Panzerturms wie erwartet geändert wurde, sind alle Vorbereitungen abgeschlossen und wir können nun mit dem Implementieren des Einstellungsdialogs beginnen.

2. Den Einstellungsdialog unseres Java Spiels einrichten

Um den Einstellungsdialog zu implementieren müssen wir einige Arbeitsschritte durchführen. Die Hauptarbeit haben wir auf dieses und das nächste Kapitel aufgeteilt.

In diesem Kapitel werden wir den Einstellungsdialog einrichten. Im nächsten Kapitel werden wir den Dialog dann fertigstellen.

Durch diese Vorgehensweise soll sichergestellt werden, dass wir nicht zu viel Quellcode auf einmal einfügen müssen und so die Übersichtlichkeit erhalten bleibt.

plhq_teaser_hbox_gelb_fotolia_RA Studio_46292813

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

Wir werden nun den Einstellungsdialog einrichten und dazu die folgenden Arbeitsschritte durchführen:

  1. Erstellen der TankPreviewPanel-Klasse – Zuerst werden wie eine neue Klasse in NetBeans anlegen. Mit Hilfe der TankPreviewPanel-Klasse werden wir eine Vorschau des Spielerpanzers anzeigen lassen, damit man direkt feststellen kann, ob die ausgewählten Farben den Vorstellungen entsprechen.
  2. Erstellen der ChooseTankColorDialog-Klasse – Danach werden wir die Klasse ChooseTankColorDialog anlegen und das Grundgerüst des Dialogs darin definieren. Mit Hilfe dieser Klasse werden wir später die Farben des Spielerpanzers ändern.
  3. Anpassen der GameWindow-Klasse – Damit der Einstellungsdialog angezeigt wird, müssen wir einige Anpassungen an der GameWindow-Klasse vornehmen.
  4. Testen des Grundgerüsts des Einstellungsdialogs – Als letzten Schritt starten wir unser Java Spiel und testen das Grundgerüst des Einstellungsdialogs.

Beginnen wir nun mit dem ersten Arbeitsschritt, dem Erstellen der Panzervorschau-Zeichenfläche.

2.1 Erstellen der TankPreviewPanel-Klasse

Wir werden nun eine weitere Klasse unserem Java Projekt hinzufügen. Die neue Klasse wird den Namen TankPreviewPanel tragen und die Zeichenfläche für die Vorschau des Spielerpanzers realisieren.

Die Klasse TankPreviewPanel legen wir wie folgt an:

  1. Wir klicken mit der rechten Maustaste auf den Haupt-Packagenamen in der Projektleiste.
  2. Danach auf den New-Eintrag im Kontextmenü klicken.
  3. Anschließend auf den Eintrag Java Class... klicken.
java spiel class tankpreviewpanel create

Eine neue Klasse unserem Java Projekt in NetBeans hinzufügen

Daraufhin öffnet sich der New Java Class-Dialog von NetBeans. In diesem Dialog geben wir als Namen der zu erstellenden Klasse TankPreviewPanel ein.

Alle anderen Einstellungen lassen wir unverändert und bestätigen den Dialog mit einem Klick auf Finish.

java spiel class tankpreviewpanel dialog

Der New Java Class Dialog von NetBeans

Jetzt generiert NetBeans eine neue Java-Datei mit dem Namen TankPreviewPanel.java und fügt sie in das Hauptpaket unseres Java Projekts ein. Dies sollte bei euch wie folgt aussehen:

java spiel class tankpreviewpanel start

Die neu erstellte Java Klasse TankPreviewPanel – Durch sie realisieren wir die Zeichenfläche für die Panzervorschau

Die neue Klasse TankPreviewPanel ist momentan noch leer. Wir werden sie nun mit dem folgenden Quellcode füllen:

TankPreviewPanel.java

package de.programmierenlernenhq.panzerhq;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JPanel;

public class TankPreviewPanel extends JPanel{

    private final Tank playersTank;
    
    private final int panelWidth;
    private final int panelHeight;    
    private final int tankWidth;
    private final int tankHeight;
    
    public TankPreviewPanel (Tank tank) {
               
        this.playersTank = tank;
        
        tankWidth  = (int)playersTank.getWidth();
        tankHeight = (int)playersTank.getHeight();
        
        panelWidth  = tankWidth * 4;
        panelHeight = tankHeight * 3;
        
        setPreferredSize(new Dimension(panelWidth, panelHeight)); 
    }
    
    @Override
    protected void paintComponent(Graphics g) {        
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, panelWidth-1, panelHeight-1);
        
        g.setColor(Color.DARK_GRAY);
        g.drawRect(0, 0, panelWidth-1, panelHeight-1);        
                
        int tankPosX = (int)playersTank.getObjectPosition().getX();
        int tankPosY = (int)playersTank.getObjectPosition().getY();
                
        g.translate(panelWidth/2 - tankWidth/2 - tankPosX, panelHeight/2 - tankHeight/2 - tankPosY); 
        playersTank.setPaintTankStatusBar(false);
        playersTank.paintMe(g);
        playersTank.setPaintTankStatusBar(true);
    }
}

Die neue Klasse TankPreviewPanel leiten wir, in Zeile 10 von der Klasse JPanel ab. Daher trägt sie auch die Bezeichnung Panel in ihrem Klassennamen.

In dem Konstruktor der neuen Klasse, mit den Zeilen 19 bis 30, initialisieren wir die fünf Membervariablen und legen die bevorzugten Maße der Zeichenfläche fest.

Anschließend zeichnen wir mit Hilfe der paintComponent() Methode, in den Zeilen 33 bis 50, die Vorschau des Spielerpanzers. Der Panzer wird auf einem weißen Hintergrund dargestellt, welcher von einem dunkelgrauen Rahmen umschlossen ist.

Damit der Spielerpanzer in der Mitte der Zeichenfläche dargestellt wird, müssen wir eine Koordinatenverschiebung durchführen lassen. Wir benutzen dafür die Methode translate(), die wir auf dem Graphics-Objekt in der Zeile 46 aufrufen.

Anschließend deaktivieren wir die Darstellung der Statusbalken des Spielerpanzers und lassen den Panzer zeichnen. Danach aktivieren wir die Statusbalken wieder.

In NetBeans sollte die TankPreviewPanel-Klasse nun wie folgt aussehen:

java spiel klasse tankpreviewpanel

Die neu erstellte Klasse TankPreviewPanel – Sie ist die Zeichenfläche für die Panzervorschau

Wir können die TankPreviewPanel-Klasse zum jetzigen Zeitpunkt nicht testen. Dies werden wir bald nachholen, jedoch müssen wir vorher das Grundgerüst des Einstellungsdialogs anlegen, in welchem die Panzervorschau eingebunden wird. Daher werden wir als Nächstes die ChooseTankColorDialog-Klasse in NetBeans erstellen.

2.2 Erstellen der ChooseTankColorDialog-Klasse

Die Vorschau des Spielerpanzers soll in dem Einstellungsdialog direkt angezeigt werden. Wir werden nun das Grundgerüst dieses Dialogs erstellen und dabei auch die Panzervorschau mit einbinden.

Dazu werden wir nun eine weitere Klasse unserem Java Projekt hinzufügen. Die neue Klasse wird den Namen ChooseTankColorDialog tragen und den Einstellungsdialog unseres Java Spiels realisieren.

Die Klasse ChooseTankColorDialog legen wir wie folgt an:

  1. Wir klicken mit der rechten Maustaste auf den Haupt-Packagenamen in der Projektleiste.
  2. Danach auf den New-Eintrag im Kontextmenü klicken.
  3. Anschließend auf den Eintrag Java Class... klicken.
java spiel class choosetankcolordialog create

Eine neue Klasse unserem Java Projekt in NetBeans hinzufügen

Daraufhin öffnet sich der New Java Class-Dialog von NetBeans. In diesem Dialog geben wir als Namen der zu erstellenden Klasse ChooseTankColorDialog ein.

Alle anderen Einstellungen lassen wir unverändert und bestätigen den Dialog mit einem Klick auf Finish.

java spiel class choosetankcolordialog name

Der New Java Class Dialog von NetBeans

Jetzt generiert NetBeans eine neue Java-Datei mit dem Namen ChooseTankColorDialog.java und fügt sie in das Hauptpaket unseres Java Projekts ein. Dies sollte bei euch wie folgt aussehen:

java spiel class choosetankcolordialog start

Die neu erstellte Java Klasse ChooseTankColorDialog – Durch sie realisieren wir den Einstellungsdialog

Die neue Klasse ChooseTankColorDialog ist momentan noch leer. Wir werden sie nun mit dem folgenden Quellcode füllen:

ChooseTankColorDialog.java

package de.programmierenlernenhq.panzerhq;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;

/**
 *
 * @author ProgrammierenLernenHQ
 */
public class ChooseTankColorDialog extends JDialog{
    
    private final GamePanel panzerGame;
    private final Tank playersTank;
    
    private final JPanel dialogPanel;
    
    private final JButton setTurretColorButton = new JButton("Set Turret Color...");
    private final JButton setCannonColorButton = new JButton("Set Cannon Color...");
    private final JButton cancelButton = new JButton("Cancel");
    private final JButton applyButton = new JButton("Apply");
    
    private Color oldTurretColor;
    private Color oldCannonColor;
    private Color tempTurretColor;
    private Color tempCannonColor;
    
    public ChooseTankColorDialog(Frame frame, GamePanel game) {
        super(frame);
        setTitle("Choose Your Tank's Colors");
        setModal(true);
        
        this.panzerGame = game;
        playersTank = panzerGame.getPlayersTank();
        
        dialogPanel = new JPanel();        
        dialogPanel.add(createPreviewPanel());
        dialogPanel.add(createButtonsPanel());        
        add(dialogPanel);
        
        registerButtonListeners();
        
        setPreferredSize(new Dimension(350,330));
    }    
    
    private JPanel createPreviewPanel() {
        JLabel titleLabel = new JLabel("Tank Preview");
        titleLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
        
        JPanel previewPanel = new JPanel();        
        previewPanel.setLayout(new BoxLayout(previewPanel, BoxLayout.Y_AXIS));
        previewPanel.add(Box.createRigidArea(new Dimension(0, 10)));
        previewPanel.add(titleLabel);
        previewPanel.add(Box.createRigidArea(new Dimension(0, 10)));
        previewPanel.add(new TankPreviewPanel(playersTank));
        
        return previewPanel;
    }
    
    private JPanel createButtonsPanel() {        
        // Hier erzeugen wir später das Panel, welches die Buttons enthält     
        
        return new JPanel();
    }
    
    private void registerButtonListeners() {
        // Hier registrieren wir später ActionListeners für die Buttons        
        
    }

}

Mit dem oberen Quellcode haben wir das Grundgerüst des Einstellungsdialogs gelegt. Einige Teile des Quellcodes werden momentan noch nicht verwendet. Sie dienen als Vorbereitung für das nächste Kapitel, in dem der Dialog dann komplett fertiggestellt wird.

Die neue Klasse ChooseTankColorDialog leiten wir in der Zeile 21 von der JDialog-Klasse der Java Swing-Bibliothek ab. In Java ist ein Dialogfenster ein unabhängiges Unterfenster eines Hauptfensters. In unserem Java Spiel Tutorial ist das Hauptfenster das GameWindow-Fenster.

Wir weisen unserem Dialog sein Hauptfenster mit der Anweisung super(frame); in Zeile 39 zu. Dabei enthält die Variable frame eine Referenz zu dem GameWindow-Objekt.

Mit der Anweisung in Zeile 40 legen wir den Titel unseres Dialogfensters fest. Anschließend folgt die Anweisung setModal(true); in Zeile 41, mit der wir den Benutzerfokus an das Dialogfenster binden.

Anschließend initialisieren wir die Membervariablen panzerGame und playersTank in den Zeilen 43 und 44, die wir später noch für das Ändern der Panzerfarben benötigen werden.

Die Zeichenfläche dialogPanel des Dialogs lassen wir mit Hilfe der Anweisungen in den Zeilen 46 bis 48 erzeugen. Sie besteht wiederum aus zwei inneren Zeichenflächen, der Panzervorschau und dem Buttons-Bereich. Diese Zeichenfläche fügen wir in Zeile 49 dem Dialogfenster hinzu.

Mit dem Methodenaufruf registerButtonListeners(); in Zeile 51 werden wir später die ActionListener für die vier Buttons unseres Einstellungsdialogs registrieren. Momentan ist diese Methode aber noch nicht ausprogrammiert, dies folgt im nächsten Kapitel.

Kommen wir nun zur createPreviewPanel() Methode in den Zeilen 56 bis 68, mit der wir die Zeichenfläche für die Panzervorschau erstellen. In dieser Methode lassen wir ein TankPreviewPanel-Objekt in Zeile 65 erzeugen, welches den Spielerpanzer im aktuellen Zustand darstellt, und fügen dieses dem previewPanel hinzu.

Die beiden Methoden createButtonsPanel() und registerButtonListeners() sind aktuell noch nicht ausprogrammiert. Dies werden wir nachholen, wenn wir später den Einstellungsdialog fertigstellen. Vorher möchten wir jedoch den bisherigen Quellcode erst einmal testen.

Weitere Informationen über das Thema Dialoge in Java könnt ihr an folgenden Stellen finden:

In NetBeans sollte die ChooseTankColorDialog-Klasse nun wie folgt aussehen:

java spiel class choosetankcolordialog

Die neu erstellte Klasse ChooseTankColorDialog – Wir haben nun das Grundgerüst des Dialogs implementiert

Wir haben das Grundgerüst des Einstellungsdialogs nun angelegt. Um den Dialog testen zu können, müssen wir aber noch einige Anpassungen an der GameWindow-Klasse vornehmen. Dies werden wir im nächsten Arbeitsschritt durchführen.

2.3 Anpassen der GameWindow-Klasse

Wir werden nun die folgenden drei Anpassungen an der GameWindow-Klasse vornehmen, damit wir den Einstellungsdialog über den Menüeintrag Change Tank’s Colors… des Preferences-Menüs starten können:

  1. Einfügen der Membervariable chooseTankColorDialog.
  2. Initialisieren der neuen Membervariable im Konstruktor der GameWindow-Klasse.
  3. Aufrufen des Einstellungsdialogs durch den ActionListeners des Menüeintrag Change Tank’s Colors….

Um die Änderungen durchzuführen, öffnen wir nun die Klassendatei GameWindow.java im Editorfenster der NetBeans IDE. Anschließend nehmen wir die markierten Änderungen an der GameWindow-Klasse vor:

GameWindow.java

package de.programmierenlernenhq.panzerhq;

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;

import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;

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

/**
 *
 * @author ProgrammierenLernenHQ
 */
public class GameWindow extends JFrame{
    
    private final GamePanel panzerGamePanel;    
    private final ChooseTankColorDialog chooseTankColorDialog;
    
    public GameWindow() {   
        
        this.panzerGamePanel = new GamePanel();        
        chooseTankColorDialog  = new ChooseTankColorDialog(this, panzerGamePanel);
                
        registerWindowListener();
        createMenu();
          
        add(panzerGamePanel);
        pack();
        
        setTitle("PanzerHQ");
        setLocation(10, 10);
        setResizable(false);
        
        setVisible(true);
    }
    
    private void registerWindowListener() {        
        addWindowListener(new WindowAdapter() {            
            @Override
            public void windowClosing(WindowEvent e) { 
                System.exit(0); 
            }
            @Override
            public void windowDeactivated(WindowEvent e) {
                // hier wird das Spiel pausiert
                panzerGamePanel.pauseGame();
            }
            @Override
            public void windowActivated(WindowEvent e) {
                // hier wird das Spiel wieder fortgesetzt
                panzerGamePanel.continueGame();
            }            
        });        
    }
    
    private void createMenu() {
        
        JMenuBar menuBar = new JMenuBar();
        this.setJMenuBar(menuBar);
        
        JMenu fileMenu = new JMenu("File");
        JMenu gameMenu = new JMenu("Game");
        JMenu prefMenu = new JMenu("Preferences");
        
        menuBar.add(fileMenu);        
        menuBar.add(gameMenu);        
        menuBar.add(prefMenu);
        
        addFileMenuItems(fileMenu);  
        addGameMenuItems(gameMenu);
        addPrefMenuItems(prefMenu);
    }
    
    private void addFileMenuItems(JMenu fileMenu) {
        
        JMenuItem quitItem = new JMenuItem("Quit");
        fileMenu.add(quitItem);
        quitItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        }); 
    }
    
    private void addGameMenuItems(JMenu gameMenu) {
        JMenuItem pauseItem = new JMenuItem("Pause");
        gameMenu.add(pauseItem);        
        pauseItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panzerGamePanel.pauseGame();
            }
        });
        
        JMenuItem continuetItem = new JMenuItem("Continue");
        gameMenu.add(continuetItem);       
        continuetItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {                
                panzerGamePanel.continueGame();
            }
        });
        
        gameMenu.addSeparator();
        JMenuItem restartItem = new JMenuItem("Restart");
        gameMenu.add(restartItem);       
        restartItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {                
                panzerGamePanel.restartGame();
            }
        });
    }
    
    private void addPrefMenuItems(JMenu prefMenu) {
        
        JMenuItem changeColorItem = new JMenuItem("Change Tank's Colors...");
        prefMenu.add(changeColorItem);
       
        changeColorItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                
                //panzerGamePanel.getPlayersTank().setTurretColor(java.awt.Color.YELLOW);
                
                panzerGamePanel.pauseGame();
                chooseTankColorDialog.pack();
                chooseTankColorDialog.setLocation(300, 200);
                chooseTankColorDialog.setVisible(true);
                
            }
        });
        
        JMenu submenu = new JMenu("Choose Background");
        prefMenu.add(submenu);

        JMenuItem menuItem = new JMenuItem("Mud Area");
        submenu.add(menuItem);
        menuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panzerGamePanel.setBackgroundImage(0);
                repaint();
            }
        });

        menuItem = new JMenuItem("Snow Area");
        submenu.add(menuItem);
        menuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panzerGamePanel.setBackgroundImage(1);
                repaint();
            }
        });
        
        menuItem = new JMenuItem("Desert Area");
        submenu.add(menuItem);
        menuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panzerGamePanel.setBackgroundImage(2);
                repaint();
            }
        });
    }
    
}

Mit den Anweisungen in den Zeilen 23 und 28 deklarieren und initialisieren wir die neue Membervariable chooseTankColorDialog.

Anschließend kommentieren wir den Test-Quellcode in Zeile 131 aus, da wir ihn nun nicht mehr benötigen. Stattdessen fügen wir vier neue Anweisungen in den Zeilen 133 bis 136 ein.

Mit den neuen Anweisungen lassen wir unser Java Spiel pausieren und den neuen Einstellungsdialog chooseTankColorDialog an der Bildschirmposition (300, 200) öffnen.

In NetBeans sollte die GameWindow-Klasse nun wie folgt aussehen:

java spiel class gamewindow end

Der Quellcode der Klasse GameWindow mit allen vorgenommenen Änderungen

In der oberen Abbildung haben wir die drei vorgenommenen Änderungen blau markiert:

  • A: Deklarieren der neuen Membervariable
  • B: Initialisieren der neuen Membervariable
  • C: Aufrufen des Einstellungsdialogs unseres Java Spiels

Das waren alle vorzunehmenden Änderungen. Wir können nun den Einstellungsdialog testen. Dazu werden wir als Nächstes unser Java Spiel in NetBeans ausführen.

2.4 Das Grundgerüst des Einstellungsdialogs testen

Wir führen nun unser Java Projekt mit einem Klick auf das Run Project-Symbol aus.

java spiel entwickeln projekt starten

Starten unseres Java Projekts über den Run Projekt Button

Im Hintergrund wird jetzt unser Java Spiel von der NetBeans IDE erstellt und anschließend ausgeführt.

Wir prüfen nun, ob die Vorschau des Spielerpanzers korrekt in dem Einstellungsdialog angezeigt wird. Dazu klicken wir mit der linken Maustaste auf den Menüeintrag Preferences in der oberen Menüleiste des Spielfensters. Anschließend klicken wir auf den ersten Eintrag: Change Tank’s Colors… in dem sich öffnenden Untermenü.

Nun sollte sich der neue Einstellungsdialog geöffnet haben und eine Vorschau des Spielerpanzer darin angezeigt werden:

java spiel tankcolordialog

Das Grundgerüst des Einstellungsdialog

In der oberen Abbildung ist das Grundgerüst des Einstellungsdialogs zu sehen. In dem Dialog wird bereits die Vorschau des Spielerpanzers dargestellt.

Im nächsten Kapitel werden wir den Quellcode des Einstellungsdialogs vervollständigen und ein Buttons-Panel in den Dialog einfügen.

3. Den Einstellungsdialog unseres Java Spiels fertigstellen

Da die Vorschau des Spielerpanzers korrekt im Einstellungsdialog angezeigt wurde, können wir nun zur Fertigstellung des Dialogs kommen.

Dem Dialog müssen noch das Buttons-Panel und einige ActionListeners hinzugefügt werden.

Dies wird mit Hilfe der beiden Methoden createButtonsPanel() und registerButtonListeners() erfolgen. Beide Methoden sind bereits im Grundgerüst des Einstellungsdialogs deklariert und müssen nur noch von uns ausprogrammiert werden.

plhq_teaser_hbox_gelb_fotolia_RA Studio_46292813

Unser großes
Android Online-Kurs
Gesamtpaket



Weitere Infos

Wir öffnen nun die Klassendatei ChooseTankColorDialog.java im Editorfenster der NetBeans IDE. Anschließend programmieren wir die beiden Methoden createButtonsPanel() und registerButtonListeners() mit dem folgenden markierten Quellcode aus:

ChooseTankColorDialog.java

.
.
.

    private JPanel createButtonsPanel() {        
        // Hier erzeugen wir das Panel, welches die Buttons enthält     
        JPanel colorButtonsPanel = new JPanel();
        colorButtonsPanel.add(setTurretColorButton);
        colorButtonsPanel.add(setCannonColorButton);
        
        JPanel mainButtonsPanel = new JPanel();
        mainButtonsPanel.add(cancelButton);
        mainButtonsPanel.add(applyButton);
        
        JPanel buttonsPanel = new JPanel();
        buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.Y_AXIS));
        buttonsPanel.add(colorButtonsPanel);
        buttonsPanel.add(Box.createRigidArea(new Dimension(0, 30)));
        buttonsPanel.add(new JSeparator());
        buttonsPanel.add(mainButtonsPanel);
        
        return buttonsPanel;
    }
    
    private void registerButtonListeners() {
        // Hier registrieren wir ActionListeners für die Buttons        
        oldTurretColor = playersTank.getTurretColor();  
        tempTurretColor = oldTurretColor;
        
        oldCannonColor = playersTank.getCannonColor();
        tempCannonColor = oldCannonColor;
        
        setTurretColorButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {                               
                Color newTurretColor = JColorChooser.showDialog(null, "Choose Turret Color", tempTurretColor);
                if (newTurretColor != null) {     
                    tempTurretColor = newTurretColor;
                    playersTank.setTurretColor(newTurretColor);
                    dialogPanel.repaint();
                }
            }
        });
        
        setCannonColorButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {                               
                Color newCannonColor = JColorChooser.showDialog(null, "Choose Cannon Color", tempCannonColor);
                if (newCannonColor != null) { 
                    tempCannonColor = newCannonColor;
                    playersTank.setCannonColor(newCannonColor);
                    dialogPanel.repaint();
                }
            }
        });
        
        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) { 
                playersTank.setTurretColor(oldTurretColor);
                playersTank.setCannonColor(oldCannonColor);
                
                tempTurretColor = oldTurretColor;
                tempCannonColor = oldCannonColor;
                
                panzerGame.continueGame();
                setVisible(false);
            }
        });
        
        applyButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                oldTurretColor = playersTank.getTurretColor();
                oldCannonColor = playersTank.getCannonColor();
                
                panzerGame.repaint();
                panzerGame.continueGame();                
                setVisible(false);
            }
        });
    }

.
.
.

Wir werden nun den oberen Quellcode kurz besprechen. Vieles davon ist selbsterklärend bzw. wurde bereits in vorherigen Lektionen angewandt.

Die createButtonsPanel() Methode

Mit der ersten Methode createButtonsPanel() erzeugen wie ein JPanel-Objekt, das zwei JPanel-Objekte in sich aufgenommen hat. In den beiden inneren JPanels sind die vier folgenden Buttons angeordnet:

  • setTurretColorButton – Zur Auswahl der Farbe des Panzerturms.
  • setCannonColorButton – Zur Auswahl der Farbe der Kanone des Spielerpanzers.
  • cancelButton – Alle Änderungen verwerfen und den Dialog abbrechen.
  • applyButton – Alle Änderungen übernehmen und den Dialog schließen.

Die inneren JPanels lassen wir mit der Anweisung in Zeile 16 vertikal im äußeren JPanel anordnen. Die inneren JPanels sind durch eine Trennlinie, Zeile 19, voneinander separiert.

Mit der return-Anweisung in Zeile 22 übergeben wir das erzeugte, äußere JPanel-Objekt schließlich an die aufrufende Methode.

Die registerButtonListeners() Methode

Mit der zweiten Methode registerButtonListeners() registrieren wir ActionListeners für die vier Buttons unseres Einstellungsdialogs. Dadurch können wir Benutzereingaben erfassen und entsprechen auf sie reagieren.

Die Listener registrieren wir mit Hilfe anonymer innerer Klassen, welche die Methode actionPerformed() des ActionListener-Interface implementieren. In dieser Methode platzieren wir jeweils die Anweisungen, um auf Klicks entsprechend zu reagieren.

Die gewünschten Farben lassen wir mit Hilfe eines JColorChooser auswählen. Ein JColorChooser ist eine grafische Komponente, durch die Farben komfortabel mit Hilfe verschiedene Farbpaletten ausgewählt werden können.

Weitere Informationen über den JColorChooser könnt ihr an folgenden Stellen finden:

In NetBeans sollte die ChooseTankColorDialog-Klasse nun wie folgt aussehen:

java spiel class choosetankcolordialog end

Die vorher erstellte Klasse ChooseTankColorDialog – Wir haben nun den Dialog fertiggestellt

Die beiden vorgenommenen Änderungen an der ChooseTankColorDialog-Klasse haben wir in der oberen Abbildung blau markiert. Es wurden folgende Änderungen vorgenommen:

  • A: Implementieren der createButtonsPanel() Methode
  • B: Implementieren der registerButtonListeners() Methode

Somit haben wir die Programmierung des Einstellungsdialogs abgeschlossen und sind somit auch fast am Ende dieser Lektion angelangt.

3.1 Die Klassendateien unseres Java Projekts zum Download

Unser Java Spiel ist nun schon etwas komplexer und besteht aus insgesamt 10 Klassen. Damit es nicht zu Missverständnissen kommt, haben wir unten alle Klassendateien zum Download bereitgestellt.

Ihr solltet noch einmal in Ruhe den kompletten Quellcode der aufgelisteten Klassendateien unseres Java Spiels anschauen und mit eurem vergleichen:

PanzerHQ.java
GameWindow.java
GamePanel.java
Coordinate.java
GameObject.java
Missile.java
Tank.java
EnemyTank.java
TankPreviewPanel.java
ChooseTankColorDialog.java

Als Nächstes werden wir unser Java Spiel starten und den Einstellungsdialog testen.

3.2 Testen des Einstellungsdialogs unseres Java Spiels

Wir führen nun unser Java Projekt mit einem Klick auf das Run Project-Symbol aus.

java spiel entwickeln projekt starten

Starten unseres Java Projekts über den Run Projekt Button

Im Hintergrund wird jetzt unser Java Spiel von der NetBeans IDE erstellt und anschließend ausgeführt.

Wir prüfen nun, ob der Einstellungsdialog korrekt funktioniert. Dazu klicken wir mit der linken Maustaste auf den Menüeintrag Preferences in der oberen Menüleiste des Spielfensters. Anschließend klicken wir auf den ersten Eintrag: Change Tank’s Colors… in dem sich öffnenden Untermenü.

Nun sollte sich der neue Einstellungsdialog geöffnet haben und eine Vorschau des Spielerpanzer zusammen mit den vier Buttons angezeigt werden:

java spiel tankcolordialog end

Der Einstellungsdialog unseres Java Spiels

Mit den beiden oberen Buttons können die Farben des Spielerpanzers angepasst werden. Mit den unteren Buttons können die Änderungen verworfen bzw. übernommen werden.

Wir der Set Turret Color...-Button angeklickt, dann öffnet sich der JColorChooser-Dialog, über den die Turmfarbe des Spielerpanzers ausgewählt werden kann.

java spiel tankcolordialog chooser

Der JColorChooser-Dialog über den die Panzerfarben ausgewählt werden können

Mit einem Klick auf den OK-Button wird die neue Panzerfarbe zwischengespeichert und in der Vorschau angezeigt. Durch Klicken des Apply-Button des Einstellungsdialogs werden die ausgewählten Farben übernommen und der Spielerpanzer entsprechend im Spiel gefärbt.

java spiel change color

Das Spielfenster unseres Java Spiels – Die Farben von Turm und Kanone des Spielerpanzers wurden geändert

In der oberen Abbildung wurden die Farben des Turms und der Kanone des Spielerpanzers gerade geändert. Über den neuen Einstellungsdialog kann nun jeder Spieler seinen Panzer nach seinen eigenen Vorstellungen färben.

3.3 Video – Funktionspräsentation unseres Java Spiels

In dem unteren Video ist das Spielfenster unseres selbst programmierten Java Spiels zu sehen. Wir sind in der Lage den Spielerpanzer selbst über die Spielfläche zu steuern. Auch die verbesserte Kollisionsabfrage ist jetzt implementiert, mit deren Hilfe wir Panzerabschüsse exakter erkennen können, sowie die Spiellogik unseres Java Spiels.

Neu hinzugekommen ist der Einstellungsdialog, über den die Farben des Panzerturms und der Kanone geändert werden können.

Die neue Funktion unseres Java Spiels haben wir im unteren Video vorgeführt:

In dem oberen Video haben wir ein kleine Partie PanzerHQ gespielt. Zu Beginn öffnen wir den neuen Einstellungsdialog und wählen die Farben unseres Panzers aus. Anschließend nehmen wir den gegnerischen Panzer unter Beschuss.

In dem Video sind viele Funktionen unseres selbst programmierten Java Spiels zu sehen. Es ist natürlich noch kein vollständiges Spiel, aber dennoch schon sinnvoll spielbar. Ihr könnt es nun beliebig anpassen und erweitern.

Zusammenfassung

In der achten Lektion unseres Java Spiel Programmieren Tutorials haben wir den Einstellungsdialog programmiert. Über den Dialog können die Farben des Panzerturms und der Kanone des Spielerpanzers ausgewählt werden. Dabei wird den Spielern eine Vorschau des Spielerpanzers direkt im Dialog präsentiert.

Um diesen Einstellungsdialog zu realisieren, haben wir zunächst einige Vorbereitungen am Quellcode unseres Java Spiels treffen und eine kleine Erweiterung an der GamePanel-Klasse vornehmen müssen.

Anschließend haben wir eine zweite Zeichenfläche (JPanel) erstellt, auf der die Vorschau des Spielerpanzers dargestellt werden. Danach haben wir den Einstellungsdialog angelegt, über den die Farben des Spielerpanzers ausgewählt werden.

In diesem Dialog haben wir die neu erstellte Zeichenfläche als Tank Preview eingebunden, wodurch die Spieler sofort prüfen können, ob die gewählte Farbe ihren Vorstellungen entspricht.

Am Ende der achten Lektion unseres Java Spiel Programmieren Tutorials haben wir unser Java Spiel in NetBeans ausgeführt, um den neuen Einstellungsdialog ausgiebig zu testen.



Comments 14

  1. Hey Chris 🙂

    Ich möchte mich für dieses geniale Tutorial bedanken. Es ist für einen Anfänger wie mich sehr verständlich und bietet ausreichend „Aha“ Erlebnisse, um das Interesse am Programmieren generell noch zu steigern. Andere Tutorials haben manchmal den Effekt einen als Anfänger förmlich mit Informationen zu erschlagen, sodass man schnell das Interesse verliert.

    Nachdem ich das Spiel fertiggestellt habe, ist mir eine Kleinigkeit aufgefallen und ich bin mir nicht ganz sicher, ob mir hier ein Fehler unterlaufen ist oder das so gedacht ist. Der gegnerische Panzer bewegt sich nur bis zu einem gewissen Punkt und bleibt dann dauerhaft stehen, während er auf einen schießt. Ich habe mit den einzelnen Werten schon ein wenig rumgespielt, konnte dabei aber nur Dinge wie zum Beispiel die Geschwindigkeit anpassen. Der Panzer bleibt aber dennoch immer am gleichen Punkt stehen.

    Über dein Feedback dazu würde ich mich sehr freuen.

    LG
    Sebastian

    1. Post
      Author

      Hallo Sebastian,

      vielen Dank für dein tolles Feedback!

      Es ist in der Tat so vorgesehen, dass der Panzer dauerhaft stehen bleibt. Ich wollte den Quellcode nicht noch komplexer machen, da sich das Tutorial an Anfänger richtet. Für das Spiel wäre eine einfache Panzer KI jedoch sehr sinnvoll, vielleicht erweitere ich das Tutorial noch um eine Lektion, in der ich dem gegnerischen Panzer etwas Intelligenz spendiere.

      Viele Grüße,
      Chris

  2. Echt cooles Anschauungsbeispiel! Ich hatte bis jetzt nur in Zusammenarbeit mit einem Webendwicklungsbüro aus Berlin meine eigene Website erstellt, hatte also bis jetzt noch gar keine Erfahrung mit diesem Einsatzgebiet von Java.

    Jetzt kann ich auch das. Vielen Dank dafür!

    Wirst du auch mal erklären, wie man ein dreidimensionales Spiel entwickelt? Oder wird das zu schnell zu kompliziert?

    Beste Grüße
    Max

    1. Post
      Author

      Hallo Maximilian,

      danke für dein Lob! Ein 3D-Spiele Tutorial zu erstellen ist sehr interessant. Dies müsste dann wahrscheinlich ein Tutorial für fortgeschrittene Programmierer werden, da der Code schnell ziemlich komplex werden würde.

      Viele Grüße, Chris

  3. Hi

    Super Tutorial, hilft mir sehr. Leider hab ich aber ein Problem. Die Flugrichtung der Geschosse wird ja in einer Variable in der MissileObject Klasse gespeichert. Diese wird jedesmal wenn man schiesst mit den Werten des Geschosses „überschrieben“. Aus diesem Grund wechseln dann alle noch im Spiel fliegenden Kugeln auch in diese Richtung. Soll heissen alle Geschosse ändern ihre Flugrichtung auf die des neuesten Geschosses. Ist das ein Fehler im Code oder habe ich etwas „zerstört“ als ich den Code leicht angepasst habe?

    LG Patrick

    1. Hallo nochmal

      Scheint als hätte ich mir den Code zerschossen als ich ihn kopiert habe, war wohl unaufmerksam :D. Nun funktioniert alles wunderbar, nochmals vielen Dank für dieses tolle Tutorial.

      LG Patrick

    2. Post
      Author

      Hallo Patrick,

      gut, wenn es jetzt funktioniert. Und danke für dein Lob!

      Viele Grüße, Chris

  4. Vielen lieben Dank für das Tutorial. Hat mir geholfen Java etwas zu lernen und hat Spaß gemacht. Es ist toll die Ergebnisse zu sehen kurz nachdem der Quelltext geschrieben wurde.

    Im Allgemeinen wünsch ich mit aber oft das die Zeilen die geschrieben wurden in Bildern gezeigt und dort auch direkt zerlegt und erklärt werden. Kleinlichere Erklärungen die tiefer ins Detail gehen helfen Anfängern am besten Dinge zu verstehen. Das betrifft alle Tutorials und Lehrversuche. Dieses allerdings viel weniger als alle andere. (No offense 😉

    Aber es war ein super Tutorial mit guter Erklärung, ich bin sehr dankbar dafür.

    1. Post
      Author

      Hallo Meponu,

      danke für dein Lob und hilfreiches Feedback!

      Wir wären gerne mehr ins Detail gegangen, aber die Zeit hat dafür leider nicht gereicht. An einigen Stellen mussten wir schon stark kürzen, um nicht zu umfangreich zu werden. Komplexe Zusammenhänge können manchmal nicht kurz erklärt werden. Gerade Anfänge freuen sich über jede hilfreiche Bemerkung. Beim nächsten Tutorial werden wir lieber mehr Lektionen machen. Diese sind dann vom Inhalt etwas kürzer, dafür aber umfangreicher kommentiert.

      Viele Grüße, Chris

  5. Ist schon ordentlich Code, lohnt sich dafür aber, ich finde es ist eine gute Idee und ein cooles Projekt!

    1. Post
      Author
  6. Hallo!

    Klaaasssee Idee! Genau das, wonach ich schon so lange gesucht habe. 🙂
    Leider konnte ich kein Datum finden, an dem dieser Beitrag gepostet wurde. Könnt ihr mir vielleicht sagen in was für Abständen hier geupdatet wird?
    Ich schreibe im Juli eine Klausur und möchte dieses Tutorial auf jedenfall zur Vorbereitung nutzen; Wäre nur super wenn es dann schon vollständig wäre, oder ich ne Idee bekomme, wie weit wir hier sein werden in etwa.
    Nochmal – super gut, hab erstmal nur grob drüber geguckt, aber sieht echt hilfreich aus bis jetzt, danke! 🙂

    1. Post
      Author

      Hallo Tyael,

      danke für Dein Lob!

      Das Java Spiel Programmieren Tutorial besteht aus 8 Teilen und ist abgeschlossen. Viel Erfolg bei Deiner Klausur!

      Viele Grüße, Chris

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.