Problemas com Datagram... MouseListener e repaint()

2 respostas
duardor

Seguinte galera:
Me foi proposto um trabalho de redes que era pra fazer um joguinho em tempo real utilizando pacotes UDP… pacotes UDP em java são relacionados nas classes que tem inicio Datagram do pacote java.net
Implementei um joguinho que tem um JPanel com fundo branco… O servidor manda um objeto MatrizQuadrado que tem uma matriz de int [9][9] e os scores dos jogadores (4) para cada cliente conectado… quando um cliente recebe algo da rede (em uma Thread separada soh pra isso) ele chama o metodo repaint() do JPanel de modo que ele percorre a matriz recebida e onde tiver posicao 1 ele faz um quadrado vermelho)…
Quando o usuario clica na tela (no JPanel) ele manda para o servidor qual posicao da matriz ele clicou. O servidor verifica se ele clicou em uma posicao 1 e se sim ele dah o ponto para o jogador, atribui a posicao a 0 e faz um random()*9 para x e y para atribuir uma nova posição para 1. nAssim ele replica esse obejto matriz para todos os jogadores e o ciclo se repete…
O problema eh o seguinte:
Minha thread de interface de usuario e de envio de mensagens é a mesma… As vezes quando clico na tela o programa dah uma congeladinha e a mensagem nao chega ao servidor…
Vcs acham que seria aconselhavel separar a interface grafica tambem do metodo de manda mensagens de modo que fiquem em Threads diferentes??? Ou sera q a congeladinha eh por causa dos constantes repaint() que chamo no JPanel (eh um painel de 500X500 pixels!)…
Aguardo sugestões!!!

Obrigado a todos!

2 Respostas

dukejeffrie

Puxa, ninguém se arriscou a responder a sua pergunta, eu vou tentar.

Separar o model do view é sempre bom. Vamos por partes…

  1. Envio de mensagem.

Voce deveria usar uma outra Thread para enviar a sua mensagem. Ou usar um Channel (do pacote nio). Jamais usar a AWT Dispatcher (que é quem ouve o seu clique) para fazer tarefas pesadas.

  1. Modelo.

Sua matriz deveria ser um objeto. Um objeto que tenha as suas responsabilidades, por exemplo, descobrir se uma posição dá pontos ou não, e se auto-atualizar:

public boolean isHit(int position);
public void updateAfterHit();

Voce pode, depois, ir melhorando o seu modelo: se a sua matriz é esparsa (poucos valores não-nulos), talvez seja melhor manter uma lista de… valores não-nulos! Se vc só tem, na matriz inteira, uma única posição não-nula? Por que você não guarda apenas ela?

public boolean isHit(int position) {
  if (position == mosca) return true;
  else return false;
}

Um java.util.HashSet pode ser um ótimo armazenador para posições não-nulas…

  1. replicação de dados
    Em vez de mandar tudo a cada vez, vc pode mandar apenas as alterações. Por exemplo, a nova posição 1 e qual jogador acertou (podendo ser nenhum). Assim, se todos os clientes conhecem as regras, eles podem atualizar suas próprias matrizes.

  2. repaint() e eventos.

Já começou bem chamando o repaint() em vez de inventar um jeito mirabolante. O repaint() deve ser chamado a partir da Thread que leu a mensagem, e por último, após fazer todas as atualizações no modelo. O que esse método faz é colocar o componente numa lista. De tempos em tempos, a AWT Thread lê esta lista e faz as operações necessárias para pintá-lo (chamando o paint(Graphics)).

Múltiplos repaints não interferem em nada. Se o objeto já está na lista de espera, ele não é colocado de novo. Só garanta que vc está chamando repaint no seu JPanel, pra ele não repintar tudo (sei lá, digamos, o JFrame inteiro).

  1. Camada de comunicação, protocolo, etc.

Por que UDP? Vc sabe que o UDP não garante algumas coisas que o TCP garante, né? Pra começar:

i. Pacotes podem não chegar ao destino
ii. Pacotes podem chegar ao destino fora de ordem.

Se você precisa de confirmação, vc tem que elaborar seu próprio esquema de ACKs (aí é da sua matéria, meu!!). Pode ser que o seu programa trave porque o servidor não soube ler a mensagem (chegada fora de ordem) ou ela não chegou nunca. E vc tem que mandar de novo se vc não tolera perdas.

De modo geral, mensagens UDP muito grandes tendem a se perder. Se o seu datagrama é grande e contém o objeto inteiro serializado, é bom considerar as alternativas pra diminuir o tamanho dele. Agora imagina os Warcrafts da vida, que trabalham com a ordem de 500 a 1000 alterações por segundo, comunicação direta entre os clientes, tolerancia baixa a falhas e ainda têm que renderizar um monte de coisas!! : )

boa sorte!!

[]s

duardor

Ae dukkie…
Eu fiz alguns tunnings no programa e funfou legal…
Valeu pela ajuda, mas quando eu vi sua mensagem jah tinha apresentado o trab…
T+
Valew pela boa vontade!!!

Abraços

Criado 9 de abril de 2003
Ultima resposta 14 de abr. de 2003
Respostas 2
Participantes 2