Scott Sinischo
Scott Sinischo

Reputation: 131

ObjectInputStream Not Reading More Than Once

I've been trying to make a two-player Dominoes game. For now, I want Player 1's movements to be mimicked on Player 2's screen, nothing more. If I start up player 1's screen, and move some Dominoes, the changes appear when I start up player 2's screen. But any movements from then on out are not changed. What is wrong here?

public class Server {

    private static ObjectOutputStream output;
    private static ObjectInputStream input;
    private static ServerSocket server;
    private static Socket connection;
    private static Player1 p1Game;
    private static final int port = 12345;

    public static void main(String[] args){
        p1Game = new Player1();
        Thread p1GameThread = new Thread(p1Game);
        p1GameThread.run();
        startServer();
    }

    private static void startServer() {
        p1Game.setStatusMessage("Starting server...");
        try{ 
            server = new ServerSocket(port, 100);
            p1Game.setStatusMessage("Awaiting connection from player 2...");
            connection = server.accept();
            output = new ObjectOutputStream(connection.getOutputStream());
            output.flush();
            p1Game.setStatusMessage("");
            while(true){
                ArrayList <CDomino> sendDominoes = p1Game.getP1Dominoes();
                System.out.println("N" + sendDominoes.get(0).getX());
                output.writeObject(sendDominoes);
                output.flush();
                Thread.sleep(1000);

                }
        } catch (Exception e) {e.printStackTrace();}
    }
}

public class Client {

    private static ObjectOutputStream output;
    private static ObjectInputStream input;
    private static Socket client;
    private static Player2 p2Game;
    private static final String serverAddress = "127.0.0.1";
    private static final int serverPort = 12345;

    public static void main(String[] args){
        p2Game = new Player2();
        Thread p2GameThread = new Thread(p2Game);
        p2GameThread.run();
        connect();
    }

    private static void connect() {
        p2Game.setStatusMessage("Attempting to connect to " + serverAddress + " on port " + serverPort + "...");
        try{
            client = new Socket( InetAddress.getByName(serverAddress), serverPort);
            input = new ObjectInputStream(client.getInputStream());
            p2Game.setStatusMessage("");
            while (true)
                p2Game.setP1Dominoes((ArrayList<CDomino>) input.readObject());
        } catch (Exception e) {e.printStackTrace();}
    }
}

public class CDomino implements Serializable{
    private static final long serialVersionUID = 345L;
    private int xC;
    private int yC;
    private int rotation;

    private Color playerColorDark;
    private Color playerColorLight;
    private int player;
    private int topSpots;
    private int bottomSpots;

