среда, 14 ноября 2012 г.

Игра на Java под Swing

Сейчас занимаюсь разработкой игры на Java, ориентируясь на Android, но ядро платформонезависимо. Поэтому для отладки использую Desktop версию. В Desktop версии графику реализовал через Swing. Для простоты в качестве элементов управления использую стандартные компонеты Swing. Для отрисовки графики испольую компонет Canvas.

Компонент Canvas
Унаследован от класса Component, специально предназначен для отрисовки на нем графики. На самом деле ничего особенного он из себя не представляет (убедиться можно посмотрев его исходный код). Он скорее своим названием декларирует что на нем будут рисовать. 
Класс предоставляет для переопределения метод paint(Graphics g), который выполняется при необходимости перерисовки.
Класс также предоставляет методы для использования двойной буфферизации (ДБ):  createBufferStrategy(int numBuffers) и getBufferStrategy().
Метод createBufferStrategy создает numBuffers буфферов. После его вызова можно использовать getBufferStrategy для получения объекта класса BufferStrategy, который предоставляет доступ к ДБ. Он имеет следующие важные методы:
  • getDrawGraphics() -- возвращает объект класса Graphics, на котором нужно рисовать.
  • show() -- отображает нарисованную в буфере картинку на экран (на компонент).
Т. е. для того чтобы отрисовать что-либо с использованием ДБ, нужно сделать следующее:
Canvas canv = new Canvas();
canv.createBufferStrategy(2);
Graphics g = canv.getDrawGraphics();
g.setColor(Color.RED);
g.drawRect(10, 10, 100, 100);
...
Цветофильтр
В игре используется цветовой фильтр для изменения цвета объектов (спрайтов). AWT предоставляет несколько способов для фильтрации (вродебы), я же использую класс RGBImageFilter. Он абстрактный и имеет абстрактный метод filterRGB(int x, int y, int rgb), который и нужно реализовать для наложения фильтра. Он должен возвращать цвет (int) пиксела в позиции (x, y). Параметр rgb -- исходный цвет пиксела. Чтобы применить этот фильтр к нужной картинке (Image), нужно сделать так:

FilteredImageSource filteredSrc = new FilteredImageSource(img.getSource(), filter);
Image filteredImage =  Toolkit.getDefaultToolkit().createImage(filteredSrc);

где, filter - это созданный ранее объект класса RGBImageFilter.

Доступ к ресурсам
Java позволяет хранить файлы различных типов непосредсвенно в jar файле. Для доступа к ним существует метод getClass().getResourceAsStream(name), где name -- путь к файлу ресурса. Путь включает /имя_файла.расширение. Имена пакетов разделяются символом /.
Например если вы поместили ваш файл empty.png в пакет com.yourname.resources.images, то путь к нему будет /com/yourname/resources/images/empty.png.
Метод возвращает поток для чтения (InputStream), далее с помощью ImageIO.read(inputStream) можно считать файл картинки в память.

Настройки пользователя
Для того чтобы хранить настройки и сохранения игры в папке пользователя создается подпапка ".название_гры". Получить путь к папке пользователя можно так:

System.getProperty("user.home");


Хранение данных
Данные храню в XML-файлах. Например карты хранятся в ресурсах в подкаталоге worlds. Их содержимое загружается в патмять с помощью сериализации. Для этого используется библиотека simple-xml. Она позволяет сериализировать и десериализировать объекты в стиле .NET (см. пост Сериализация в C#).

Кое-что
На Java я раньше не писал и игры не писал тоже (кроме простейшей игрухи на XNA). Поэтому в ходе работы я узнавал и понимал кое-что новое:
  • Картинки нужно кешировать. В игре используется разворот картинок, наложение фильтров и масштабирование. Все эти операции нагружают процессор. И когда я запустил игру (без кеширования), то заметил насколько сильно. 
  • Ну очевидно что нужно использовать ДБ, без нее никак.
  • При проектировании нужно максимально отделять логику игры от её графики.
  • Отрисовка графики тоже имеет логику) и нужно максимально отделить платформозависимую её часть от общей. Например класс Color является частью библиотеки AWT, и его не слудует использоват в ядре (движке) игры. Потом все равно придется переделывать чтобы заработало под Android.
Пожалуйста, оставляйте комментарии)

1 комментарий:

  1. Благодарю, твоя статья помогла в кое чем разобраться!)

    ОтветитьУдалить