Ноя
11

AndEngine. Базовые понятия

logo_100Продолжаем знакомство с AndEngine.

Первая часть здесь.

В этом уроке рассмотрим основные понятия движка.

Ещё раз повторюсь, что я ещё не полностью изучил весь движок. Поэтому пишу то, что пока знаю.

1. Класс Engine. Самый главный класс, который упраляет процессом вывода графики, проигрывания звуков и музыки, обрабатывает касания экрана, воспроизводит вибрацию, реагирует на акселерометр. И в своём основном цикле (update) заставляет работать все объекты в игре — от спрайтов до модификаторов (аналог Твинов во Flash).

engine

Разновидности движка (подклассы):

  • FixedStepEngine — движок с фиксированной частотой шагов в секунду. По аналогии с Flash здесь можно задать частоту кадров (например, 30 или 60);
  • LimitedFPSEngine — движок с фиксированной частотой кадров в секунду. По моим наблюдениям выдаёт меньше FPS, чем FixedStepEngine;
  • SingleSceneSplitScreenEngine — делит экран на две части и выводит в каждой части изображение ОДНОЙ сцены с двух разных камер;
  • DoubleSceneSplitScreenEngine — делит экран на две части и выводит в каждой части изображение ДВУХ разных сцен с двух разных камер;

2. Класс Camera. Не менее важный класс. Именно Camera отвечает за то, что вы увидите на экране. Всё, что за пределами камеры, на экране не видно. Размер камеры обычно устанавливается равным размеру экрана устройства.

scene1

Можно установить размер меньше, тогда всё оставшееся место на экране будет пустым (чёрным).

Подклассы Камеры:

  • BoundCamera — перемещается по сцене в заданных рамках;
  • ZoomCamera — камера с произвольным увеличением сцены. Расширяет класс BoundCamera;
  • SmoothCamera — расширяет ZoomCamera. Производит плавное увеличение/уменьшение зума при его изменении;

Камеру можно заставить следовать за каким-нибудь объектом (например, Главным Героем).

3. Сцена Scene. Сцена похожа на MovieClip во Flash. Она является контейнером для остальных объектов — других сцен, спрайтов, графических примитивов.

При создании игры обязательно нужно создать хотя бы одну сцену (в методе onLoadScene () нашего Activity).

Подклассы Scene:

  • SplashScene — сцена-заставка (типа экрана с логотипом разработчика во время запуска игры);
  • CameraScene — очень полезный класс, который позволяет отображать сцену на одном месте экрана, даже если камера перемещается по другой сцене. Если вы знакомы с Flixel, то сцена как бы имеет свойство scrollFactor.xy = 0;
  • PopupScene и TextPopupScene — расширение от CameraScene. Это просто сцены, которые появляются и исчезают через заданное время.

4. Класс Entity (Сущность). Это прародитель всех спрайтов, сцен и графических примитивов (линий и прямоугольников). Entity не может содержать графику. Но Entity может содержать в себе другие Entity.

Entity содержит методы по изменению цвета, масштабированию, повороту, видимости и прочие.

Entity можно использовать, например, как простой контейнер для спрайтов (вместо раздутого класса Scene). И потом на основную Сцену можно добавить уже несколько Entity (типа слои).

5. Класс BaseBackground и прочие — виды фонов для Сцены.

У Сцены, по умолчанию, есть задний фон — Background, залитый чёрный цветом. Однако его можно отключить или заменить на более интересный.

Фон (задник; бэкграунд) у Сцены изначально является неподвижным по отношению к камере. Т.е. фон всегда остаётся на месте, когда камера двигается по сцене.

Какие виды фонов предоставляет AndEngine:

  • ColorBackground — прямоугольник, залитый сплошным цветом;
  • EntityBackground — в качестве заднего фона рисуется содержимое Entity;
  • SpriteBackground— в качестве заднего фона рисуется содержимое спрайта;
  • RepeatingSpriteBackground — фон рисует повторяющийся спрайт;
  • ParallaxBackground — задний фон с эффектом перспективы. Добавляем в него спрайты и задаём им скорость горизонтального смещения. При прокрутке Камеры по Сцене по горизонтали спрайты движутся с разной скоростью, создавая эффект перспективы (надеюсь ясно объяснил? :). Движок сам заботится об исчезновении спрайтов с одной стороны экрана и появления с другой;
  • AutoParallaxBackground — расширяет ParallaxBackground, но при этом все спрайты на фоне движутся постоянно, независимо от движения камеры;

 

