Pull to refresh

Пробуем AndEngine и physicsbox2d

Reading time 5 min
Views 6K
В этой заметке я хочу рассказать о существовании такого расширения для AndEngine как physics2box.
AndEngine — это бесплатный движок для игр под Andtoid, один из наиболее популярных. Для него существует ряд расширений, одно из них — physicsbox2d. Эта библиотека позволяет создавать физику в игровом мире.

Про AndEngine на Хабре уже отлично написал stepango . Я с удовольствием воспользовался его трудами, и, заодно, прикрутил physicsbox2d. Это оказалось довольно просто.

Я не берусь рассказать обо всех, или даже о какой-то части возможностей этих двух инструментов, а только подскажу интересующимся, с чего начать. А начать вот с чего:

Создаем стандартный проект под Android, и добавляем в него библиотеки andengine.jar, andenginephysicsbox2dextension.jar. Также, понадобится папка armeabi с файлами libandenginephysicsbox2dextension.so и armeabilibxmp.so. В Nebeans достаточно положить все это в папку libs в проекте. Как добыть все это — описывать не буду, что помешает праздно любопытствующим, но не остановит действительно заинтересовавшихся. Теперь можно приступать.

1. Унаследуем нашу Activity от AndEngine-вской BaseGameActivity.
2. Реализуем нужные нам методы onLoadEngine и onLoadScene

Вот код:
public class MainActivity extends BaseGameActivity
{
    // Ширина экрана камеры типа пикселях
    private static final int CAMERA_WIDTH = 800;
    // Высота экрана камерыв пикселях
    private static final int CAMERA_HEIGHT = 480;
    // Параметры физической среды в нашем мире
    private static final FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);
    // Камера, через которую мы смотрим на мир
    private Camera mCamera;
    // Сцена, на которую мы смотрим через камеру
    private Scene mScene;
    // Физический Мир, в котором все происходит.
    private PhysicsWorld mPhysicsWorld;
    
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
    }

    // загрузка движка
    public Engine onLoadEngine() {
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
        // Тут происходят загадочные манипуляции с разрешением, чтоб
        // не думать о нем в дальнейшем. RatioResolutionPolicy об этом вроде
        // заботится. Однако детали я еще не выяснял, не судите строго
        return new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT,
                new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT),
                this.mCamera));
    }

    public void onLoadResources() {
    }

    public Scene onLoadScene() {
        // Создаем новую сцену. Можно создать многослойную сцену, но это не для нас, новичков.
        mScene = new Scene(1);
        // Создаем физический мир с земной гравитацией, действущей вниз.
        this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);
        // Физический мир будет рулить сценой
        mScene.registerUpdateHandler(mPhysicsWorld);
        return mScene;
    }

    public void onLoadComplete() {
    }
  
}



Запускаем — и видим дружелюбный вакуум. В нашем мире пока ничего нет.

2. Загрузим текстуры. Немного совершенствуя пример stepango , используем статические переменные. Ходят слухи, что так лучше. Для этого создадим отдельный класс:

public class Textures {

    private Texture mTexture;
    private static TextureRegion mBallTextureRegion;
    private static TextureRegion mBackgroundTextureRegion;

    public Textures(final BaseGameActivity activity, final Engine engine) {
        // Здесь как бы атлас текстур - на этой "площадке" будут располагаться
        // все текстуры.
        mTexture = new Texture(1024, 1024,
                TextureOptions.BILINEAR_PREMULTIPLYALPHA);

        // Размер изображения - 512х1024.
        mBackgroundTextureRegion = TextureRegionFactory.createFromAsset(
                mTexture, activity, "gfx/bkg.png", 0, 0);
        // обратите внимание - кладем некстуру на атлас с координат
        // 512,0 - иначе мячик наложится на фон.
        mBallTextureRegion = TextureRegionFactory.createFromAsset(
                mTexture, activity, "gfx/ball.png", 512, 0);

        engine.getTextureManager().loadTexture(mTexture);
    }

