Clients do not communicate in the same multiplayer game in Java

4

I'm trying to make a simple multiplayer tank game by implementing chat. The game and the chat are all ok! However, I can not get 2 clients to see the same object Arena .

In this case, each customer joining creates a tank in the arena. However, whenever I try to run, it creates a different arena for each player.

public class Arena extends JComponent implements MouseListener, ActionListener, KeyListener {
    private Tanque apontado;
    private int largura, altura;
    private HashSet<Tanque> tanques;
    private Tiro tiro;
    private Timer contador;
    private long agora;

    public Arena(int largura, int altura) {
        this.largura = largura;
        this.altura = altura;
        tanques = new HashSet<Tanque>();
        tiro = new Tiro(-40, -10, 0, null, -1);
        addMouseListener(this);
        addKeyListener(this);
        setFocusable(true);
        contador = new Timer(40, this);
        contador.start();
        agora = 1;
    }

    public void adicionaTanque(Tanque t) {
        tanques.add(t);
    }

    public Dimension getMaximumSize() {
        return getPreferredSize();
    }

    public Dimension getMinimumSize() {
        return getPreferredSize();
    }

    public Dimension getPreferredSize() {
        return new Dimension(largura, altura);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(new Color(245, 245, 255));
        g2d.fillRect(0, 0, largura, altura);
        g2d.setColor(new Color(220, 220, 220));
        for (int _largura = 0; _largura <= largura; _largura += 20)
            g2d.drawLine(_largura, 0, _largura, altura);
        for (int _altura = 0; _altura <= altura; _altura += 20)
            g2d.drawLine(0, _altura, largura, _altura);
        // Desenhamos todos os tanques
        for (Tanque t : tanques) {
            t.draw(g2d);
        }
        tiro.draw(g2d);

    }

    public void mouseClicked(MouseEvent e) {
        for (Tanque t : tanques)
            t.setEstaAtivo(false);
        for (Tanque t : tanques) {
            boolean clicado = t.getRectEnvolvente().contains(e.getX(), e.getY());
            if (clicado) {
                t.setEstaAtivo(true);
                apontado = t;
            }
        }
        repaint();
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }

    public void actionPerformed(ActionEvent e) {
        for (Tanque t : tanques) {
            t.mover();
            t.calculaTempo();
        }
        colisao();
        tiro.mover();
        repaint();
    }

    public void colisao() {
        if (tiro.estaAtivo) {
            for (Tanque t : tanques) {
                if (t.getId() != tiro.getId()) {
                    double dist = Math.sqrt(Math.pow(tiro.x - t.x, 2) + Math.pow(tiro.y - t.y, 2));
                    if (dist <= 20) {/* Distancia de acerto */
                        tiro.x = -10;
                        tiro.y = -10;
                        tanques.remove(t);
                        tiro.estaAtivo = false;
                        break;
                    }
                    /* Tanque detecta o míssil e tenta se esquivar */
                    if (dist < 100) {
                        t.setTempo(System.currentTimeMillis());

                        if (agora % 2 == 0)
                            t.girarAntiHorario(7);
                        else
                            t.girarHorario(7);

                        t.velocidade = 6;
                    }
                }

            }
        }
        for (Tanque t : tanques) {
            autoColisao(t);
        }

    }

    public void autoColisao(Tanque tanque) {
        for (Tanque t : tanques) {/* verifica a distancia para checar colisão entre os tanques */
            if (tanque.getId() != t.getId()) {
                double dist = Math.sqrt(Math.pow(tanque.x - t.x, 2) + Math.pow(tanque.y - t.y, 2));
                if (dist <= 30) { /* Colisão entre tanques */
                    if (t.velocidade > 0) {
                        t.velocidade *= -1;
                        t.girarAntiHorario(7);
                    } else {
                        t.velocidade = 2;
                        t.girarHorario(7);
                    }
                }

                if (dist < 80 && tanque.estaAtivo) {/* tanque inimigo tenta fugir */
                    t.setTempo(System.currentTimeMillis());
                    if (agora % 2 == 0)
                        t.girarAntiHorario(5);
                    else
                        t.girarHorario(5);

                    t.velocidade = 6;
                }

            }
        }
    }

