Threads

segue em anexo o codigo da pequena animacao…para ficar mais facil de resolver o meu problema.

Eu queria saber como fazer para que o meu fundo de tela pare de piscar!!!
o meu professor sugeriu que eu usasse o paintcomponents, mais nao consegui…que q vcs me mostrem como usa-lo.

Ficarei grata se alguem puder me ajudar!!

Em primeiro lugar, não duplique tópicos. Você poderia ter dado continuidade ao assunto no seu post original:
http://www.guj.com.br/posts/list/57701.java
E nem sequer ter criado esse segundo post:
http://www.guj.com.br/posts/list/57585.java

E nem esse terceiro, que estou respondendo agora…

Bem, tenho uma série de sugestões a fazer… Na verdade, tem bastante coisa para melhorar no seu algoritmo. Se você quer partir diretamente para a solução do seu problema, leia o meu próximo post. Mas tire um tempo para ler esse, depois.

  1. O método pintar() deve ser chamado antes do método contaTempo(). Caso contrario, a tela pode piscar no primeiro quadro (você terá contado o tempo, antes de exibir qualquer imagem);

2.Existe uma regra no swing de que o objeto graphics não deve ser alterado. Para corrigir isso, sempre que utilizar um método do swing (paint, paintComponent, paintComponents, paintChildren ou paintBorder), faça o seguinte:

public void paint(Graphics g) { Graphics tela = g.create(); //Aqui vai o seu código normal tela.dispose(); }

No geral, essa é uma boa prática. Você garante que um método de pintura não irá interferir no outro.

  1. O segredo para uma boa aplicação de animações está naquele loop, que você chamou de inicioAnimacao.

Quem deve controlar o seu próprio x, y e z são as classes que serão pintadas na tela, ou classes específicas para objetos da animação.

Geralmente, vão ser criadas classes com dois métodos, que serão chamados por seu animation loop:

processLogics(); (Ajusta o x, y e z do objeto animado)
renderGraphics(); (Pinta o objeto)

O animation loop (ou MainLoop), fica com a árdua tarefa de manter a taxa de processamento da lógica constante (independente da velocidade do hardware), enquanto mantém ao máximo possível a atualização dos gráficos (em chamadas ao paint()). Geralmente “o máximo possível” é a taxa de atualização do monitor, ou seja, em torno de 75 quadros em um segundo: mais do que isso é desperdício de processamento.

Esse tipo de abordagem é válido tanto para uma animação estática quanto para jogos de computador. Quanto à isso, fiz esse post no meu blog que explica como funciona um bom animation loop.

Existe uma ótima teoria sobre o animation loop, imagens e animação no site do livro Killer Game Programming in Java.

Agora que as sugestões foram dadas, vamos ao seu problema específico, o flickering.

Flickering é o fato da tela “piscar”. Por que isso ocorre? Isso ocorre porque a imagem é exibida enquanto é desenhada. Como parte dela está pronta e parte não está, você tem a impressão da tela estar piscando. Isso acontece muito rapidamente.

As técnicas utilizadas para eliminar isso são chamadas Double Buffering e Page Flipping. Como isso funciona? Basicamente você trabalhará com duas imagens, uma que está em memória e outra que está desenhada na tela. Você faz os desenhos na imagem que não está sendo exibida e depois “troca” ela com a que está sendo exibida. O fato de ter duas imagens é o tal Double Buffering e troca-la de maneira imediata é o page flipping.

Como implementamos isso? O Java possui a classe BufferStrategy para te auxiliar a usar double buffering. Os componentes do swing também tem suporte direto a esse recurso. Faremos o seguinte:

  1. Primeiramente, na última linha do construtor da janela, vamos indicar para ela que queremos double buffering. Na última linha do seu construtor faça:

public Janela() { //Código de inicialização createBufferStrategy(2); //Queremos double buffering }

  1. Depois, vamos alterar o método paint. Primeiramente, não usaremos o método paint do java diretamente. Deixemos que ele gerencie a pintura para nós. Altere o nome do método paint para pintar. Pintar não precisa receber nenhum parâmetro (nem mesmo o objeto graphics).

Na primeira linha do método pintar, pedimos a nossa BufferStrategy para retornar o objeto graphics da imagem em memória. Na última, pedimos para que esse objeto seja exibido:

private void pintar() { //Pedimos a imagem em memória Graphics tela = getBufferStrategy().getDrawGraphics().create(); //Aqui vai o código que estava no seu paint original tela.dispose(); //Liberamos a memória do objeto Graphics getBufferStrategy().show(); //Fazemos o page flipping, exibindo a tela recém desenhada. }

Agora, só falta corrigir o método inicioAnimacao() para chamar pintar() ao invés de repaint().

Pronto! O flickering foi embora!