| Назад
    Вперед 6.4. Спрайтовая анимацияВ этом примере мы покажем, как можно
    использовать многопоточность для организации в
    приложениях Java спрайтовой анимации. Исходный текст примера Архив проекта для Java WorkShop 2.0  Демонстрация(ваш браузер должен уметь работать с аплетами
    Java JDK 1.1)
 Немного теорииМногопоточность находит свое применение в
    создании анимационных изображений, оживляющих
    приложения Java.  Как создать анимацию?  Простейший способ заключается в использовании
    спрайтов - набора изображений для всех кадров
    анимации. При поочередном отображении этих
    кадров в окне приложения с достаточно высокой
    скоростью возникает эффект анимации.  Прежде чем приложение Java приступит к анимации,
    оно должно дождаться завершения загрузки всех
    кадров. Это необходимо потому, что время загрузки
    файлов отдельных спрайтов через сеть Internet может
    быть значительным. К счастью, приложениям Java
    доступен класс MediaTracker, специально
    предназначенный для решения такой задачи.  Что же касается самого процесса рисования
    спрайтов, то он должен выполняться в отдельном
    потоке при помощи метода drawImage.  Описание примераНаш пример аплета рисует в своем окне фрагмент
    неба с облаками, который раскачивается из одной
    стороны в другую. В верхней части окна вы можете
    увидеть номер текущего отображаемого
    фрейма (рис. 1).   
 Рис. 1. Бегущие облака в окне аплета  Сразу после инициализации аплет приступает к
    загрузке спрайтов, о чем можно судить по стоке
    Loading (рис. 2).   
 Рис. 2. Идет загрузка файлов отдельных спрайтов  Рассмотрим исходный текст аплета.  Главный класс аплетаГлавный класс аплета создан на базе класса Applet
    и реализует интерфейс Runnable:  import java.applet.Applet;
import java.awt.*;
public class SkyMove extends Applet
  implements Runnable
{
  . . .
}В нем мы определили четыре поля.  Поле thr класса Thread хранит ссылку на поток,
    выполняющий анимацию в окне аплета:  Thread thr = null; Поле bImagesLoaded используется как признак
    завершения процесса загрузки изображений
    спрайтов:  boolean bImagesLoaded = false; В поле nCurrentImage мы храним номер текущего спрайта,
    отображаемого в процессе анимации:  int nCurrentImage = 0; И, наконец, массив im хранит ссылки на все
    изображения спрайтов, составляющих анимацию:  Image[] im; Методы start и stop Эти методы запускают и останавливают поток
    анимации, соответственно, при активизации аплета
    и при прекращении его работы:  public void start()
{
  if(thr == null)
  {
    thr = new Thread(this);
    thr.start();
  }
}
public void stop()
{
  if(thr != null)
  {
    thr.stop();
    thr = null;
  }
}Они устроены также, как и аналогичные методы в
    наших предыдущих приложениях.  Метод runРассмотрим исходный текст метода run.  Прежде всего этот метод устанавливает
    начальное значение для номер текущего
    отображаемого кадра анимации, равное нулю:  nCurrentImage = 0; Далее если изображения еще не загружены (а
    сразу после первого запуска метода run так оно и
    будет), метод выполняет в цикле загрузку всех
    спрайтов:  if(!bImagesLoaded)
{
  im = new Image[40];
      
  MediaTracker mt = new MediaTracker(this);
  String s;
      
  for(int i = 1; i < 41; i++)
  {
    s = "pic" + ((i < 10) ? "0" : "") 
      + i + ".gif";
        
    im[i - 1] = 
      getImage(getDocumentBase(), s);
          
    mt.addImage(im[i - 1], 0);  
  }
  . . .
}Ссылки на загруженные изображения
    записываются в массив im.  Чтобы дождаться завершения процесса загрузки,
    мы пользуемся методом waitForAll:  try
{
  mt.waitForAll();
  bImagesLoaded = !mt.isErrorAny();
}
catch(InterruptedException ie)
{
  stop();
}Этот метод возвращает признак успешного
    завершения загрузки, инверсное значение
    которого сохраняется в переменной bImagesLoaded.  На следующем этапе загруженные спрайты будут
    отображаться в окне аплета.  Вначале мы получаем ссылку на контекст
    отображения g и устанавливаем флаг направления
    отображения спрайтов flip:  Graphics g = getGraphics();
boolean flip = true; При этом спрайты будут отображаться в прямом
    направлении, то есть от первого к последнему.  Отображение выполняется в цикле и только при
    условии, что все изображения загружены:  while(true)
{
  if(bImagesLoaded)
  {
    . . .
  }
}Мы рисуем спрайт (методом drawImage) и его номер
    (методом drawString):  g.drawImage(im[nCurrentImage],
  0, 0, null);
        
g.drawString("Frame: " +
 (nCurrentImage + 1), 10, 30);    Далее мы проверяем флаг направления
    отображения спрайтов и изменяем соответствующим
    образом номер текущего спрайта:  if(flip)
{  
  nCurrentImage++;
        
  if(nCurrentImage > 38)
    flip = false;
}  
else
{
  nCurrentImage--;
          
  if(nCurrentImage < 1)
    flip = true;
}В конце каждой итерации выполняется задержка
    на 30 миллисекунд:  try
{
  thr.sleep(30);
}
catch(InterruptedException ie)
{
  stop();
}     Метод paintИсходный текст метода paint выглядит следующим
    образом:  public void paint(Graphics g)
{
  if(!bImagesLoaded)
    g.drawString("Loading...", 10, 30);    
}Если изображения не загружены, метод рисует в
    окне строку "Loading...". После загрузки данная
    строка затирается спрайтами.  
 Назад Вперед |