类在游戏中不可服务的问题,但在隔离

时间:2016-06-13 21:16:02

标签: java sockets bufferedimage

因此,在我正在制作的游戏中,我正在尝试通过套接字发送类型为Troop的类型列表和Tower类型的ArrayList,其中类Troop和Tower都具有缓冲图像。游戏以60 fps运行,每次在updateConnection()方法中通过服务器和客户端之间的两个ArrayLists发送。当我拿出Troop类和服务器和客户端类时,我成功地能够通过ArrayLists发送,但是我得到一个错误,说当Troop在游戏中运行时不可消毒。下面我包括了Troop类,服务器和客户端类,运行测试发送和接收的两个类,以及Game类中的方法updateConnection():

public class Server{

private ObjectOutputStream output;
private ObjectInputStream input;
private ServerSocket server;
private Socket connection;

JTextArea t;
JFrame f;

//constructor
public Server(){


    f = new JFrame();
    f.getContentPane().setPreferredSize(new Dimension(300, 300));
    f.pack();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLocationRelativeTo(null);
    t = new JTextArea();
    f.add(t, BorderLayout.CENTER);
    f.setVisible(true);

    try{
        server = new ServerSocket(8790, 10); //8798 is a dummy port for testing, this can be changed. The 100 is the maximum people waiting to connect.
            try{
                //Trying to connect and have conversation
                waitForConnection();
                setupStreams();
            }catch(EOFException eofException){
                //t.append("Connection was terminated");
            }
    } catch (IOException ioException){
        ioException.printStackTrace();
    }
}

//wait for connection, then display connection information
private void waitForConnection() throws IOException{
    t.append(" Waiting for someone to connect...");
    connection = server.accept();
    t.append(" Now connected to " + connection.getInetAddress().getHostName());
}

//get stream to send and receive data
private void setupStreams() throws IOException{
    output = new ObjectOutputStream(connection.getOutputStream());
    output.flush();

    input = new ObjectInputStream(connection.getInputStream());

    t.append(" Streams are now setup ");
    f.setVisible(false);
    f.dispose();
}


