вторник, 1 мая 2012 г.

(АРХИВ GLES1) Бэкграунд. Текст.

Здесь будет рассмотрено создание бэка и вывод текста.
На видео есть стрельба пульками, но этот вопрос будет рассмотрен позже.

Бэкграунд. Когда я впервые сделал бэкграунд - я сделал его по аналогии с простым спрайтом. Однако, позже я выяснил, что можно несколько оптимизировать установку бэка. Для создания текстуры спрайтов мы используем такую конструкцию:
package ru.sapfil.andengine.test1;
this.mTexture = new BitmapTextureAtlas(64, 64, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
Если для бэка изменить последний параметр на TextureOptions.DEFAULT - производительность приложения резко возрастает. Так же хочется отметить, что для любого спрайта требуется создавать текстуру, стороны которой равны 2 в n- ной степени. Иначе не работает. Для моего телефона с разрешением 320*480 приходится использовать текстуру 512*512. При этом сама картинка png может быть меньшего размера. До установки бэка FPSLogger выдавал мне 80-90 кадров в секунду. С бэком - резко упало до 20. Мой телефон довольно слабый и текстура 512*512 - слишком тяжелая для него. Чтож... позже придется сделать опцию по отключению бэка. Ну а вот сам код, который нужно добавить в проект для установки бэка. Кончено, надо не забыть закинуть текстурку бэка в gfx/assets.
package ru.sapfil.andengine.test1;
/** добавить переменные в начало кода */
 private BitmapTextureAtlas mBackTexture1;
 private TextureRegion mBackTextureRegion1;
 private Sprite mBackSprite1;

/** добавить этот код в onLoadResources() */
// создаем текстуру, указываем в ней текстурный регион, загружаем текстуру в текстурный менеджер движка 
    this.mBackTexture1 = new BitmapTextureAtlas(512, 512, BitmapTextureFormat.RGB_565, TextureOptions.DEFAULT);
    this.mBackTextureRegion1 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBackTexture1, this, "Back1.png", 0, 0);
    this.mEngine.getTextureManager().loadTexture(this.mBackTexture1);

/** добавить этот код в onLoadScene() */
 this.mBackSprite1 = new Sprite(0, 0, 320, 480, this.mBackTextureRegion1);
 this.mBackSprite1.setIgnoreUpdate(true);
 SpriteBackground bg = new SpriteBackground(mBackSprite1);
 mScene.setBackground(bg);
Текст. Мне захотелось увидеть хоть какой-то текст в моем приложении. Чтобы что-то писать на экране - надо загрузить шрифт в формате ttf. Кидаем нужный нам шрифт в папочку assets/fonts. Задаем размер текстуры для шрифта. Размер выбираем опытным путем. Если размер будет слишком мал - некоторые символы просто не будут печататься, на их месте будет всякая чушь. Символы в текстуре движок разместит сам при помощи инструмента FontFactory. Вот код, который вывел мне небольшую надпись в верхнем углу экрана:
package ru.sapfil.andengine.test1;
/** добавить переменные в начало кода */
// текстура под шрифт
private BitmapTextureAtlas mFontTexture;
// переменная для шрифта
private Font mFont;

