Customers do not communicate in the same multiplayer game in Java

Asked

Viewed 149 times

4

I’m trying to make a simple tank multiplayer game by implementing chat. The game and the chat are all ok! However, I can’t get 2 customers to view the same object Arena.

In this case, each customer who joins 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();
    }

}
  • 1

    Please access the following link to learn how to provide a [mcve] so that we can execute the code and simulate the problem.

  • Caroline, why do you think there are two arenas? More specifically, at which point of debug you stopped and inspected and saw that there were two instances of Arena?

  • When each customer connects, he must confirm a tank within the Arena. But, he displays an Arena with only one tank. Does not show opponent’s tank

  • Hi Caroline. This I understand, but you need to say how you know this, what appears in debug, etc.

  • p.s.: When you reply to a comment put it to who it is with @Carolineteixeira, for example. You get all comments notifications, but others don’t. That’s why I only saw your new comment today.

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 is because in the connection receiving processing code, in each Accept you create a new Server object, probably because in your project you made the Server inherit from Thread and imagined that you should create a new instance for each new client (which is partly true).

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

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.