A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Jogos de tabuleiro Multiplayer Marco Antonio. Apresentação Jogos multiplayer fazem uso de threads para gerenciar múltiplas tarefas, além de sockets para.

Apresentações semelhantes


Apresentação em tema: "Jogos de tabuleiro Multiplayer Marco Antonio. Apresentação Jogos multiplayer fazem uso de threads para gerenciar múltiplas tarefas, além de sockets para."— Transcrição da apresentação:

1 Jogos de tabuleiro Multiplayer Marco Antonio

2 Apresentação Jogos multiplayer fazem uso de threads para gerenciar múltiplas tarefas, além de sockets para envio de pacotes entre computadores. Na aplicação a seguir temos vários exemplos de como isso pode ser implementado.

3 DadosDeConexao package com.javagames.tabuleiro; /** * Armazena os dados de conexao da aplicacao * * Porta local - utilizada para o ServerSocket * Porta remota - utilizada para o socket cliente * Servidor - nome/ip da maquina remota * O servidor + porta remota sao utilizados para enviar os dados a cada jogada * Nao e necessario indicar o nome/ip da maquina local * Nome do usuario - utilizado para personalizar sua partida * * @author marcoreis * */ public class DadosDeConexao { private int portaLocal; private int portaRemota; private String servidor; private String nomeDoUsuario; {...Metodos de acesso...} }