    public void keyPressed(KeyEvent e) {
        for (Tanque t : tanques) {
            t.setEstaAtivo(false);
            if (t == apontado) {
                t.setEstaAtivo(true);
                switch (e.getKeyCode()) {
                case KeyEvent.VK_LEFT:
                    t.girarAntiHorario(3);
                    break;
                case KeyEvent.VK_UP:
                    t.aumentarVelocidade();
                    break;
                case KeyEvent.VK_DOWN:
                    t.diminuirVelocidade();
                    break;
                case KeyEvent.VK_RIGHT:
                    t.girarHorario(3);
                    break;
                case KeyEvent.VK_SPACE: {
                    atirar(t.getId());
                    agora = System.currentTimeMillis();
                }
                    break;
                }
                break;
            }
            repaint();
        }

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    public void atirar(int id) {
        for (Tanque t : tanques) {
            if (t.estaAtivo) {
                if (!tiro.estaAtivo) {
                    tiro.x = t.x;
                    tiro.y = t.y;
                    tiro.angulo = t.angulo;
                    tiro.cor = Color.RED;
                    tiro.setId(t.getId());
                    tiro.estaAtivo = true;
                }
            }
        }
    }
}

Server Code:

public class Servidor extends Thread {


/* Aqui vou criar um Array list para armazenar o BufferedWiter de cada 
 * jogador que se conecta no site.
 * O restante das variaveis tem nomes sugestivos
 */
private static ArrayList<BufferedWriter> clientes;
private static ServerSocket servidor; 
private String nickname; /*essa variavel vai servir para armeznar o nome do jogador cliente que o servidor recebe*/
private Socket conexao;
private InputStream entrada;  
private InputStreamReader leitura_entrada;  
private BufferedReader buffer; 

Arena arena = new Arena(640, 480);
JFrame janela = new JFrame("JTank");




public Servidor(Socket conexao) {

    this.conexao= conexao;
    try {



        entrada  = conexao.getInputStream();
         leitura_entrada = new InputStreamReader(entrada);
         buffer = new BufferedReader(leitura_entrada);
  } catch (IOException e) {
         e.printStackTrace();
  }                          
}


public void run(){


 janela.getContentPane().add(arena);
    janela.setResizable(false);
    janela.pack();
    janela.setVisible(true);        
    arena.adicionaTanque(new Tanque(500, 50, 180, Color.BLUE, 1));


  try{
    String mensagem;
    OutputStream ou =  this.conexao.getOutputStream();
    Writer ouw = new OutputStreamWriter(ou);
    BufferedWriter bfw = new BufferedWriter(ouw); 
    clientes.add(bfw);
    nickname = mensagem = buffer.readLine();


    while(!"Sair".equalsIgnoreCase(mensagem) && mensagem != null)
      { 



       mensagem = buffer.readLine();
       sendToAll(bfw, mensagem);
       System.out.println(mensagem);  


       }

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

   }                       
}      

public void sendToAll(BufferedWriter bwSaida, String msg) throws  IOException 
{
BufferedWriter bwS;



for(BufferedWriter bw : clientes){
bwS = (BufferedWriter)bw;
if(!(bwSaida == bwS)){ 

 bw.write(nickname + " -> " + msg+"\r\n");
 bw.flush();          
}
}          
}


public void chama_arena() {

}


public static void main(String []args) {

try{    

JLabel lblMessage = new JLabel("Porta do Servidor:");
JTextField txtPorta = new JTextField("12345");
Object[] texts = {lblMessage, txtPorta };  
JOptionPane.showMessageDialog(null, texts);
servidor = new ServerSocket(Integer.parseInt(txtPorta.getText()));
clientes = new ArrayList<BufferedWriter>();
JOptionPane.showMessageDialog(null,"Servidor ativo na porta: "+         
txtPorta.getText());

 while(true){
 System.out.println("Aguardando conexão...");
 Socket conexao = servidor.accept();
 System.out.println("Cliente conectado...");
 Thread t = new Servidor(conexao);
  t.start();   
   }

}catch (Exception e) {

e.printStackTrace();
}                       


}   



}

Client code:

public class Cliente extends JFrame implements ActionListener, KeyListener {



    private static final long serialVersionUID = 1L;
    private JTextArea texto;
    private JTextField txtMsg;
    private JButton btnEnviar;
    private JButton btnSair;
    private JLabel lblHistorico;
    private JLabel lblMsg;
    private JPanel pnlContent;
    private Socket socket;
    private OutputStream ou;
    private Writer ouw;
    private BufferedWriter bfw;
    private JTextField txtIP;
    private JTextField txtPorta;
    private JTextField txtNome;

