Поиск по блогу

воскресенье, 1 апреля 2012 г.

Начало работы с libGDX

Сегодня я хочу немного рассказать про игровой движок libGDX. Это достаточно популярный открытый игровой 2D/3D движок для платформы Android. Раньше я пробовал начинать работать с его главным конкурентом движком AndEngine, но в итоге перешел на libGDX из-за слабой документации и сложностей с тестированием у AndEngine.
Главной фишкой libGDX является мультиплатформенная разработка. Приложение пишется независимым от платформы и потом для портирования достаточно лишь добавить загрузчик для нужной платформы.
Итак, перейдем к делу. Здесь я расскажу как написать простейшее приложение с использованием libGDX, которое будет работать как на PC, так и на Android. Начнем.
В первую очередь качаем свежайшую сборку libGDX отсюда. Нам нужен файл libgdx-nightly-latest.zip.
Теперь запускаем Eclipse. Типичное приложение на libGDX состоит из трех проектов - это базовый проект, загрузчик для PC и загрузчик для Android. Сперва создадим базовый проект. Нам нужен обычный Java Project. Назовем его HelloWorldLibGdx. Далее создаем в нем папку libs. Туда мы должны положить файлы gdx.jar и gdx-sources.jar из архива с libGDX. Добавляем gdx.jar в build path. Также добавляем к gdx.jar исходники (может быть полезно при отладке) и потом во вкладке Order & Export ставим галочку на gdx.jar. В итоге должно быть так:
Следующий проект - загрузчик для PC. Создаем еще один Java Project. Имя - HelloWorldLibGdxDesktop. Опять создаем папку libs. Кладем туда gdx-natives.jar, gdx-backend-lwjgl.jar и gdx-backend-lwjgl-natives.jar. Добавляем все эти библиотеки в build path. Также добавляем туда базовый проект. Получиться должно примерно так:
И последние проект - загрузчик для Android. Тут уже создаем Android Project. Имя - HelloWorldLibGdxAndroid. Build target можно выбрать любой. И опять создаем папку libs. Копируем туда gdx-backend-android.jar, а также папки armeabi и armeabi-v7a. Добавляем gdx-backend-android.jar в build path (если она сама не подхватилась из папки libs). Также в build path добавляем gdx.jar из базового проекта. Добавляем и сам базовый проект, а потом ставим для него галочку в Order & Export. Результат должен быть такой:
Все, мы готовы кодить. В базовом проекте создаем класс HelloWorld и пишем в нем:
public class HelloWorld implements ApplicationListener {
SpriteBatch spriteBatch;
Texture texture;
BitmapFont font;
Vector2 textPosition = new Vector2(100, 100);
Vector2 textDirection = new Vector2(1, 1);
@Override
public void create() {
font = new BitmapFont();
font.setColor(Color.RED);
texture = new Texture(Gdx.files.internal("data/your_texture.jpg"));
spriteBatch = new SpriteBatch();
}
@Override
public void dispose() {}
@Override
public void pause() {}
@Override
public void render() {
int centerX = Gdx.graphics.getWidth() / 2;
int centerY = Gdx.graphics.getHeight() / 2;
Gdx.graphics.getGL10().glClear(GL10.GL_COLOR_BUFFER_BIT);
textPosition.x += textDirection.x * Gdx.graphics.getDeltaTime() * 60;
textPosition.y += textDirection.y * Gdx.graphics.getDeltaTime() * 60;
if (textPosition.x < 0) {
textDirection.x = -textDirection.x;
textPosition.x = 0;
}
if (textPosition.x > Gdx.graphics.getWidth()) {
textDirection.x = -textDirection.x;
textPosition.x = Gdx.graphics.getWidth();
}
if (textPosition.y < 0) {
textDirection.y = -textDirection.y;
textPosition.y = 0;
}
if (textPosition.y > Gdx.graphics.getHeight()) {
textDirection.y = -textDirection.y;
textPosition.y = Gdx.graphics.getHeight();
}
spriteBatch.begin();
spriteBatch.setColor(Color.WHITE);
spriteBatch.draw(texture, centerX - texture.getWidth() / 2, centerY - texture.getHeight() / 2, 0, 0, texture.getWidth(), texture.getHeight());
font.draw(spriteBatch, "Hello World!", (int)textPosition.x, (int)textPosition.y);
spriteBatch.end();
}
@Override
public void resize(int width, int height) {
spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
textPosition.set(0, 0);
}
@Override
public void resume() {}
}
Данный код просто отображает текстуру в центре экрана, а также создает анимированный текст, который перемещается по экрану. Прошу обратить внимание на выделенный красным текст - это имя файла с картинкой-текстурой. Замените его именем своего файла. Разрешение текстуры должно быть степенью двойки - т.е. допустимы 128х128, 256х256 и так далее. Также прошу обратить внимание на то, что текстура должна лежать в папке data. Так что создаем папку data для проекта с загрузчиком для PC и кладем туда нужную картинку. Для Android-проекта есть небольшое отличие - папку data с картинкой нужно создать в папке assets.
Теперь осталось написать загрузчики и все готово. Для PC в проекте HelloWorldLibGdxDesktop создаем класс HelloWorldDesktop, который содержит всего одну строку:
public static void main(String[] args) {
new LwjglApplication(new HelloWorld(), "Hello World", 480, 320, false);
}
 Теперь проверим как он работает:
