Jogos de tabuleiro
Multiplayer
Marco Antonio
Apresentação
• Jogos multiplayer fazem uso de threads para
gerenciar múltiplas tarefas, além de sockets
para envio de paco...
DadosDeConexao
package com.javagames.tabuleiro;
/**
* Armazena os dados de conexao da aplicacao
*
* Porta local - utilizad...
UtilComunicacao
package com.javagames.tabuleiro;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* Transporta...
UtilComunicacao
/**
* Sincroniza dois mapas
* Por definicao, um mapa nao tem repeticao de chaves (keys)
* Isso garante que...
UtilComunicacao
/**
*
* E o outro lado do metodo enviaDadosParaComputadorRemoto
* Enquanto o primeiro esta no cliente, est...
JogoDaVelha
package com.javagames.tabuleiro;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax....
JogoDaVelha
/**
* MŽtodo construtor
* Inicializacao dos parametros obrigatorios
*/
public JogoDaVelha() {
setSize(LARGURA,...
JogoDaVelha
/**
* Algoritmo a ser implementado
* @return Se o jogador atual ganhou ou nao
*/
private boolean ganhou() {
tr...
JogoDaVelha
/**
* Calcula a celular que deve ser utilizada a partir do ponto clicado na tela
* @param pontoClicado
*/
priv...
JogoDaVelha
/**
*
* @param pontoClicado Coordenadas do clique do usuario
* @return Se o quadrante clicado est‡ ou nao ocup...
/**
* Desenha/redesenha a tela a cada clique
* Ou, na versao multiplayer, a cada jogada
*/
public void paint(Graphics g) {...
JogoDaVelha
/**
* Desenha a respectiva imagem dada uma posicao e um jogador
* @param posicaoX
* @param posicaoY
* @param j...
JogoDaVelha
/**
* Efetua todas as operacoes referentes ao evento clique do mouse
* A cada jogada do usuario, o jogo deve a...
ThreadJogoDaVelha
package com.javagames.tabuleiro;
import java.net.*;
import java.util.*;
public class ThreadJogoDaVelha e...
ThreadJogoDaVelha

/**
* A thread fica aguardando ate a jogada do oponente
* Apos a jogada, bloqueia a thread (accept)
* A...
ThreadJogoDaVelha
private UtilComunicacao getUtilComunicacao() {
if (utilComunicacao == null) {
utilComunicacao = new Util...
Splash Screen
•

No Netbeans, crie uma tela com
os componentes indicados.

•

Inicie seu jogo e informe os
dados do oponen...
Conexão
private void btnConectarActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_btnConectarActionPerform...
Próximos SlideShares
Carregando em…5
×

Apostila de Jogos em Rede com Java

2.815 visualizações

Publicada em

Como criar o jogo da velha usando Java. Pode ser jogado em rede, utilizando sockets. As telas são feitas com Swing.

Publicada em: Tecnologia
0 comentários
1 gostou
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
2.815
No SlideShare
0
A partir de incorporações
0
Número de incorporações
7
Ações
Compartilhamentos
0
Downloads
162
Comentários
0
Gostaram
1
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Apostila de Jogos em Rede com Java

  1. 1. Jogos de tabuleiro Multiplayer Marco Antonio
  2. 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. 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. 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. 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<String, String> mapaRecuperado) { Map mapa = new HashMap(); for (Object o : mapaRecuperado.keySet()) { mapa.put(o.toString(), mapaRecuperado.get(o)); } return mapa; }
  6. 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<String, String> mapaRecuperado = (Map<String, String>) o; return mapaRecuperado; } catch (Exception e) { e.printStackTrace(); return null; } } }
  7. 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<String, String> mapaDeCasas; private String jogadorAtual; private Point pontoClicado; private DadosDeConexao dadosDeConexao; private UtilComunicacao utilComunicacao;
  8. 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. 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 (getMapaDeCasas().get(i + "," + j) != null && getMapaDeCasas().get(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. 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. 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. 12. /** * 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(); // } JogoDaVelha /** * 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. 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("xis.png"), posicaoX, posicaoY, this); } else { g.drawImage(UtilImagem.getImagem("zero.png"), posicaoX, posicaoY, this); } } /** * Armazena todas as jogadas ate o presente instante * @return 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. 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. 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. 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. 17. ThreadJogoDaVelha private UtilComunicacao getUtilComunicacao() { if (utilComunicacao == null) { utilComunicacao = new UtilComunicacao(); } return utilComunicacao; } }
  18. 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. 19. Conexão private void btnConectarActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST: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

×