Uma animação nada mais é do que uma sequência de quadros (também chamados de frames) que simula um movimento. Podemos criar animações simples repetindo imagens e exibindo-as uma após a outra. Utilizando o laço for, por exemplo, poderemos exibir uma sequência de frames que irá simular um movimento, como no código a seguir:
public class animacao
extends Applet
{
public void start()
{
for (animframe = 0; animframe < nenhum_dos_frames;
animframe ++)
{
// configura um quadro
setup_animacao_frame(animframe);
// redesenhando a tela para um novo quadro
repaint()
// faz um intervalo de 0,1 segundos (100 milionesimos de segundo)
entre cada frame
try
{
Thread.sleep (100);
} catch (InterruptedException e) {};
}
}
// outras instruções
}
Esse código possui um problema: a chamada do método repaint() não desenha imediatemente na tela. Java coleta solicitações para pintar a tela de maneira que possa executá-las quando não existirem outros eventos para serem processados. Como o laço for do método start() não permite que sejam enviadas mensagens de evento, Java não poderá repintar a tela até que seja finalizado o laço for. Para contornar este problema, criaremos uma linha de execução (thread), como mostra o código seguinte:
public class animacao
extends Applet implements Runnable
{
Thread anime = null;
public void start()
{
anime = new Thread(this);
anime.start();
}
public void run()
{
for (animframe = 0; animframe < nenhum_dos_frames;
animframe ++)
{
// configurando o quadro
setup_animacao_frame (animframe);
// redesenhando a tela
repaint();
// faz um intervalo de 0,1 segundos (100 milionésimos
de segundo) entre os frames
try
{
Thread.sleep (100);
} catch (InterruptedException e) {};
}
}
// outras instruções
}
O exemplo anterior implementa a interface Runnable, que permite a execução de uma linha independente.
Vejamos agora uma animação completa escrita em Java (marquee.java). Nesta aplicação, a string Aprendendo Java aparece atravessando a janela do applet da esquerda para a direita. Para executar o movimento, a string será redesenhada na tela a cada 0,1 segundos (100 milésimos de segundo). Esse efeito é semelhante àquele gerado pela tag <MARQUEE> em HTML.
import java.applet.*;
import java.awt.*;
public class marquee extends Applet implements Runnable
{
int xpos = 0;
Thread anime = null;
Image file_img;
public void start()
{
if (anime = null)
{
anime = new Thread(this);
anime.start();
}
}
public void paint(Graphics g)
{
while (anime != null)
{
xpos+= 10;
if (xpos > size().width)
xpos = 0;
repaint();
try
{
Thread.sleep (100);
}
catch (InterruptedException e) {};
}
}
}
Como podemos ver, a string é redesenhada
na tela a cada 0,1 segundos utilizando-se cada vez uma coordenada
x diferente.
Esta mesma técnica de redesenhar sequências de
objetos na tela pode ser utilizada com imagens. Vejamos agora
um exemplo (logogif.java) de um logotipo Java animado em três
dimensões. Para isso, usaremos seis imagens .gif, que
serão redesenhadas a cada 0,2 segundos (200 milionésimos
de segundo).
import java.applet.*;
import java.awt.*;
public class logogif extends Applet implements Runnable
{
int img_index = 0;
Thread anime = null;
String im_nomes[] = (java1.gif, java2.gif,
java3.gif, java4.gif,
java5.gif, java6.gif};
mage java_img[] = new Image[6];
public void init()
{
for (int i = 0; i < 6; i++)
java_img[i] = getImage (getCodeBase(), img_nomes[i]);
}
public void start()
{
if (anime = null)
{
anime = new Thread(this);
anime.start();
}
}
public void paint (Graphics g)
{
g.drawImage (java_img[img_index], 0, 0, this);
}
public void run()
{
while (anime != null)
{
img_index++;
if (img_index > 5)
img_index = 0;
repaint();
try
{
Thread.sleep(200);
}
catch (InterruptedException e) {};
}
}
}
Quando você executar este applet, irá notar uma certa cintilação (conhecida como flickering). O flickring é o resultado do desaparecimento de toda a área do desenho com a cor de fundo. Quando o código chama o método repaint() para redesenhar a tela, este chama o método update(), cuja função é exatamente apagar todas as áreas do desenho com a cor de fundo. Só que, como o código chama o método paint() (responsável por desenhar toda a área de exibição), o método update() não possui utilidade neste caso é só contribui para o aumento da cintilação.
Podemos resolver este inconveniente sobrescrevendo
o método update() ou evitando a chamada do método
repaint() para redesenhar a tela, passando diretamente para
o método paint().
O código seguinte sobrescreve o método update(),
eliminando a operação de apagar:
public void update (Graphics
g)
{
paint(g);
}
Vale lembrar que esta sobrescrição
funciona somente quando o método paint() redesenha
toda a área de exibição.
Podemos também não chamar a o método
repaint() e passar diretamene a chamar o método paint().
Neste caso, teremos:
Graphics g = getGraphics();
paint(g);
Por hora, ficamos por aqui. Na semana que vem, concluiremos nossa passagem pela parte de multimídia com Java criando um efeito especial de desaparecimento (fading). Um abraço e até lá!