    public static TextureRegion getBackground() {
        return mBackgroundTextureRegion;
    }

    public static TextureRegion getBallTextureRegion() {
        return mBallTextureRegion;
    }
}



Нужно инициализировать сей объект в activity в соответствующем методе:

public void onLoadResources() {
        // Загружаем текстуры
        mTextures = new Textures(this, getEngine());
    }


То, что не очень правильно работаем со статическими объектами — не в этом суть примера. По хорошему, тут бы какой-нибудь singleton подошел.

3. Теперь у нас есть текстуры. Самое время в методе onLoadScene создать объекты — боковые стенки, пол, и мячик.
Метод преображается следующим образом:

public Scene onLoadScene() {
        // Создаем новую сцену. Можно создать многослойную сцену, но это не для нас, новичков.
        mScene = new Scene(1);
        // Создаем физический мир с земной гравитацией, действущей вниз.
        this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);
        
        // Физический мир будет рулить сценой
        mScene.setBackground(new SpriteBackground(new Sprite(0, 0, Textures.getBackground())));
        
        // Создаем линии - будут границами
        Line line_top = new Line(0, 0, CAMERA_WIDTH, 0, 5.0f * metrics.density);
        Line line_left = new Line(0, 0, 0, CAMERA_HEIGHT, 5.0f * metrics.density);
        Line line_right = new Line(CAMERA_WIDTH, 0, CAMERA_WIDTH, CAMERA_HEIGHT, 5.0f * metrics.density);
        Line line_bottom = new Line(0, CAMERA_HEIGHT, CAMERA_WIDTH, CAMERA_HEIGHT, 5.0f * metrics.density);
        // Создаем тела на основе линий
        Body wall_top = PhysicsFactory.createLineBody(mPhysicsWorld, line_top, FIXTURE_DEF);
        Body wall_left = PhysicsFactory.createLineBody(mPhysicsWorld, line_left, FIXTURE_DEF);
        Body wall_right = PhysicsFactory.createLineBody(mPhysicsWorld, line_right, FIXTURE_DEF);
        Body wall_bottom = PhysicsFactory.createLineBody(mPhysicsWorld, line_bottom, FIXTURE_DEF);

        // Создаем спрайт мячика
        Sprite mSprite = new Sprite(0.0f, 0.0f, 100, 100, Textures.getBallTextureRegion());
        // Устанавливаем его в нужное место
        mSprite.setPosition(100, 100);
        // Создаем физическое тело мячика
        Body mBody = PhysicsFactory.createCircleBody(mPhysicsWorld, 100, 100, 50, 0, BodyType.DynamicBody, FIXTURE_DEF);
               
        // Связываем спрайты с их физическими телами
        this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_top, wall_top, true, true));
        this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_left, wall_left, true, true));
        this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_right, wall_right, true, true));
        this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(line_bottom, wall_bottom, true, true));
        mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(mSprite, mBody, true, true));
        
        // Загружаем в сцену спрайты
        this.mScene.attachChild(mSprite);
        this.mScene.attachChild(line_top);
        this.mScene.attachChild(line_left);
        this.mScene.attachChild(line_right);
        this.mScene.attachChild(line_bottom);
 
        mScene.registerUpdateHandler(mPhysicsWorld);
        return mScene;
    }



Вот и все. При запуске у нас появится фон, и мячик вверху слева. Он тут же начнет падать, долетит до конца экрана, отскочит… и дальше все как в жизни, без вского вмешательства прогаммиста.

После некоторого время знакомства, могу сказать: physics2box штука мощная и интересная. Есть проблемы с документацией и примерами, но тем любопытней процесс создания приложения.

Вот ссылка на статью stepango , которая мне помогла в моих изысканиях:
habrahabr.ru/blogs/android_development/120716
Tags:
Hubs:
+2
Comments 6
Comments Comments 6

Articles