    public Cliente() throws IOException {
        JLabel lblMessage = new JLabel("Verificar!");
        txtIP = new JTextField("127.0.0.1");
        txtPorta = new JTextField("12345");
        txtNome = new JTextField("Cliente");
        Object[] texts = { lblMessage, txtIP, txtPorta, txtNome };
        JOptionPane.showMessageDialog(null, texts);
        pnlContent = new JPanel();
        texto = new JTextArea(10, 20);
        texto.setEditable(false);
        texto.setBackground(new Color(240, 240, 240));
        txtMsg = new JTextField(20);
        lblHistorico = new JLabel("Histórico");
        lblMsg = new JLabel("Mensagem");
        btnEnviar = new JButton("Enviar");
        btnEnviar.setToolTipText("Enviar Mensagem");
        btnSair = new JButton("Sair");
        btnSair.setToolTipText("Sair do Chat");
        btnEnviar.addActionListener(this);
        btnSair.addActionListener(this);
        btnEnviar.addKeyListener(this);
        txtMsg.addKeyListener(this);
        JScrollPane scroll = new JScrollPane(texto);
        texto.setLineWrap(true);
        pnlContent.add(lblHistorico);
        pnlContent.add(scroll);
        pnlContent.add(lblMsg);
        pnlContent.add(txtMsg);
        pnlContent.add(btnSair);
        pnlContent.add(btnEnviar);
        pnlContent.setBackground(Color.LIGHT_GRAY);
        texto.setBorder(BorderFactory.createEtchedBorder(Color.BLUE, Color.BLUE));
        txtMsg.setBorder(BorderFactory.createEtchedBorder(Color.BLUE, Color.BLUE));
        setTitle(txtNome.getText());
        setContentPane(pnlContent);
        setLocationRelativeTo(null);
        setResizable(false);
        setSize(250, 300);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    /* Vou criar aqui um método chamado conectar.. Se conecta ao servidor */

    public void conectar() throws IOException {

        socket = new Socket(txtIP.getText(), Integer.parseInt(txtPorta.getText()));
        ou = socket.getOutputStream();
        ouw = new OutputStreamWriter(ou);
        bfw = new BufferedWriter(ouw);
        bfw.write(txtNome.getText() + "\r\n");
        bfw.flush();




    }

    /*
     *  metodo Enviar mensagem é responsável pela troca de mensagens dentro do servidor
     */
    public void enviarMensagem(String msg) throws IOException {

        if (msg.equals("Sair")) {
            bfw.write("Desconectado \r\n");
            texto.append("Desconectado \r\n");
        } else {
            bfw.write(msg + "\r\n");
            texto.append(txtNome.getText() + " diz -> " + txtMsg.getText() + "\r\n");
        }
        bfw.flush();
        txtMsg.setText("");




    }

    /*
     * Método para ler as mensagens recebidas pelo servidor
     */
    public void escutar() throws IOException {



        InputStream in = socket.getInputStream();
        InputStreamReader inr = new InputStreamReader(in);
        BufferedReader bfr = new BufferedReader(inr);
        String msg = "";


        while (!"Sair".equalsIgnoreCase(msg))

            if (bfr.ready()) {
                msg = bfr.readLine();
                if (msg.equals("Sair"))
                    texto.append("Servidor caiu! \r\n");
                else
                    texto.append(msg + "\r\n");
            }
    }

    /*
     * Método usado quando o usuário clica em sair
     */
    public void sair() throws IOException {

        enviarMensagem("Sair");
        bfw.close();
        ouw.close();
        ou.close();
        socket.close();
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        try {

            if (e.getActionCommand().equals(btnEnviar.getActionCommand()))
                enviarMensagem(txtMsg.getText());
            else if (e.getActionCommand().equals(btnSair.getActionCommand()))
                sair();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {

        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            try {
                enviarMensagem(txtMsg.getText());
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub
    }

    public static void main(String[] args) throws IOException {

        Cliente app = new Cliente();

        app.conectar();
        app.escutar();
    }

}
    
asked by anonymous 13.11.2017 / 06:23

1 answer

1

The problem is that your Arena object is not static, so it is an attribute of the Server class. This means that each time a Server object is created a new Arena object will also be created.

And this happens because in the incoming connection handling code, on each accept you create a new Server object, probably because in your project you made Server inherit from Thread and imagined that you should create a new instance for each new client (which is partly true).

That said, if you make Arena static it will solve (partially) your problem, but it would be ideal to revise the project so that you separate the treatment of connected clients from the object that controls the arena for example. On the server side you could rethink the tasks that are performed to be more modularized.

It would be nice, as I said, to separate at least the network treatment from the Arena treatment.

    
08.01.2018 / 16:03