ClassCastException, когда я пытаюсь загрузить геймплей для клона Space Invaders - PullRequest
0 голосов
/ 30 января 2019

Редактировать : Решено Марком Роттвилом!Во время сохранения я использовал oos.writeObject(this);, а не oos.writeObject(GamePlay.this);

, поэтому у меня возникли большие проблемы с работой функции загрузки.Когда я применял эту логику к простым программам, у меня никогда не было проблем, и я впервые делаю что-то, что включает сериализацию и потоки.Так что у меня есть предчувствие, что проблема связана с потоками.

Так что, как я это сделал, у меня есть класс Gameplay, который сохраняет себя, используя это.При сохранении этого файла не возникает ошибок, и он успешно появляется в моей папке.:

                try {

                FileOutputStream fos = new FileOutputStream("C:\\temp\\gameplay.dat");
                try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
                    oos.writeObject(this);
                }
                System.out.println("Gameplay Saved");
            } catch (IOException e) {
                System.out.println("Error Saving");
            }

Когда я играю в игру, консоль сообщает, что она успешно сохранена.Однако, когда я перезагружаю игру и пытаюсь загрузить ее, я получаю ClassCastException.Вот код загрузки игры

  public void actionPerformed(ActionEvent arg0) {
            try {
                FileInputStream fi = new FileInputStream("C:\\temp\\gameplay.dat");
                ObjectInputStream oi = new ObjectInputStream(fi);
                try {
                    Gameplay game = new Gameplay();
                    try {
                        game = (Gameplay) oi.readObject();
                    } catch (ClassCastException e) {
                        System.out.println("ClassCastException ");
                    }
                    oi.close();
                    fi.close();
                    game.addKeyBindings(panelCont);
                    frame.add(game);
                    Thread t1 = new Thread(game);
                    t1.start();
                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(SpaceRaiders.class.getName()).log(Level.SEVERE, null, ex);
                }

            } catch (FileNotFoundException e) {
                System.out.println("File not found");
            } catch (IOException e) {
                System.out.println("Error initializing stream");

            }

Я действительно хочу понять, что происходит, и я ценю любую помощь, если кто-то может просто указать мне правильное направление!

Обратите внимание: если вам нужно взглянуть на класс Gameplay, я не против опубликовать его, но он довольно длинный, и я не хочу перегружать его.

Вот класс Gameplay

public class Gameplay extends JPanel implements ActionListener, Runnable, Serializable {

private Ship player = new Ship(new Point(200, 555));
private Timer t = new Timer(5, this);
private int score;

//Laser and shot variables ----------
private ArrayList<Laser> lasers = new ArrayList<Laser>();
private boolean readytofire;
private boolean shot = false;

//Invader variables -----------
private ArrayList<Invader> invaders = new ArrayList<Invader>();

public Gameplay() {
    super();
    t.start();
    setFocusable(true);
    requestFocus();
    setFocusTraversalKeysEnabled(false);

    for (int j = 0; j < 80; j += 20) {
        for (int i = 0; i < 20; i++) {
            invaders.add(new Invader(5 + i * 30, j));
        }
    }
}

public boolean addLaser(Laser a) {
    lasers.add(a);
    return true;
}

public boolean addPlayer(Ship p) {

    this.player = p;

    return true;
}

// Les évenements claviers --------------------
@Override
public void actionPerformed(ActionEvent ae) {
    repaint();
}

public void addKeyBindings(JComponent jc) {
    jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "moveRight");
    jc.getActionMap().put("moveRight", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            moveRight();
        }
    });

    jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "moveLeft");
    jc.getActionMap().put("moveLeft", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            moveLeft();
        }
    });
    jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "shoot");
    jc.getActionMap().put("shoot", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            shoot();
        }
    });

    // FONCTIONS DE SAUVEGARDE------------------------
    jc.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "save");
    jc.getActionMap().put("save", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            try {

                FileOutputStream fos = new FileOutputStream("C:\\temp\\gameplay.dat");
                try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
                    oos.writeObject(this);
                }
                System.out.println("Gameplay Saved");
            } catch (IOException e) {
                System.out.println("Error Saving");
            }

        }
    });
}