Добрались, наконец-то, до спрайтов 🙂

Спрайты бывают:

  • Sprite — обычные (один кадр);
  • TiledSprite — спрайт с несколькими кадрами;
  • AnimatedSprite — спрайт с несколькими кадрами + возможность анимации;

Для вывода графики AndEngine использует OpenGL. OpenGL использует Атласы изображений для рисования графики. Т.е. OpenGL берёт из Атласа заданную прямоугольную область и копирует её на экран.

opengl

Поэтому мы должны все наши спрайты и прочие картинки предварительно загрузить в эти Атласы. В AndEngine они называются BitmapTextureAtlas.

BitmapTextureAtlas ДОЛЖЕН иметь размеры, равные степеням 2 (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048). Например, 512×256 или 1024×1024. (Размер 2048 доступен только для OpenGL версии 2.0 и будет работать не на всех девайсах).

Графику можно загружать как напрямую из файлов (из папки assets), так и из ресурсов (папка res).

Лично мне нравится первый способ. Для удобства можно создать в папке assets подпапки gfx, fonts, sfx, music, levels и т.п.

assets

При загрузке графики в Атлас нужно указывать координаты. Нельзя допускать, чтобы графика разных спрайтов пересекалась в Атласе.

Лично я всю графику предварительно размещаю на чистом листе в Фотошопе, чтобы потом легко можно было узнать координаты той или иной графики (текстуры спрайта).

И желательно оставлять между текстурами зазор в 1 пиксель. Вот пример размещения нескольких текстур в Атласе:

atlas

Давайте теперь посмотрим на код нашего Activity. Вот как он выглядит:

package com.drderico.example;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;

import android.os.Bundle;

public class AndEngineExampleActivity extends BaseGameActivity {

	public static Camera mCamera;

	/**
	 * Размеры экрана и камеры
	 */
	public static final int Camera_width = 800;
	public static final int Camera_height = 480;

	/**
	 * Основная сцена игры
	 */
	public static Scene MainScene;

	/**
	 * Область на Атласе, в которую загружается графика для спрайта
	 */
	TextureRegion _Sprite_TR;

	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
	public Engine onLoadEngine() {
    	/**
    	 * Создаём камеру размером 800*480
    	 * Я ориентируюсь на экран своего Galaxy S
    	 */
		mCamera = new Camera(0, 0, Camera_width, Camera_height);
		/**
		 * Создаем движок с некоторыми опциями
		 */
		return new Engine(
				/**
				 * Опции движка
				 */
				new EngineOptions(
						true,	//режим Fullscreen = true
						ScreenOrientation.LANDSCAPE,	//ориентация экрана ГОРИЗОНТАЛЬНАЯ
						/**
						 * Здесь нужно указать правила для вывода графики
						 * На разных устройствах экран имеет разные свойства:
						 * разрешение экрана, плотность в точках/дюйм и прочие
						 *
						 *  В данном случае RatioResolutionPolicy позволит
						 *  движку отображать графику в игре без искажений на любых экранах,
						 *  т.е. вся графика будет ПРОПОРЦИОНАЛЬНО уменьшатся или
						 *  увеличиваться относительно заданного нами размера (800x480)
						 */
						new RatioResolutionPolicy(Camera_width, Camera_height),
						/**
						 * Указываем основную камеру для движка
						 */
						mCamera)
				.setNeedsSound(true)	//игра будет использовать звуки
				.setNeedsMusic(true));	//игра будет использовать музыку
	}

	@Override
	public void onLoadResources() {
		/**
		 * Указываем путь до графики. В данном случае графика будет загружаться из папки assets/gfx/
		 */
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

		/**
		 * Создаем Атлас, в который будем загружать графику.
		 * TextureOptions - задаёт режим вывода графики на экран.
		 * Если вы планируете масштабировать спрайты, изменять прозрачность и спрайты
		 * имеют изначально размыте края, то лучше ставить BILINEAR_PREMULTIPLYALPHA
		 * Тут нужно эскпериментировать
		 * Бывает:
		 * 		NEAREST
		 * 		NEAREST_PREMULTIPLYALPHA
		 * 		BILINEAR
		 * 		BILINEAR_PREMULTIPLYALPHA
		 *  	и др.
		 */
		BitmapTextureAtlas Texture1 = new BitmapTextureAtlas(512, 512, TextureOptions.NEAREST_PREMULTIPLYALPHA);

		/**
		 * Создаем регион (область) для спрайта в этом атласе.
		 * Нужно указать координаты региона в Атласе (0,0 в данном случае)
		 */
		_Sprite_TR = BitmapTextureAtlasTextureRegionFactory.createFromAsset(Texture1, this, "face.png", 0, 0);

		/**
		 * Теперь всё готово. Загружаем Атлас
		 */
		mEngine.getTextureManager().loadTextures(Texture1);
	}