/** добавить этот код в onLoadResources() */
// создаем текстуру для шрифта. Размер текстуры выбираем опытным путем (в данном случае 128*64)
this.mFontTexture = new BitmapTextureAtlas(128, 64, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
// заполняем шрифтовую текстуру. Здесь 16 - размер шрифта.
this.mFont = FontFactory.createFromAsset(mFontTexture, this, "fonts/Postmodern_One.ttf", 16, true, Color.WHITE);
// далее по аналогии со спрайтами - загружаем готовую текстуру в текстурный менеджер
this.mEngine.getTextureManager().loadTexture(this.mFontTexture);
.. загружаем шрифт в менеджер шрифтов
this.mEngine.getFontManager().loadFont(this.mFont);

/** добавить этот код в onLoadScene() */
// 0,0 - коодринаты, в которые помечается верхний левый угол блока с текстом.
// HorizontalAlign.LEFT - выравнивание текста по левому краю блока
final Text textLeft = new Text(0, 0, this.mFont, "Points: 0", HorizontalAlign.LEFT);
// Добавить текст в сцену
mScene.attachChild(textLeft);
Изменяемый текст. Конечно хорошо, что мы что-то написали на экране. Однако хотелось бы иметь возможность текст менять. Например, изменять количество очков, заработанных игроком. Или какие-нибудь еще параметры цифровые обозначать. Ну а лично мне нравится прямо на экран выводить дебаг-информацию. ФПС, количество объектов на экране и еще что-нибудь. На самом деле все просто. Вот пример строчки с изменяемым содержимым.
package ru.sapfil.andengine.test1;

/** добавить переменные в начало кода */
private ChangeableText objectsText;

/** добавить этот код в onLoadScene() */
objectsText = new ChangeableText(0, 40, this.mFont, "Objects:", HorizontalAlign.LEFT, "Objects: XXXXX".length());
mScene.attachChild(objectsText);

/** добавить этот код в основной цикл игры */
objectsText.setText("Objects: " + AE_Test1_Activity.this.mEngine.getScene().getChildCount());
Вместо "Objects: XXXXX".length() можно было бы поставить просто число, обозначающее максимальное количество символов в строчке. В данном случае 14. Но так, как сделано тут - нагляднее. Так же на видео видноеще два параметр - ФПС и прошедшее время. Код там почти начисто слизан из официального примера. Единственное отличие - переменные я все-таки вынес в начало кода.

2 комментария:

  1. В вашем примере не всё описано.
    И если добавлять последний печатаемый текст с координатами не 0, 0 то "кораблик" вылетает за экран. Как бы координаты камеры для "кораблика" начинаются с последнего напечатанного текста.

    Для тех, кто хочет менять графику: текстуру надо объявлять больше реальной или вылетит с ошибкой.
    this.mBackTexture1 = new BitmapTextureAtlas(1024, 512, BitmapTextureFormat.RGB_565, TextureOptions.DEFAULT);
    this.mBackTextureRegion1 = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBackTexture1, this, "background.png", 0, 0);
    Например если текстура background.png имеет разрешение 1020х600, то надо указывать: "...BitmapTextureAtlas(1024, 1024, BitmapTextureFormat...". Надеюсь понятно написал :).

    В общем кому интересно вылаживаю рабочий исходник:
    https://docs.google.com/open?id=0B6rzuB-A4HPkcXFRSXp6bnNibWc

    В моём варианте изменен экран (разрешение горизонтальный 800х480). Выводится время работы, FPS, количество объектов.

    ОтветитьУдалить
    Ответы
    1. Хм. Странно, что там какая-то ошибка с координатами кораблика.
      Но в данный момент я работаю с версией GLES2 и проект уже полностью переделан подж эту версию. По-этому если ошибка и была, теперь уже трудно найти ее.

      Да, естественно что для хранения графики надо брать больший или равный размер карты.
      [i]Пример - нам надо нарисовать квадрат размером 20 на 20 сантиметров на бумаге. Мы можем взять лист А4 и нарисовать на нем, его размеры позволяют. Но если нам потребуется квадрат 25 на 25 сантиметров - тогда уж придется взять литок формата А3. И при этом смириться, что довольно большая часть листа не используется.[/i]
      Применительно к программированию - надо не просто выбрать размер, равный или больше нужного. Надо еще, чтобы размер текстуры по длине и ширине был кратен степени 2. ТО есть 2,4,8,16,32,64,128,256,512,1024. То есть если нажно хранить картинку 600 на 600 - придется взять текстуру 1024 на 1024. При этом часть этой картинки можно использовать для хранения других спрайтов.

      Кстати, я пробовал интересую вещь. Дело в том. что при добавлении БЭКа, который большой по размеру - ФПС сильно проседает. Я пробовал не использовать текстуру 512 на 512, а использовать 2 текстуры 256 на 512. Или 4 текстуры 256 на 256. Я подозревал, что хранение именно больших по размерам текстур просаживает быстродействие. Однако, оказалось, что почти нет никакой разницы, как хранить большую текстуру - полностью или частями. При этом, возможно, хранение частями даже хуже, ведь для каждый части надо использовать свои переменные. И при равном количестве хранимой графической информации - количество переменных в программе больше и по-этому производительность проекта может быть даже хуже.

      Удалить