    private final int[][] spotMatrix = {
              { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
              { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, 
              { 1, 0, 0, 0, 0, 0, 0, 0, 1 }, 
              { 1, 0, 0, 0, 1, 0, 0, 0, 1 }, 
              { 1, 0, 1, 0, 0, 0, 1, 0, 1 }, 
              { 1, 0, 1, 0, 1, 0, 1, 0, 1 }, 
              { 1, 0, 1, 1, 0, 1, 1, 0, 1 }
              };

    private final int[][] topGridMatrix = {
            {-12, -30}, {-2, -30}, {8, -30},
            {-12, -20}, {-2, -20}, {8, -20},
            {-12, -10}, {-2, -10}, {8, -10}
    };

    private final int[][] bottomGridMatrix = {
            {-12, 5}, {-2, 5}, {8, 5},
            {-12, 15}, {-2, 15}, {8, 15},
            {-12, 25}, {-2, 25}, {8, 25},
    };

    public CDomino(int x, int y, int angle, int color){
        xC = x;
        yC = y;
        rotation = angle;
        topSpots = new Random().nextInt(7);
        bottomSpots = new Random().nextInt(7);

        if (color == 2){
            playerColorLight = new Color(60, 180, 60);
            playerColorDark = new Color(0, 100, 0);
        }
        else{
            playerColorLight = new Color(120, 120, 255);
            playerColorDark = new Color(0, 0, 200);
        }
    }

    public boolean isInside(int x, int y){
        if (rotation == 0 | rotation == 180) return (x > xC-15) && (x < xC+15) && (y > yC-30) && (y < yC+30);
        else return (x > xC-30) && (x < xC+30) && (y > yC-15) && (y < yC+15);
    }

    public int getX(){return xC;}
    public int getY(){return yC;}
    public void setPosition(int x, int y){
        xC = x;
        yC = y;
    }

    public void rotate(){
        if (rotation == 270) rotation = 0;
        else rotation += 90;
    }

    //dimensions are 36x71px
    public void draw(Graphics g, int viewingPlayer){

        g.setColor(Color.WHITE);
        if (rotation == 0 || rotation == 180){
            g.fillRect(xC-18, yC-36, 36, 71);
            g.setColor(playerColorDark);
            g.drawRoundRect(xC-18, yC-36, 36, 71, 5, 5);
            g.setColor(playerColorLight);
            g.drawRoundRect(xC-19, yC-37, 38, 73, 5, 5);
            g.setColor(Color.GRAY);
            g.drawLine(xC-13, yC, xC+14, yC);
        }
        else {
            g.fillRect(xC-36, yC-18, 71, 36);
            g.setColor(playerColorDark);
            g.drawRoundRect(xC-36, yC-18, 71, 36, 5, 5);
            g.setColor(playerColorLight);
            g.drawRoundRect(xC-37, yC-19, 73, 38, 5, 5);
            g.setColor(Color.GRAY);
            g.drawLine(xC, yC-13, xC, yC+14);
        }

        g.setColor(Color.RED);
        if (isInOpponentHomeArea(yC, viewingPlayer)) return;
        for (int i = 0; i < 9; i++){
            if (spotMatrix[topSpots][i] == 1){
                if (rotation == 0)
                    g.fillOval(xC+topGridMatrix[i][0]-1, yC+topGridMatrix[i][1]-1, 7, 7);
                else if (rotation == 90)
                    g.fillOval(xC-topGridMatrix[i][1]-7, yC+topGridMatrix[i][0]-1, 7, 7);
                else if (rotation == 180)
                    g.fillOval(xC-topGridMatrix[i][0]-6, yC-topGridMatrix[i][1]-6, 7, 7);
                else if (rotation == 270)
                    g.fillOval(xC+topGridMatrix[i][1]-1, yC-topGridMatrix[i][0]-7, 7, 7);
            }
        }

        for (int i = 0; i < 9; i++){
            if (spotMatrix[bottomSpots][i] == 1){
                if (rotation == 0)
                    g.fillOval(xC+bottomGridMatrix[i][0]-1, yC+bottomGridMatrix[i][1]-1, 7, 7);
                else if (rotation == 90)
                    g.fillOval(xC-bottomGridMatrix[i][1]-7, yC+bottomGridMatrix[i][0]-1, 7, 7);
                else if (rotation == 180)
                    g.fillOval(xC-bottomGridMatrix[i][0]-6, yC-bottomGridMatrix[i][1]-6, 7, 7);
                else if (rotation == 270)
                    g.fillOval(xC+bottomGridMatrix[i][1]-1, yC-bottomGridMatrix[i][0]-7, 7, 7);
            }
        }
    }

    private boolean isInOpponentHomeArea(int y, int player){
        if (player == 1) return (y < 125);
        else return (y > 651);
    }
}


public class Player1 extends JApplet implements KeyListener, MouseListener, MouseMotionListener, Runnable{

    private ArrayList<CDomino> p1Dominoes;
    private ArrayList<CDomino> p2Dominoes;
    private CDomino activeDomino;
    private String statusMessage;

    public Player1(){
    }

    public void run(){
        setFocusable(true);
        addKeyListener(this);
        addMouseListener(this);
        addMouseMotionListener(this);
        initialize();
        showWindow();
    }

    public void initialize(){
        statusMessage = "Initializing window...";
        p1Dominoes = new ArrayList<CDomino>();
        p2Dominoes = new ArrayList<CDomino>();
        for (int i = 0; i < 7; i++){
            p1Dominoes.add(new CDomino(85 + i*100, 715, 0, 1));
            p2Dominoes.add(new CDomino(85 + i*100, 60, 0, 2));
        }
        activeDomino = null;
    }

    public void paint(Graphics g){

        Image img = createImage(getSize().width, getSize().height);
        Graphics gimg = img.getGraphics();
        gimg.setColor(new Color(235, 235, 235));
        gimg.clearRect(0, 0, getSize().width, getSize().height);
        gimg.fillRect(0, 0, 800, 800);

        gimg.setColor(Color.MAGENTA);
        gimg.drawLine(0, 125, 800, 125);
        gimg.drawLine(0, 650, 800, 650);
        gimg.setColor(new Color(200, 255, 200));
        gimg.fillRect(0, 0, 800, 125);
        gimg.setColor(new Color(180, 230, 255));
        gimg.fillRect(0, 651, 800, 125);

        gimg.setColor(Color.RED);
        gimg.setFont(new Font("SansSerif", Font.BOLD, 18));
        gimg.drawString(statusMessage, 10, 630);

        for (CDomino domino : p1Dominoes) domino.draw(gimg, 1);
        for (CDomino domino : p2Dominoes) domino.draw(gimg, 1);


        g.drawImage(img, 0, 0, null);
    }

    public void setStatusMessage(String message){
        statusMessage = message;
        repaint();
    }

    public ArrayList<CDomino> getP1Dominoes(){
        return p1Dominoes;
    }

    public void mouseDragged(MouseEvent e) {
        if (e.isMetaDown()) return;
        for (CDomino domino : p1Dominoes){
            if ((domino.isInside(e.getX(), e.getY()) && activeDomino == null) || (activeDomino == domino)){
                    activeDomino = domino;
                    domino.setPosition(e.getX(), e.getY());
                    repaint();
            }
        }
    }

    public void mouseMoved(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    public void mouseClicked(MouseEvent e) {
        //if (!e.isMetaDown()) return;
        tryRotate(e);
    }

    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    public void mousePressed(MouseEvent e) {
        }

    private void tryRotate(MouseEvent e) {
        if (!SwingUtilities.isRightMouseButton(e)) return;
        for (CDomino domino : p1Dominoes){
            if (domino.isInside(e.getX(), e.getY())){
                domino.rotate();
                repaint();
            }
        }
    }

    public void mouseReleased(MouseEvent e) {
        activeDomino = null;
    }

    public void keyPressed(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {

    }

    public void keyTyped(KeyEvent e) {

    }

    public void showWindow(){
        JFrame application = new JFrame("Dominoes - Player 1 (Server)");
        application.add(this);
        application.setDefaultCloseOperation(3);
        application.setSize(800, 800);
        application.setLocationRelativeTo(null);
        application.setVisible(true);
        application.setResizable(false);
    }

}

(Player2.java is very similar, but with a setP1Dominoes() that DOES call repaint().)

Upvotes: 0

Views: 176

Answers (2)

user207421
user207421

Reputation: 310913

You need to look up ObjectOutputStream.reset() and what is for. Call it after every writeObject().

Upvotes: 2

laune
laune

Reputation: 31290

The problem I see is here:

public void paint(Graphics g){
    Image img = createImage(...);
    //...
}

Thus, each call creates another Image. - Make the declaration of Image img a class variable and initialize it elsewhere so that paint starts with getting the Graphics object.

Somewhat strange - the Client's main calls:

p1GameThread.run()

which is not the correct way to start a thread; this is done by calling Thread.start(). But then the run methods should listen to the other side's socket messages.

Don't use sleep to determine the time for another send. Listeners detect when an operation on the table is complete: this is the time for sending.

Don't use two different Player classes - this will create an ever-growing number of pitfalls. Playing (except for setting the first move) is symmetrical, and so a single Player class should be sufficient. - Some sort of "referee" may be required to synchronize actions - as there can't be two moves of one player in a row - add it to another class present on both sides.

Upvotes: 0

Related Questions