java - 如何在 Java 中加载游戏并返回到游戏之前的状态?

标签 java serialization deserialization

首先我想说的是,我对于使用 Java 中的 swing 还比较陌生。我可以让 swing 做一些事情,比如玩游戏,但我不确定我是否真正理解幕后发生的事情。因此,我开始用 Java 开发一款游戏,类似于《文明》,并且已经取得了一些不错的进展。我想把注意力转向保存游戏并重新加载它。然而,我在这方面遇到了一些麻烦。所以我做了一些研究,发现了如何使对象可序列化并从那里保存/加载。效果很好,我可以保存我的游戏并加载它。问题是,所有内容都再次出现在屏幕上(地形图 block 、单位、HUD),但似乎存储在我的某些对象中的数据已设置回其初始化点。例如,我可以在 X 方向的图 block 41 上结束,但是当我加载游戏时,它会将其设置回 0。

关于我如何设置游戏的简要描述:我有一个创建新 Window 对象的 Main 类。 Window 对象本质上是一个 JFrame,其中包含按钮信息和一个 Panel 类,该类只是绘制游戏的 JPanel。游戏中发生的所有事情都在 JPanel 中创建。我对编程并不陌生,我是一名计算 Material 科学家,但我是用 Java 编写游戏的新手,我觉得我犯了一个非常简单的错误。我将在下面发布 JFrame 和 JPanel(其中一部分,相当长)。

框架

public class GameWindow extends JFrame implements ActionListener
{
//ints
private int fCounter = 0;   

//timers
private Timer t;

//Panels
private GamePanel gamePanel;

//menu bars
private JMenuBar menuBar;

//menus
private JMenu fileMenu;

//menu items
private JMenuItem save; 
private JMenuItem load; 
private JMenuItem exit; 
private JMenuItem newGame;

//menu panels
private JPanel menuPanel;

//File objects  
private File file;

//File Chooser
private JFileChooser chooser;

//user objects
private Player humanPlayer;
private AI aIPlayer;
private FileActions fileActions;
//**************************************************************************constructor 
public GameWindow()
{
    //set specifications for frame
    super("New Game v 0.00: pre-Alpha");
    this.setResizable(false);
    setFocusable(true);     
    setSize(1600, 800);


    //creates a new menubar
    menuBar = new JMenuBar();

    //craetes a new file menu
    fileMenu = new JMenu("File");

    //creates the file options
    save = new JMenuItem("Save");
    save.addActionListener(this);
    load = new JMenuItem("Load");
    load.addActionListener(this);
    newGame = new JMenuItem("New Game");
    newGame.addActionListener(this);
    exit = new JMenuItem("Exit");
    exit.addActionListener(this);

    //adds file options to the file menu
    fileMenu.add(save);
    fileMenu.add(load);
    fileMenu.add(newGame);
    fileMenu.add(exit);

    //adds the file menu to the menubar
    menuBar.add(fileMenu);

    //establishes the menu panel as a new JPanel
    menuPanel = new JPanel();

    //adds the menu to the menubar
    menuPanel.add(menuBar);

    //sets user class objects
    humanPlayer = new Player();
    aIPlayer = new AI();
    fileActions = new FileActions();

    //panels
    gamePanel = new GamePanel();
    gamePanel.setSize(750, 750);
    gamePanel.setFocusable(true);
    addKeyListener(gamePanel);
    addMouseListener(gamePanel);
    addMouseMotionListener(gamePanel);
    setVisible(true);

    //adds panels to the frame with layout
    add(menuPanel, BorderLayout.EAST);
    add(gamePanel, BorderLayout.CENTER);    

    //add file choosers
    chooser = new JFileChooser();

    //adds file objects
    file = new File("");        

    //timers
    t = new Timer(1, this);
    t.start();  
}
@Override
public void actionPerformed(ActionEvent e)
{
    // TODO Auto-generated method stub
    //save a game
    if(e.getSource() == save)
    {
        //fCounter = chooser.showSaveDialog(this);
        //if(fCounter == JFileChooser.APPROVE_OPTION)
        //{
            //file = chooser.getSelectedFile(); 
            fileActions.addObject(gamePanel);       
            fileActions.saveGame();
        //}
    }
    //load a save file
    if(e.getSource() == load)
    {
        this.remove(gamePanel);

        gamePanel = fileActions.loadGame();

        this.add(gamePanel);
        gamePanel.setFocusable(true);
        addKeyListener(gamePanel);
        addMouseListener(gamePanel);
        addMouseMotionListener(gamePanel);
        add(gamePanel, BorderLayout.CENTER);
        setVisible(true);
    }
    //starts a new game
    if(e.getSource() == newGame)
    {
        //gamePanel = null;
        //gamePanel = new GamePanel();

        gamePanel.setNewGameSetup(true);
        gamePanel.setMainMenuView(false);

    }
    //exits the game
    if(e.getSource() == exit)
    {
        System.exit(0);
    }
    gamePanel.repaint();        
}

}

<小时/>

面板类的一部分