// Le mouvement du Ship --------------------
public void moveRight() {
    if (player.getCentre().getX() >= 580) {
        player.setX(580);
    } else {
        double movement = player.getCentre().getX();
        movement += 10;
        player.setX(movement);
    }
    this.repaint();
}

public void moveLeft() {
    if (player.getCentre().getX() <= 20) {
        player.setX(20);
    } else {
        double movement = player.getCentre().getX();
        movement -= 10;
        player.setX(movement);
    }
    this.repaint();
}

// Création du laser --------------------
public void shoot() {

    shot = true;
    if (readytofire) {
        Point top = new Point(player.getTopX(), player.getTopY());
        Laser laser = new Laser(top);
        addLaser(laser);

    }
}

// Mouvement du laser --------------------    
public void moveShot() {
    if (shot) {
        for (Laser l : lasers) {
            l.setY(l.getTopLeft().getY() - 2);

        }
    }
}

// Collision Detection
public boolean checkCollision(Invader i, Laser l) {
    double x = i.getlocX();
    double y = i.getlocY();
    if (l.getX() > x && l.getX() < x + 15 && l.getY() > y && l.getY() < y + 15) {
        return true;
    } else {
        return false;
    }
}

public boolean outBounds(Laser l) {

    if (l.getY() == 0) {
        return true;
    } else {
        return false;
    }
}

// Dessiner les graphiques --------------------
@Override
public void paint(Graphics g) {
    setBackground(Color.black);
    super.paint(g);
    player.draw(g);
    try {
        for (Laser l : lasers) {
            l.draw(g);
        }
        for (Invader i : invaders) {
            i.draw(g);
        }

    } catch (Exception e) {

    }
    g.drawString("Score: " + score, 0, 10);

}

// public void paintComponent (Graphics g){
// Controle Thread
public void run() {

    while (true) {
        moveShot();

        //Verifie Collision-------------------------------------------------
        List<Invader> invaderRemove = new ArrayList<Invader>();
        List<Laser> laserRemove = new ArrayList<Laser>();
        for (Invader i : invaders) {
            for (Laser l : lasers) {

                if (checkCollision(i, l) == true) {

                    laserRemove.add(l);
                    invaderRemove.add(i);
                    score += 1;
                }
            }
        }

        lasers.removeAll(laserRemove);
        invaders.removeAll(invaderRemove);

        //Enleve les lasers si ils arrivent a la fin du frame---------------
        for (Laser l : lasers) {
            if (outBounds(l) == true) {
                laserRemove.add(l);

            }

        }
        lasers.removeAll(laserRemove);

        //Mouvement des invaders
        for (Invader i : invaders) {
            i.moveAndUpdate();

        }

        try {
            Thread.sleep(10);
            readytofire = true;

        } catch (InterruptedException ex) {
            Logger.getLogger(Gameplay.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}

}

И трассировка стека

java.lang.ClassCastException: spaceraiders.vue.Gameplay$4 cannot be cast to spaceraiders.vue.Gameplay
at spaceraiders.Controlleur.SpaceRaiders$2.actionPerformed(SpaceRaiders.java:106)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6533)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6298)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

1 Ответ

0 голосов
/ 30 января 2019

Это ваш код:

jc.getActionMap().put("save", new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent ae) {
        try {
            FileOutputStream fos = new FileOutputStream("C:\\temp\\gameplay.dat");
            try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
                oos.writeObject(this);
            }
            System.out.println("Gameplay Saved");
        } catch (IOException e) {
            System.out.println("Error Saving");
        }
    }
});

Это создает анонимный класс, и this в oos.writeObject(this) относится к этому анонимному классу.Это не относится к вашему экземпляру GamePlay.Таким образом, вы сериализуете это Action, а при десериализации и приведении к GamePlay приведение завершается неудачно.

Вам нужно либо вызвать действие, чтобы вызвать метод в классе GamePlay, который содержит фактическую сериализациюкод, или вам нужно сослаться на класс, используя GamePlay.this.Подробности см. В Получение объекта внешнего класса из объекта внутреннего класса

...