重新启动/重播Java游戏,而无需重新启动GUI [英] Restart/replay Java game without restarting the GUI

查看:75
本文介绍了重新启动/重播Java游戏,而无需重新启动GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为我的Java游戏添加重新启动/重播功能.当前在我的Game类(GUI和游戏被初始化的地方)中,我有:

I'm trying to add a restart/replay functionality to my Java game. Currently in my Game class (where the GUI and game gets initialized), I have:

init() method
Game() object

Game对象包含整个游戏窗口的GUI,并包含各种对象(例如实际游戏窗口,记分板,倒数计时器等).

The Game object contains the GUI for the whole game window, and includes various objects (such as the actual game window, score board, a countdown timer, etc).

我想添加一项功能,如果他们单击GUI上的重新启动按钮或游戏结束,游戏将重新启动(以及倒计时和计分).我确实意识到最好重新实例化对象(计分,倒数),但是一旦实例化,它们便成为我的GUI的一部分

I would like to add a functionality where the game would restart (along with the countdown and scoring) if they click the restart button on the GUI or once the game ends. I do realize that it's best to re-instantiate the objects (scoring, countdown), however once instantiated they're part of my GUI

i.e. add(scoreboard)

是否有一种方法可以重新实例化对象而不必重新实例化我的GUI?理想情况下,我只想重新实例化对象,而不必为GUI重新打开全新的JFrame.如果有人可以为我提供我应该拥有的类和方法(以及它们的用途)的概述,将不胜感激.

Is there a way to re-instantiate the objects without having to re-instantiate my GUI? Ideally I'd just like to re-instantiate the objects without having to re-open a completely new JFrame for the GUI. If someone could provide me with a sort of outline for the classes and methods I should have (and what they do), it'd be much appreciated.

谢谢!

推荐答案

从GUI(视图)中分离数据(模型).

Separate the data (model) from the GUI (view).

举个例子,您的计分板可能是一个JTable.JTable将在视图类中,而TableModel将在模型类中.

To take one example, your scoreboard is probably a JTable. The JTable would be in a view class, while the TableModel would be in a model class.

您对所有GUI组件都执行相同的操作.对于每个组件,在模型类中都有一个组件数据模型.

You do the same for all of your GUI components. For each component, you have a model of the component data in a model class.

这是我组装的秒表GUI的模型类.甚至无需查看GUI,您就应该能够识别出构成秒表的所有数据组件.

Here's a model class for a stopwatch GUI I put together. Without even seeing the GUI, you should be able to identify all of the data components that make up a stop watch.

package com.ggl.stopwatch.model;

import java.util.ArrayList;
import java.util.List;

import javax.swing.table.DefaultTableModel;

public class StopwatchModel {

    protected boolean isSplitTime;

    protected long startTime;

    protected long endTime;

    protected DefaultTableModel tableModel;

    protected List<Long> splitTimes;

    protected String[] columnNames = {"", "Increment", "Cumulative"};

    public StopwatchModel() {
        this.splitTimes = new ArrayList<Long>();
        this.isSplitTime = false;
        this.startTime = 0;
        this.endTime = 0;
        setTableModel();
    }

    public void resetTimes() {
        this.splitTimes.clear();
        this.isSplitTime = false;
        this.startTime = 0;
        this.endTime = 0;
    }

    public boolean isSplitTime() {
        return isSplitTime;
    }

    public long getStartTime() {
        return startTime;
    }

    public long getEndTime() {
        return endTime;
    }

    public long getLastSplitTime() {
        int size = splitTimes.size();
        if (size < 1) {
            return getStartTime();
        } else {
            return splitTimes.get(size - 1);
        }
    }

    public long getPenultimateSplitTime() {
        int size = splitTimes.size();
        if (size < 2) {
            return getStartTime();
        } else {
            return splitTimes.get(size - 2);
        }
    }

    public DefaultTableModel getTableModel() {
        return tableModel;
    }

    public int getTableModelRowCount() {
        return tableModel.getRowCount();
    }

    public void clearTableModel() {
        tableModel.setRowCount(0);
    }