public class GamePanel extends JPanel  implements        
ActionListener,KeyListener,MouseListener,MouseMotionListener,Serializable
{
//globals
private static int mapHeight = 0;
private static int mapWidth= 0;
private static int currentMapHoriztonal= 0;
private static int currentMapVertical= 0;
private static int currentMouseMapHoriztonal= 0;
private static int currentMouseMapVertical= 0;
private static int turnNumber= 0;
private  int unitFocusNumber = -1;
private  int cityFocusNumber = -1;

private Terrain[][] terrain;
private ArrayList<Unit> playerUnits = new ArrayList<Unit>();
private ArrayList<City> playerCities = new ArrayList<City>();

private boolean terrainCreate = true;
private boolean mainMenu = true;
private boolean newGameSetup = false;
private boolean mapView = false;
private boolean mapSizeOptions = false;
private boolean playerTurn = true;
private boolean[] move = new boolean[4];

private Font mainMenuTitle = new Font("Algerian",Font.BOLD,75);
private Font mainMenuOptions = new Font("Calibri",Font.BOLD,15);

private Player player = new Player();

private FileActions fA;

private AI aI = new AI();

public GamePanel()
{

}
//getters
public int getMapHeight()
{
    return mapHeight;
}
public boolean getMapView()
{
    return mapView;
}
public Terrain[][] getTerrain()
{
    return terrain;
}


//setters
public void setMapHeight(int height)
{
    mapHeight = height;
}
public void setMapWidth(int width)
{
    mapWidth = width;
}
public void setMapView(boolean b)
{
    mapView = b;
}
public void setMainMenuView(boolean b)
{
    mainMenu = b;
}
public void setNewGameSetup(boolean b)
{
    newGameSetup = b;
}


//painters

//paints the game
public void paintComponent(Graphics g)
{       
    if(mainMenu == true)
    {
        paintMainMenu(g);
    }
    if(newGameSetup == true)
    {
        paintSetupScreen(g);
    }
    else if(mapView == true)
    {
        if(terrainCreate == true)
        {
            //sets the terrain
            terrain  = new Terrain[mapHeight][mapWidth];

            for(int i = 0; i < mapHeight; i++)
            {
                for(int j = 0; j < mapWidth; j++)
                {                   
                    terrain[i][j] = new Terrain(j,i,mapWidth,mapHeight);
                    terrain[i][j].setTerrain(j,i);
                }
            }
            for(int i = 0; i < 4; i++)
            {
                playerUnits.add(new Scout(75*i,75*i));
            }
            playerUnits.add(new Settler(75*9,75*8));
            playerUnits.add(new Settler(75*14,75*12));

            terrainCreate = false;
        }
        if(terrainCreate == false)
        {
            paintTerrain(g);
            paintCities(g);
            paintUnits(g);
            paintHud(g);
        }           
    }                       
}

任何帮助将不胜感激!

编辑: 这是实际加载和保存游戏的类。

public class FileActions implements Serializable
{
    private ArrayList<Object> objects = new ArrayList<Object>();

    //setters
    public void addObject(Object o)
    {
        objects.add(o);
    }

    //getters

    public void saveGame()
    {
        try
        {  // Catch errors in I/O if necessary.
            // Open a file to write to, named SavedObj.sav.
            FileOutputStream saveFile=new FileOutputStream("NTT.sav");

            // Create an ObjectOutputStream to put objects into save file.
            ObjectOutputStream save = new ObjectOutputStream(saveFile);

            // Now we do the save.
            for(int i = 0; i < objects.size();i++)
            {
                save.writeObject(objects.get(i));
            }
            // Close the file.
            save.close(); // This also closes saveFile.
        }
        catch(Exception exc)
        {
            exc.printStackTrace(); // If there was an error, print the info.            
        }       
    }
    public GamePanel loadGame()
    {
        GamePanel stuff = new GamePanel();
        try
        {
            // Open file to read from, named SavedObj.sav.
            FileInputStream saveFile = new FileInputStream("NTT.sav");

            // Create an ObjectInputStream to get objects from save file.
            ObjectInputStream save = new ObjectInputStream(saveFile);           

             stuff = (GamePanel) save.readObject();

            // Close the file.
            save.close(); // This also closes saveFile.

        }
        catch(Exception exc)
        {
            exc.printStackTrace(); // If there was an error, print the info.
        }
        System.out.println(stuff);

        return stuff;       
    }
}

最佳答案

好吧,所以我做了一些更多的挖掘,本质上我不应该在使用序列化作为保存方法时使用静态变量,因为静态变量不是 GamePanel 对象的一部分而是类的一部分,所以当 save 方法保存时对象它实际上并不保存静态变量变成的任何内容。我将需要保存的所有变量设置为非静态,并且一切正常

关于java - 如何在 Java 中加载游戏并返回到游戏之前的状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33638742/

相关文章:

c# - 将 JSON 数组反序列化为字典,其中的键与 JSON 分开提供

c# - 让 NodaTime.Serialization.JsonNet 使用自定义日期格式

java - Java 中的静态 block 未执行

java - Spring RestTemplate : Request/response json not getting logged

c# - 在 C# 中反序列化 SOAP 数组

c# - 如何将 JSON 反序列化到这个 POCO 类中?

java - JAXB xml 字符串到 java 对象 - 意外元素

Java wait() 不抛出 InterruptedException

c# - 在 .NET Framework 2 和 4 中进行序列化和反序列化 - C#

.net - 如何从 AfterReceiveReply 中的 WCF 消息中提取错误代码