	@Override
	public Scene onLoadScene() {
		/**
		 * Создаём основную сцену и запоминаем её
		 * в MainScene. Это упростит доступ к сцене из
		 * любого другого класса и сэкономит время.
		 * Иначе придётся каждый раз вызывать метод
		 * this.mEngine.getScene();
		 * чтобы получить доступ к Сцене
		 */
		MainScene = new Scene();
		return MainScene;
	}
	@Override
	public void onLoadComplete() {
		/**
		 * Всё прошло успешно. Текстуры загружены,
		 * движок создан, сцена создана.
		 * Самое время создать спрайт и добавить
		 * его на сцену
		 */
		Sprite _Sprite = new Sprite(100, 100, _Sprite_TR);
		MainScene.attachChild(_Sprite);
	}
}

Результат:

device-2011-11-14-104825

В следующем уроке поговорим об анимированных спрайтах и модификаторах (modifiers).

Скачать исходник примера




15 коммент. к записи “AndEngine. Базовые понятия”

  • отличная статья. Автору большое спасибо! Когда выйдет третья часть?

  • Спасибо за Ваш труд. Пожалуй это первый вменяемый цикл статей про AndEngine в рунете!

    • Рад, что кому-то пригодилось 🙂

  • Было бы хорошо, если продолжили писать.

    Большое спасибо.

  • Я бы хотел сказать спасибо за статью. Было бы очень хорошо, если бы вы продолжили писать про AndEngine. Статья очень помогла. Особенно помогают наглядные материалы — картинки(особенно та, с TextureBitmapAtlas) и области выделенные цветом.

    • Буду писать, как будет время

  • У меня появляются ошибки с требованием убрать @Override перед основными функциями движка (onLoadEngine (). и т.д) Если я убираю эти ключевые слова, то всё работает. Это нормально?

    P.S. Спасибо за статьи, они одни из единственных что есть в рунете об этом движке.

    • У вас просто компилятор настроен на Java версию 1.5 скорее всего. В еклипсе на проекте в контекстном меню Properties->Java Compiler и там везде замените на 1.6

      • Спасибо, помогло. Ни в одном мануале по настройке эклипса об этом не говорилось.

  • Добрый день. Не подскажете, как устроена работа со слоями в движке? Ну т.е. мне хочется, чтобы определенный текст был всегда «поверх» спрайта. В сцену я добавляю текст позже, но все равно спрайт оказывается выше. Знаю, что можно работать с 2мя слоями, как scene.getFirstChild () и scene.getLastChild () (кстати, это же нужно делать при загрузке сцены, а потом их сохранить, например в Entity layer1, layer2; ?). Вопрос — как работать с большим количеством слоев? Так же, только вместо getLastChild использовать getChildByNum? Или же в движке это реализовано более удобным образом? Спасибо.

    • В главную сцену можно добавить как Enity, так и другие сцены. В каждой сцене можно организовать еще слои опять же с помощью Entity или Scene. Внутри одной Entity детей можно сортировать и задавать им z-index. Чем раньше добавляется child, тем он дальше от зрителя. Можно заранее создать несколько Scene (или Entity) и добавить их в главную сцену. Их можно прятать и показывать, когда нужно. Объяснил кратко, если есть еще вопросы, пиши

      • И опять Вы мне помогли, спасибо) Хорошо, что есть человек, которому не лень отвечать на вопросы новичков)

  • Привет. Сайт клевый, хотя стиль написания у тебя явно не языка java, но зато примеры по своей логике полезные. Вот только возникла проблема с фоном. Когда пытаюсь всеми возможными способами сделать фоновое изображение получаю моргающий экран с непонятными глюками. Использовал уже и SpriteBackgroung и RepeatingSpriteBackground, перепробовал много TextureOption но все тщетно. Может сталкивался кто-нибудь с такой проблемой

  • Целые выходные не мог заставить работать. Прочитал и все завелось)))) спасибо вам огромное!!!

Прокомментировать



ЗАДАЙ СВОЙ ВОПРОС