4 UtilComunicacao package com.javagames.tabuleiro; import java.io.*; import java.net.*; import java.util.*; /** * Transporta os dados entre duas maquinas utilizando socket * Deve ser atualizada para suportar diferentes tipos de dados * Os metodos tem suporte apenas a Map * * @author marcoreis * */ public class UtilComunicacao { /** * Abre um socket entre o cliente e o servidor * O servidor deve estar esperando (accept) esta requisicao * * @param dadosDeConexao Nome do servidor remoto e porta * @param mapa - dados que serao enviados */ public void enviaDadosParaComputadorRemoto(DadosDeConexao dadosDeConexao, Map mapa) { try { Socket socket = new Socket(dadosDeConexao.getServidor(), dadosDeConexao.getPortaRemota()); OutputStream outSocket = socket.getOutputStream(); ObjectOutputStream saida = new ObjectOutputStream(outSocket); saida.writeObject(mapa); saida.close(); outSocket.close(); } catch (Exception e) { e.printStackTrace(); }

5 UtilComunicacao /** * Sincroniza dois mapas * Por definicao, um mapa nao tem repeticao de chaves (keys) * Isso garante que nao havera posicoes repetidas * * @param mapaRecuperado * @return Mapa sincronizado */ public Map sincronizaMapas(Map mapaRecuperado) { Map mapa = new HashMap(); for (Object o : mapaRecuperado.keySet()) { mapa.put(o.toString(), mapaRecuperado.get(o)); } return mapa; }

6 UtilComunicacao /** * * E o outro lado do metodo enviaDadosParaComputadorRemoto * Enquanto o primeiro esta no cliente, este esta no servidor * Converte os dadso em Map, ou seja, nao suporta outros tipos de dados * * @param socket Conexao aberta entre cliente e servidor * @return Mapa enviado */ public Map extrairMapa(Socket socket) { try { InputStream dados = socket.getInputStream(); ObjectInputStream ois = new ObjectInputStream(dados); Object o = ois.readObject(); Map mapaRecuperado = (Map ) o; return mapaRecuperado; } catch (Exception e) { e.printStackTrace(); return null; }

7 JogoDaVelha package com.javagames.tabuleiro; import java.awt.*; import java.awt.event.*; import java.util.*; import javax.swing.*; import com.javagames.util.*; /** * Jogo da velha multiplayer * Utiliza sockets para comunicar as jogadas entre jogadores * * @author marcoreis * */ @SuppressWarnings("serial") public class JogoDaVelha extends JFrame { private static final int QUANTIDADE_DE_CASAS = 3; private int ALTURA = 350; private int LARGURA = 300; private Map mapaDeCasas; private String jogadorAtual; private Point pontoClicado; private DadosDeConexao dadosDeConexao; private UtilComunicacao utilComunicacao;

8 JogoDaVelha /** * MŽtodo construtor * Inicializacao dos parametros obrigatorios */ public JogoDaVelha() { setSize(LARGURA, ALTURA); setBackground(Color.BLUE); adicionaEventoCliqueDoMouse(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } /** * Chama o construtor padrao * @param dados - Dados de conexao informado pelo usuario */ public JogoDaVelha(DadosDeConexao dados) { this(); this.dadosDeConexao = dados; setTitle("Bem-vindo, " + dados.getNomeDoUsuario()); } /** * Adicionar listener para cliques do mouse */ private void adicionaEventoCliqueDoMouse() { addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { eventoCliqueDoMouse(e); } }); }

9 JogoDaVelha /** * Algoritmo a ser implementado * @return Se o jogador atual ganhou ou nao */ private boolean ganhou() { try { int contador = 0; //Verifica se ganhou na vertical for (int i = 0; i < 3; i++) { //Verifica se as posicoes estao ocupadas pelo jogador atual for (int j = 0; j < 3; j++) { // if (posicao[i][j] != null && posicao[i][j].equals(jogadorAtual)) { // contador++; // } //Caso tenha as tres posicoes ocupadas, retorna true, jogador atual ganhou if (contador == 3) { return true; } //Quando muda de coluna, zera o contador contador = 0; } } catch (Exception e) { } return false; }

10 JogoDaVelha /** * Calcula a celular que deve ser utilizada a partir do ponto clicado na tela * @param pontoClicado */ private void marcaPosicao(Point pontoClicado) { int indiceX = pontoClicado.x / (getTamanhoDaCasaX()); int indiceY = pontoClicado.y / (getTamanhoDaCasaY()); String posicao = indiceX + "," + indiceY; getMapaDeCasas().put(posicao, jogadorAtual); //Envia os dados para a thread do oponente, que esta esperando getUtilComunicacao().enviaDadosParaComputadorRemoto(dadosDeConexao, getMapaDeCasas()); setTitle(dadosDeConexao.getNomeDoUsuario() + ", voce jogou. Aguarde."); } /** * * @return {@link} */ private UtilComunicacao getUtilComunicacao() { if (utilComunicacao == null) { utilComunicacao = new UtilComunicacao(); } return utilComunicacao; }

11 JogoDaVelha /** * * @param pontoClicado Coordenadas do clique do usuario * @return Se o quadrante clicado est ou nao ocupado */ private boolean posicaoJahMarcada(Point pontoClicado) { int indiceX = pontoClicado.x / (getTamanhoDaCasaX()); int indiceY = pontoClicado.y / (getTamanhoDaCasaY()); String posicao = indiceX + "," + indiceY; if (getMapaDeCasas().get(posicao) != null) { return true; } return false; } /** * Calculo para definir o tamanho das celulas utilizadas. * Jamais utilize valores fixos, pois isso impede a evolucao do sistema * @return Tamanhos */ private int getTamanhoDaCasaY() { return ALTURA / QUANTIDADE_DE_CASAS; } private int getTamanhoDaCasaX() { return LARGURA / QUANTIDADE_DE_CASAS; }

12 JogoDaVelha /** * Desenha/redesenha a tela a cada clique * Ou, na versao multiplayer, a cada jogada */ public void paint(Graphics g) { super.paint(g); //Vertical g.drawLine((LARGURA / 3), 30, (LARGURA / 3), ALTURA - 10); g.drawLine((LARGURA / 3) * 2, 30, (LARGURA / 3) * 2, ALTURA - 10); //Horizontal g.drawLine(10, ALTURA / 3, LARGURA - 10, ALTURA / 3); g.drawLine(10, (ALTURA / 3) * 2, LARGURA - 10, (ALTURA / 3) * 2); imprimeMapaNoTabuleiro(); // } /** * Imprime o mapa no tabuleiro * A chave (key) do mapa esta no formato 'x,y' * Por isso temos o stringtokenizer que recupera cada valor separado pela ',' * Em seguida le cada posicao marcada do mapa, recuperando o jogador marcado * Por fim, desenha na celula x,y a imagem respectiva * O loop le todos os elementos que compoe o mapa naquele momento * */ public void imprimeMapaNoTabuleiro() { for (Object o : getMapaDeCasas().keySet()) { //o (formato x,y) try { StringTokenizer s = new StringTokenizer(o.toString(), ","); int posicaoX = new Integer(s.nextToken()) * getTamanhoDaCasaX() + 30; int posicaoY = new Integer(s.nextToken()) * getTamanhoDaCasaY() + 50; // String jogador = getMapaDeCasas().get(o); desenhaIcone(posicaoX, posicaoY, jogador); // } catch (Exception e) { System.out.println(e); }

13 JogoDaVelha /** * Desenha a respectiva imagem dada uma posicao e um jogador * @param posicaoX * @param posicaoY * @param jogador */ private void desenhaIcone(int posicaoX, int posicaoY, String jogador) { Graphics g = getGraphics(); if (jogador.equals("X")) { g.drawImage(UtilImagem.getImagem("zero.png"), posicaoX, posicaoY, this); } else { g.drawImage(UtilImagem.getImagem("xis.png"), posicaoX, posicaoY, this); } /** * Armazena todas as jogadas ate o presente instante * @return Mapa atual */ public Map getMapaDeCasas() { if (mapaDeCasas == null) { mapaDeCasas = new HashMap (); } return mapaDeCasas; } public void setMapaDeCasas(Map mapaDeCasas) { this.mapaDeCasas = mapaDeCasas; }

14 JogoDaVelha /** * Efetua todas as operacoes referentes ao evento clique do mouse * A cada jogada do usuario, o jogo deve aplicar todas as regras definidas * Alem de informar se algo nao esta correto * @param e Ponto clicado na tela */ private void eventoCliqueDoMouse(MouseEvent e) { pontoClicado = e.getPoint(); defineJogador(); if (posicaoJahMarcada(pontoClicado)) { JOptionPane.showMessageDialog(null, "Posicao ja ocupada.", "Atencao", JOptionPane.WARNING_MESSAGE); } else { repaint(); marcaPosicao(pontoClicado); } if (ganhou()) { JOptionPane.showMessageDialog(null, "Ganhou"); } /** * Nas duas primeiras jogadas da partida verifica quem e quem * O primeiro jogador sera '0' * O segundo sera 'X' */ private void defineJogador() { if (getMapaDeCasas().keySet().size() == 0 && jogadorAtual == null) { jogadorAtual = "0"; } else if (getMapaDeCasas().keySet().size() == 1 && jogadorAtual == null) { jogadorAtual = "X"; }

15 ThreadJogoDaVelha package com.javagames.tabuleiro; import java.net.*; import java.util.*; public class ThreadJogoDaVelha extends Thread { private DadosDeConexao dadosDeConexao; private JogoDaVelha jogo; private UtilComunicacao utilComunicacao; /** * Metodo construtor que exige os dados de conexao e o seu tabuleiro * * Esta classe gerencia as jogadas do oponente atraves do socket * Observacao: Nao ha controle para bloquear o jogador depois do clique * Isso permite que alguem jogue duas vezes * * @param jogo Tabuleiro do seu jogo * @param dados Informacoes necessarias para conectar os tabuleiros */ public ThreadJogoDaVelha(JogoDaVelha jogo, DadosDeConexao dados) { this.dadosDeConexao = dados; this.jogo = jogo; }

16 ThreadJogoDaVelha /** * A thread fica aguardando ate a jogada do oponente * Apos a jogada, bloqueia a thread (accept) * Assim que o oponente jogar, sincroniza os mapas * */ @SuppressWarnings("unchecked") public void run() { // while (true) { try { jogo.repaint(); Thread.sleep(1000); //Aguarda jogada do oponente //Bloqueia a thread ServerSocket server = new ServerSocket(dadosDeConexao.getPortaLocal()); Socket socket = server.accept(); //O oponente jogou jogo.setTitle(dadosDeConexao.getNomeDoUsuario() + ", agora Ž sua vez."); //Processa jogada //Recupera o mapa de jogadas do oponente Map mapaRecuperado = getUtilComunicacao().extrairMapa( socket); //Sincroniza o seu tabuleiro Map mapaDeCasas = getUtilComunicacao().sincronizaMapas(mapaRecuperado); jogo.setMapaDeCasas(mapaDeCasas); jogo.imprimeMapaNoTabuleiro(); //Desbloquear os recursos apos sua utilizacao socket.close(); server.close(); // } catch (Exception e) { System.out.print("..."); }

17 ThreadJogoDaVelha private UtilComunicacao getUtilComunicacao() { if (utilComunicacao == null) { utilComunicacao = new UtilComunicacao(); } return utilComunicacao; }

18 Splash Screen No Netbeans, crie uma tela com os componentes indicados. Inicie seu jogo e informe os dados do oponente. O botão de conectar deve iniciar uma thread do JogoDaVelha passando todos os dados necessários (veja o próximo slide).

19 Conexão private void btnConectarActionPerformed(java.awt.event.ActionEvent evt) {//GEN- FIRST:event_btnConectarActionPerformed DadosDeConexao dados = new DadosDeConexao(); dados.setPortaLocal(new Integer(txtPortaLocal.getText())); dados.setPortaRemota(new Integer(txtPortaServidor.getText())); dados.setServidor(txtServidor.getText()); dados.setNomeDoUsuario(txtNome.getText()); JogoDaVelha jogo = new JogoDaVelha(dados); new ThreadJogoDaVelha(jogo, dados).start(); setVisible(false); }//GEN-LAST:event_btnConectarActionPerformed


Carregar ppt "Jogos de tabuleiro Multiplayer Marco Antonio. Apresentação Jogos multiplayer fazem uso de threads para gerenciar múltiplas tarefas, além de sockets para."

Apresentações semelhantes


Anúncios Google