Отлично! Остался загрузчик для Android. Открываем дефолтную activity в проекте HelloWorldLibGdxAndroid и редактируем ее так:
public class HelloWorldLibGdxAndroidActivity extends AndroidApplication {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initialize(new HelloWorld(), false);
    }
}
Как видите, опять всего одна строка. Теперь запускаем эмулятор и видим что-то вроде этого:
Вот и готово первое приложение на libGDX :-)

10 комментариев:

  1. Как обычно у меня заморочки на самом простом - вставке нужного кода что бы все работало .. в базовом проекте в классе все строчки помечены красным крестиком с лампочкой :)) мне кажется что я накосячил в названии класса .. :\
    Кстати у тебя здесь упрощенный мануал :) мне понятнее было пройти поэтапно по англ. версии (до редактирования кода), как новичку ..

    ОтветитьУдалить
    Ответы
    1. Да, я не стал тут вдаваться в подробности - а то гайд получился бы очень большим. Тут только необходимый минимум.
      А что снизу в Problems пишет?

      Удалить
  2. ApplicationListener cannot be resolved to a type
    BitmapFont cannot be resolved to a type
    и так 70 штук .. может import надо сделать?
    блин .. позор мне, как на лабах))

    ОтветитьУдалить
    Ответы
    1. Юрик, все правильно, импорт решит проблему :-)

      Удалить
  3. Почему-то слегка мерцает текст. Это только у меня и в чем может быть проблема?

    ОтветитьУдалить
    Ответы
    1. Мерцает в настольном приложении или на Android? Или и там, и там?

      Удалить
    2. в настольном приложении.

      Удалить
    3. Хм, у меня такого точно не было. Попробуйте в конструкторе LwjglApplication false на true поменять - может помочь.

      Удалить
    4. Разницы нет.
      Единственное что более менее помогает это выключение вертикальной синхронизации.

      conf.vSyncEnabled = false;
      new LwjglApplication(new Game(), conf);

      Но все равно какие то искажения пробегают.
      Если говорить точнее, то с вертикальной синхронизацией визуально кажется, что рас в секунду тормозит прорисовка и по картинке(тексту) пробегает мерцающая полоса. А без вертикальной синхронизации картинка(текст) двигается равномерно, но постоянно наблюдаются мелкие полоски искажения.

      К слову, если сравнивать с Unity3d, то там включение синхронизации решает полностью эту проблему.

      Удалить
    5. Специально запустил у себя код - такого поведения не наблюдаю. Сложно сказать в чем причина. Возможно дело в особенностях взаимодействия libGDX и драйвера видеокарты.

      Удалить