    public int addTableModelRow(long startTime, long previousSplitTime, 
            long currentSplitTime, int splitCount) {
        String[] row = new String[3];

        row[0] = "Split " + ++splitCount;
        row[1] = formatTime(previousSplitTime, currentSplitTime, false);
        row[2] = formatTime(startTime, currentSplitTime, false);

        tableModel.addRow(row);

        return splitCount;
    }

    public void setStartTime() {
        if (getStartTime() == 0L) {
            this.startTime = System.currentTimeMillis();
        } else {
            long currentTime = System.currentTimeMillis();
            int size = splitTimes.size();
            if (size > 0) {
                long splitTime = splitTimes.get(size - 1);
                splitTime = splitTime - getEndTime() + currentTime;
                splitTimes.set(size - 1, splitTime);
            }
            this.startTime = currentTime - getEndTime() + getStartTime();
        }
    }

    protected void setTableModel() {
        this.tableModel = new DefaultTableModel();
        this.tableModel.addColumn(columnNames[0]);
        this.tableModel.addColumn(columnNames[1]);
        this.tableModel.addColumn(columnNames[2]);
    }

    public void setSplitTime() {
        this.splitTimes.add(System.currentTimeMillis());
        isSplitTime = true;
    }

    public void setEndTime() {
        Long split = System.currentTimeMillis();
        if (isSplitTime) {
            this.splitTimes.add(split);
        }
        this.endTime = split;
    }

    public String formatTime(long startTime, long time, boolean isTenths) {
        long elapsedTime = time - startTime;

        int seconds = (int) (elapsedTime / 1000L);

        int fraction = (int) (elapsedTime - ((long) seconds * 1000L));
        fraction = (fraction + 5) / 10;
        if (fraction > 99) {
            fraction = 0;
        }
        if (isTenths) {
            fraction = (fraction + 5) / 10;
            if (fraction > 9) {
                fraction = 0;
            }
        }


        int hours = seconds / 3600;
        seconds -= hours * 3600;

        int minutes = seconds / 60;
        seconds -= minutes * 60;

        StringBuilder builder = new StringBuilder();

        builder.append(hours);
        builder.append(":");
        if (minutes < 10) builder.append("0");
        builder.append(minutes);
        builder.append(":");
        if (seconds < 10) builder.append("0");
        builder.append(seconds);
        builder.append(".");
        if ((!isTenths) && (fraction < 10)) builder.append("0");
        builder.append(fraction);

        return builder.toString();
    }

}

一旦分离,就将初始化方法放入模型类中.

Once separated, you put initialize methods in your model classes.

编辑后添加:您将模型类的实例传递给视图类以生成视图.这是秒表GUI的主面板.

Edited to add: You pass an instance of the model class to your view class to generate the view. Here's the main panel of the stop watch GUI.

package com.ggl.stopwatch.view;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

import com.ggl.stopwatch.model.StopwatchModel;
import com.ggl.stopwatch.thread.StopwatchThread;

public class StopwatchPanel {

    protected static final Insets entryInsets = new Insets(0, 10, 4, 10);
    protected static final Insets spaceInsets = new Insets(10, 10, 4, 10);

    protected JButton resetButton;
    protected JButton startButton;
    protected JButton splitButton;
    protected JButton stopButton;

    protected JLabel timeDisplayLabel;

    protected JPanel mainPanel;
    protected JPanel buttonPanel;
    protected JPanel startPanel;
    protected JPanel stopPanel;

    protected SplitScrollPane splitScrollPane;

    protected StopwatchModel model;

    protected StopwatchThread thread;

    public StopwatchPanel(StopwatchModel model) {
        this.model = model;
        createPartControl();
    }