        //  input.readObject();


public void closeConnection(){
    //t.append(" Closing Connections... ");
    try{
        output.close(); //Closes the output path to the client
        input.close(); //Closes the input path to the server, from the client.
        connection.close(); //Closes the connection between you can the client
    }catch(IOException ioException){
        ioException.printStackTrace();
    }
}

public ObjectOutputStream getOutput(){
    return output;
}
public ObjectInputStream getInput(){
    return input;
}

public void sendObjects(Object obj){
    try {
        output.writeObject(obj);
        output.flush();
        output.reset();
    } catch (IOException e) {
        e.printStackTrace();
    }

}


public Object receiveObjects(){
    try{
        return input.readObject();
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
        return null;
    }
}
}

 public class Client extends JFrame{


private static final long serialVersionUID = 1L;
private ObjectOutputStream output;
private ObjectInputStream input;

private String serverIP;
private Socket connection;

JTextArea t;
JFrame f;

//constructor
public Client(String host){

    serverIP = host;

    f = new JFrame();
    f.getContentPane().setPreferredSize(new Dimension(300, 300));
    f.pack();

    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLocationRelativeTo(null);
    t = new JTextArea();
    f.add(t, BorderLayout.CENTER);
    f.setVisible(true);

    try{
        connectToServer();
        setupStreams();
    }catch(EOFException eofException){
        //t.append("Connection was terminated");
    }catch(IOException ioException){
        ioException.printStackTrace();
    }
}

public Client(){

    serverIP = "127.0.0.1";

    f = new JFrame();
    f.getContentPane().setPreferredSize(new Dimension(300, 300));
    f.pack();

    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLocationRelativeTo(null);
    t = new JTextArea();
    f.add(t, BorderLayout.CENTER);
    f.setVisible(true);


    try{
        connectToServer();
        setupStreams();
    }catch(EOFException eofException){
        //t.append("Connection was terminated");
    }catch(IOException ioException){
        ioException.printStackTrace();
    }
}



//connect to server
private void connectToServer() throws IOException{
    t.append("Attempting connection...");
    connection = new Socket(InetAddress.getByName(serverIP), 8790);
    t.append("Connection Established! Connected to: " + connection.getInetAddress().getHostName());
}

//set up streams
private void setupStreams() throws IOException{
    output = new ObjectOutputStream(connection.getOutputStream());
    output.flush();
    input = new ObjectInputStream(connection.getInputStream());
    t.append(" The streams are now set up!");
    f.setVisible(false);
    f.dispose();
}


//Close connection
public void closeConnection(){
    //t.append(" Closing the connection!");
    try{
        output.close();
        input.close();
        connection.close();
    }catch(IOException ioException){
        ioException.printStackTrace();
    }
}

public ObjectOutputStream getOutput(){
    return output;
}
public ObjectInputStream getInput(){
    return input;
}

public void sendObjects(Object obj){
    try {
        output.writeObject(obj);
        output.flush();
        output.reset();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

public Object receiveObjects(){
    try{
        return input.readObject();
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
        return null;
    }
}

} 

public class Troop implements Serializable{
private int x;
private int y;


private int health;
private int movSpeed;
private int movSpeedx;
private int movSpeedy;
private int cost;
private long deployCoolDown;
private int level;
private transient BufferedImage image;
private int size = 16;
private Handler handler;

/**
 * 
 * @param x
 * @param y
 * @param level
 * @param health
 * @param movSpeed
 * @param movSpeedx
 * @param movSpeedy
 * @param cost
 * @param deployCoolDown
 * @param image
 * 
 */

public Troop(int x, int y, int level, int health, int movSpeed, int movSpeedx, int movSpeedy, int cost, long deployCoolDown, BufferedImage image, Handler handler){
    this.x = x;
    this.y = y;
    this.level = level;
    this.health = health;
    this.movSpeed = movSpeed;
    this.movSpeedx = -movSpeed;
    this.movSpeedy = movSpeedy;
    this.cost = cost;
    this.deployCoolDown = deployCoolDown;
    this.image = image;
    this.handler = handler;

}
public void update(){
    Move();
    if(health <= 0){
        handler.getTroops().remove(this);
    }
}

public void checkX(){
    int z = 0;
    int tempMovSpeed = movSpeed;
    if(tempMovSpeed> 0){ //moving down
        int ty = (int) (y + tempMovSpeed + size + size/2) / Tile.TILE_WIDTH;
        if(!collisionWithTile((int) (x) / Tile.TILE_HEIGHT,ty) &&
                !collisionWithTile((int) (x + size) / Tile.TILE_HEIGHT,ty) &&
                    !collisionWithTile((int) (x + size/2) / Tile.TILE_HEIGHT,ty)){
            z = 1;
        }else{
            //System.out.println("collision moving down");
        }
    }

    tempMovSpeed = -movSpeed;

    if(tempMovSpeed < 0){ // up
        int ty = (int) (y + tempMovSpeed - size/2) / Tile.TILE_WIDTH;

        if(!collisionWithTile((int) (x) / Tile.TILE_HEIGHT,ty) &&
                !collisionWithTile((int) (x + size) / Tile.TILE_HEIGHT,ty) &&
                    !collisionWithTile((int) (x + size/2) / Tile.TILE_HEIGHT,ty)){
            if(z == 1){
                z = 3;
            }
            else{
                z = 2;
            }
        }else{
            //System.out.println("collision moving up");
        }
    }

    //System.out.println(z);

    if(z == 0){
        //System.out.println("dead end?");
    }
    else if(z == 1){
        movSpeedy = movSpeed;
    }
    else if(z == 2){
        movSpeedy = -movSpeed;
    }
    else if(z == 3){
        Random r = new Random();
        int q = r.nextInt(2);
        if(q == 0){
            movSpeedy = movSpeed;
        }
        else{
            movSpeedy = -movSpeed;
        }
    }
}
public void checkY(){
    int z = 0;
    int tempMovSpeed = movSpeed;
    int tx = (int) (x + tempMovSpeed + size + size/2) / Tile.TILE_WIDTH;

    if(!collisionWithTile(tx, (int) (y) / Tile.TILE_HEIGHT) &&
            !collisionWithTile(tx, (int) (y + size) / Tile.TILE_HEIGHT) &&
                !collisionWithTile(tx, (int) (y + size/2) / Tile.TILE_HEIGHT)){
        z = 1;

    }

    tempMovSpeed = -movSpeed;
    tx = (int) (x + tempMovSpeed - size/2) / Tile.TILE_WIDTH;

    if(!collisionWithTile(tx, (int) (y) / Tile.TILE_HEIGHT) &&
            !collisionWithTile(tx, (int) (y + size) / Tile.TILE_HEIGHT) &&
                !collisionWithTile(tx, (int) (y + size/2) / Tile.TILE_HEIGHT)){
        if(z != 1){
            z = 2;
        }
        else{
            z = 3;
        }
    }
    if(z == 0){
        //System.out.println("dead end");
    }
    else if(z == 1){
        movSpeedx = movSpeed;
    }
    else if(z == 2){
        movSpeedx = -movSpeed;
    }
    else{
        Random r = new Random();
        int q = r.nextInt(1);
        if(q == 0){
            movSpeedx = movSpeed;
        }
        else{
            movSpeedx = -movSpeed;
        }
    }
}

protected boolean collisionWithTile(int x, int y){
    return !handler.getWorlds().get(handler.getGame().getLevel()).getTile(x, y).isPath();
}

public void render(Graphics g){
    g.setColor(Color.GREEN);
    g.fillRect(x, y, size, size);
}
public void Move(){
    if(movSpeedx > 0){ //moving right
            int tx = (int) (x + movSpeedx + size + size/2) / Tile.TILE_WIDTH;
            if(!collisionWithTile(tx, (int) (y) / Tile.TILE_HEIGHT) &&
                    !collisionWithTile(tx, (int) (y + size) / Tile.TILE_HEIGHT) &&
                        !collisionWithTile(tx, (int) (y + size/2) / Tile.TILE_HEIGHT)){
                x += movSpeedx;
            }else{
                x = tx * Tile.TILE_WIDTH - 3 * size /2;
                checkX();
                movSpeedx = 0;

            }
        }
    else if(movSpeedx < 0){ // left
        int tx = (int) (x + movSpeedx - size/2) / Tile.TILE_WIDTH;

        if(!collisionWithTile(tx, (int) (y) / Tile.TILE_HEIGHT) &&
                !collisionWithTile(tx, (int) (y + size) / Tile.TILE_HEIGHT) &&
                    !collisionWithTile(tx, (int) (y + size/2) / Tile.TILE_HEIGHT)){
            x += movSpeedx;
        }else{
            x = tx * Tile.TILE_WIDTH + Tile.TILE_WIDTH + size/2;
            checkX();
            movSpeedx = 0;
        }
    }

    if(movSpeedy > 0){ //moving down
        int ty = (int) (y + movSpeedy + size + size/2) / Tile.TILE_WIDTH;
        if(!collisionWithTile((int) (x) / Tile.TILE_HEIGHT, ty) &&
                !collisionWithTile((int) (x + size) / Tile.TILE_HEIGHT, ty) &&
                    !collisionWithTile((int) (x + size/2) / Tile.TILE_HEIGHT, ty)){
            y += movSpeedy;
        }else{
            //System.out.println("collision");
            y = ty * Tile.TILE_WIDTH - 3 * size /2;
            movSpeedy = 0;
            checkY();
        }
    }
    else if(movSpeedy < 0){ // up
        int ty = (int) (y + movSpeedy - size/2) / Tile.TILE_WIDTH;

        if(!collisionWithTile((int) (x) / Tile.TILE_HEIGHT, ty) &&
                !collisionWithTile((int) (x + size) / Tile.TILE_HEIGHT, ty) &&
                    !collisionWithTile((int) (x + size/2) / Tile.TILE_HEIGHT, ty)){
            y += movSpeedy;
        }else{
            y = ty * Tile.TILE_WIDTH + Tile.TILE_WIDTH + size/2;
            movSpeedy = 0;
            checkY();
        }
    }

}



public int getX() {
    return x;
}
public void setX(int x) {
    this.x = x;
}
public int getY() {
    return y;
}
public void setY(int y) {
    this.y = y;
}
public int getSize(){
    return size;
}
public int getMovSpeed() {
    return movSpeed;
}
public void setMovSpeed(int movSpeed) {
    this.movSpeed = movSpeed;
}
public int getHealth() {
    return health;
}

public void changeHealth(int health) {
    this.health += health;
}

public int getCost() {
    return cost;
}

public void setCost(int cost) {
    this.cost = cost;
}

public long getDeployCoolDown() {
    return deployCoolDown;
}

public void setDeployCoolDown(int deployCoolDown) {
    this.deployCoolDown = deployCoolDown;
}

 private void writeObject(ObjectOutputStream out)throws IOException{
     out.defaultWriteObject();
 }

 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
     in.defaultReadObject();
 }


}

来自Game的方法(每秒调用60次):

private void updateConnection(){


        if(isClientActive()){
            if(player.getType() == 0){
                client.sendObjects(towers);
                System.out.println("sent towers: " + towers.size());
            }else{
                client.sendObjects(troops);
                System.out.println("sent troops: " + troops.size());
            }
            ArrayList<Object> obj = (ArrayList<Object>)client.receiveObjects();
            System.out.println("obj: " +obj.size());
            if(obj != null && obj.size() > 0){
                if (obj.get(0) instanceof Troop) {
                    mendTroops(obj);
                }else if(obj.get(0) instanceof Troop){
                    mendTowers(obj);
                }
            }
        }else if(isServerActive()){
            if(player.getType() == 0){
                server.sendObjects(towers);
                System.out.println("sent towers: " + towers.size());
            }else{
                server.sendObjects(troops);
                System.out.println("sent troops: " + troops.size());
            }
            ArrayList<Object> obj = (ArrayList<Object>)server.receiveObjects();
            System.out.println("obj: " +obj.size());
            if(obj != null && obj.size() > 0){
                if (obj.get(0) instanceof Troop) {
                    mendTroops(obj);
                }else if(obj.get(0) instanceof Troop){
                    mendTowers(obj);
                }
            }
        }
    }

以下是我调用服务器,客户端和部队类的两种主要方法:

public static void main(String[] args){
    Server s = new Server();
    ArrayList<Troop> troopsArray = new ArrayList<Troop>();
    troopsArray.add(new Goblin(1,1,1));
    troopsArray.add(new Goblin(2,2,2));
    s.sendObject(troopsArray);
}


public static void main(String[] args){
    Client c = new Client();
    while(true){
        ArrayList<Troop> troop2 = (ArrayList<Troop>)c.receiveObjects();     
        JOptionPane.showMessageDialog(null, troop2.get(1).getX());
    }
}

以下是请求的Handler代码:

public class Handler implements Serializable{
private Game game;
private transient Player player;
private transient ArrayList<Tower> towers;
private transient ArrayList<Troop> troops;
private transient Screen screen;
private transient Frame frame;
private transient Menu menu;
private ArrayList<Worlds> worlds;

public Handler(Game game, Player player, ArrayList<Tower> towers, ArrayList<Troop> troops, Screen screen, Frame frame, Menu menu, ArrayList<Worlds> worlds){
    this.game = game;
    this.player = player;
    this.towers = towers;
    this.troops = troops;
    this.screen = screen;
    this.frame = frame;
    this.menu = menu;
    this.worlds = worlds;
}

public Server getServer(){
    return game.getServer();
}
public Client getClient(){
    return game.getClient();
}
public ArrayList<Worlds> getWorlds() {
    return worlds;
}

public Game getGame() {
    return game;
}

public Player getPlayer() {
    return player;
}

public ArrayList<Tower> getTowers() {
    return towers;
}

public ArrayList<Troop> getTroops() {
    return troops;
}

public Screen getScreen() {
    return screen;
}

public Frame getFrame() {
    return frame;
}

public Menu getMenu() {
    return menu;
}
public boolean towerCollisionWithTile(int x, int y){
    return worlds.get(game.getLevel()).getTile(x, y).isTowerNotPlaceable();
}

}

世界级:

public class Worlds implements Serializable{

private int width = 40;
private int height = 20; //in tiles
private int spawnX, spawnY;
private int[][]  tiles;

public Worlds(String path){
    loadWorld(path);
}

public Tile getTile(int x, int y){
    if(x < 0 || y < 0 || x >= width || y >= height)
        return Tile.grassTile;

    Tile t = Tile.tiles[tiles[x][y]];
    if(t == null)
        return Tile.grassTile;
    return t;
}



public void render(Graphics g){

    for(int y = 0; y < height; y++){
        for(int x = 0; x < width; x++){
            getTile(x, y).render(g, (int) (x * Tile.TILE_WIDTH),
                        (int) (y* Tile.TILE_HEIGHT));
        }
    }
}


private void loadWorld(String path){
    String file = Utils.loadFileAsString(path);
    String [] tokens = file.split("\\s");

    tiles = new int[width][height];

    for(int y = 0; y < height; y++){
        for(int x = 0; x < width; x++){
            tiles[x][y] = Utils.parseInt(tokens[(x + y * width)]);
        }
    }

}
}

很抱歉,如果我发布了太多代码,但我宁愿有点太多,还不够。如果需要,我可以发布错误控制台的内容。我很感激帮助。

2 个答案:

答案 0 :(得分:0)

处理程序似乎是this,不可序列化。你需要像BufferedImage一样使它成为瞬态。

答案 1 :(得分:0)

归功于Ian和CConard96。问题是,虽然我试图发送的类是可序列化的,但它所引用的引用却没有。为了减少我通过套接字发送的内容(从而简化它以便更少需要可序列化)我能够通过使用静态引用来解决问题,从而消除它们(非序列化类)被写入的ObjectOutputStream。

虽然瞬态可以起作用,但在这种情况下并不理想。它将导致发送的对象具有对瞬态的任何空引用。因此Handler变量以及缓冲的Image需要以不同的方式传递。