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

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

Jogos de tabuleiro Multiplayer

Apresentações semelhantes


Apresentação em tema: "Jogos de tabuleiro Multiplayer"— 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 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 * marcoreis */ public class UtilComunicacao { * Abre um socket entre o cliente e o servidor * O servidor deve estar esperando (accept) esta requisicao dadosDeConexao Nome do servidor remoto e porta 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 * mapaRecuperado Mapa sincronizado */ public Map sincronizaMapas(Map<String, String> 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 socket Conexao aberta entre cliente e servidor Mapa enviado */ public Map extrairMapa(Socket socket) { try { InputStream dados = socket.getInputStream(); ObjectInputStream ois = new ObjectInputStream(dados); Object o = ois.readObject(); Map<String, String> mapaRecuperado = (Map<String, String>) 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 * 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<String, String> 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 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
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 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."); } * private UtilComunicacao getUtilComunicacao() { if (utilComunicacao == null) { utilComunicacao = new UtilComunicacao(); return utilComunicacao;

11 JogoDaVelha /** * pontoClicado Coordenadas do clique do usuario 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 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); JogoDaVelha

13 JogoDaVelha /** * Desenha a respectiva imagem dada uma posicao e um jogador posicaoX posicaoY 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 Mapa atual public Map<String, String> getMapaDeCasas() { if (mapaDeCasas == null) { mapaDeCasas = new HashMap<String, String>(); return mapaDeCasas; public void setMapaDeCasas(Map<String, String> 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 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 jogo Tabuleiro do seu jogo 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<String, String> 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"

Apresentações semelhantes


Anúncios Google