    protected void createPartControl() {
        splitScrollPane = new SplitScrollPane(model);

        createStartPanel();
        createStopPanel();
        setButtonSizes(resetButton, startButton, splitButton, stopButton);

        mainPanel = new JPanel();
        mainPanel.setLayout(new GridBagLayout());

        int gridy = 0;

        JPanel displayPanel = new JPanel();
        displayPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE, 6));

        timeDisplayLabel = new JLabel(model.formatTime(0L, 0L, true));
        timeDisplayLabel.setHorizontalAlignment(SwingConstants.CENTER);
        Font font = timeDisplayLabel.getFont();
        Font labelFont = font.deriveFont(60.0F);
        timeDisplayLabel.setFont(labelFont);
        timeDisplayLabel.setForeground(Color.BLUE);
        displayPanel.add(timeDisplayLabel);

        addComponent(mainPanel, displayPanel, 0, gridy++, 1, 1, spaceInsets,
                GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);

        buttonPanel = new JPanel();
        buttonPanel.add(startPanel);
        addComponent(mainPanel, buttonPanel, 0, gridy++, 1, 1, spaceInsets,
                GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);

        addComponent(mainPanel, splitScrollPane.getSplitScrollPane(), 0, gridy++, 1, 1, spaceInsets,
                GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL);
    }

    protected void createStartPanel() {
        startPanel = new JPanel();
        startPanel.setLayout(new FlowLayout());

        resetButton = new JButton("Reset");
        resetButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                model.resetTimes();
                timeDisplayLabel.setText(model.formatTime(0L, 0L, true));
                splitScrollPane.clearPanel();
                mainPanel.repaint();
            }
        });

        startPanel.add(resetButton);

        startButton = new JButton("Start");
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                model.setStartTime();
                thread = new StopwatchThread(StopwatchPanel.this);
                thread.start();
                displayStopPanel();
            }
        });

        startPanel.add(startButton);
    }

    protected void createStopPanel() {
        stopPanel = new JPanel();
        stopPanel.setLayout(new FlowLayout());

        splitButton = new JButton("Split");
        splitButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                model.setSplitTime();
                splitScrollPane.addSplit(model.getStartTime(), 
                        model.getPenultimateSplitTime(), 
                        model.getLastSplitTime());
                splitScrollPane.setMaximum();
                splitScrollPane.repaint();
            }
        });

        stopPanel.add(splitButton);

        stopButton = new JButton("Stop");
        stopButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                model.setEndTime();
                thread.setRunning(false);
                if (model.isSplitTime()) {
                    splitScrollPane.addSplit(model.getStartTime(), 
                            model.getPenultimateSplitTime(), 
                            model.getLastSplitTime());
                    splitScrollPane.setMaximum();
                    splitScrollPane.repaint();
                }
                displayStartPanel();
            }
        });

        stopPanel.add(stopButton);
    }

    protected void addComponent(Container container, Component component,
            int gridx, int gridy, int gridwidth, int gridheight, 
            Insets insets, int anchor, int fill) {
        GridBagConstraints gbc = new GridBagConstraints(gridx, gridy,
                gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, insets, 0, 0);
        container.add(component, gbc);
    }

    protected void displayStopPanel() {
        buttonPanel.remove(startPanel);
        buttonPanel.add(stopPanel);
        buttonPanel.repaint();
    }

    protected void displayStartPanel() {
        buttonPanel.remove(stopPanel);
        buttonPanel.add(startPanel);
        buttonPanel.repaint();
    }

    protected void setButtonSizes(JButton ... buttons) {
        Dimension preferredSize = new Dimension();
        for (JButton button : buttons) {
            Dimension d = button.getPreferredSize();
            preferredSize = setLarger(preferredSize, d);
        }
        for (JButton button : buttons) {
            button.setPreferredSize(preferredSize);
        }
    }

    protected Dimension setLarger(Dimension a, Dimension b) {
        Dimension d = new Dimension();
        d.height = Math.max(a.height, b.height);
        d.width = Math.max(a.width, b.width);
        return d;
    }

    public void setTimeDisplayLabel() {
        this.timeDisplayLabel.setText(model.formatTime(model.getStartTime(), 
                System.currentTimeMillis(), true));
    }

    public JPanel getMainPanel() {
        return mainPanel;
    }

}

这篇关于重新启动/重播Java游戏,而无需重新启动GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