2016-06-13 23 views
-1

Also in einem Spiel, das ich mache, versuche ich über eine ArrayList vom Typ Troop und ArrayList des Typs Tower über einen Sockel, mit beiden Klasse Troop zu senden und Tower mit einem gepufferten Image. Das Spiel läuft mit 60 fps und sendet jedes Mal die beiden ArrayLists zwischen Server und Client in der updateConnection() -Methode. Als ich die Troop-Klasse und die Server- und Client-Klassen herausholte, bin ich erfolgreich in der Lage, die ArrayLists zu senden, aber ich bekomme eine Fehlermeldung, dass Troop nicht sterilisierbar ist, wenn es im Spiel läuft. Im Folgenden enthalten ich die Truppe Klasse, die beiden Klassen der Server- und Client-Klassen, die den Test zum Senden und Empfangen, und die Methode updateConnection() in der Klasse Spiel liefen:Problem mit Klasse nicht im Spiel Serilizable, aber funktioniert gut, wenn isoliert

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(); 
} 


} 

Das Verfahren von Game (das 60-mal pro Sekunde aufgerufen wird):

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); 
       } 
      } 
     } 
    } 

Hier sind die beiden wichtigsten Methoden, die ich den Server, Client zu testen, rufen, und Truppen Klassen:

Hier
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()); 
    } 
} 

ist der angeforderte Code 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(); 
} 

} 

Weltklasse:

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)]); 
     } 
    } 

} 
} 

Sorry, wenn ich zu viel Code geschrieben, aber ich würde lieber ein wenig zu viel, als nicht genug haben. Wenn es erforderlich ist, kann ich den Inhalt der Konsole für die Fehler veröffentlichen. Ich schätze die Hilfe.

+0

Ich bin nicht sicher, was "Handler" ist, aber sind Sie sicher, dass serialisieren-fähig ist und seine Eigenschaften? Wenn ein Objekt serialisiert wird, muss es zusammen mit einer seiner Eigenschaften serialisiert werden können. – CConard96

+0

Das könnte das Problem sein, ich werde versuchen, das alles jetzt zu beheben. – Dak31

+0

Ich ging und machte alle Klassen implementieren serializable, aber ohne Erfolg – Dak31

Antwort

0

Kredit geht an Ian und CConard96. Das Problem war, während die Klasse, die ich zu senden versuchte, serialisierbar war, die Referenzen, die es machte, nicht waren. Um das, was ich über den Socket gesendet habe, zu reduzieren (und so zu vereinfachen, dass weniger serialisierbar ist), konnte ich das Problem beheben, indem ich statische Referenzen verwendete, um sie (die nicht-serialisierten Klassen) zu eliminieren ObjectOutputStream.

Während Transienten funktionieren können, ist es in dieser Situation nicht ideal. Es wird dazu führen, dass das gesendete Objekt einen NULL-Verweis auf alles transient hat. Also musste sowohl die Handler-Variable als auch das gepufferte Image anders übergeben werden.

0

Der Handler scheint this zu sein, der nicht serialisierbar ist. Sie müssen es wie das BufferedImage transient machen.

+0

Das Bild hat die 'transient' Schlüsselwort und würde während der Serialisierung übersprungen werden. Das sollte den Fehler nicht verursachen. – CConard96

+0

@ CConard96 Ich habe meine Antwort korrigiert. Danke, dass du transient besser erklärst. – Ian

+0

Handler ist eine Klasse, die ich selbst gemacht habe. Es ist eine nette Klasse, wo ich auf alle Variablen von einem Ort aus zugreifen kann. Es implementiert auch Serializable. – Dak31