Libgdxначало работы с libgdx

Реализуем класс Door

Вот код для нашего основного класса – Door:

package com.myfirstgdx.game;

        import com.badlogic.gdx.ApplicationAdapter;
        import com.badlogic.gdx.Gdx;
        import com.badlogic.gdx.graphics.GL20;
        import com.badlogic.gdx.graphics.OrthographicCamera;
        import com.badlogic.gdx.graphics.g2d.SpriteBatch;
        import com.door.managers.GameManager;

public class Door extends ApplicationAdapter {

    private OrthographicCamera camera;
    private SpriteBatch batch;
    //переменные для хранения значений размеров
    //высоты и ширины области просмотра нашей игры
    private float w,h;

    @Override
    public void create() {
        //узнаём размеры для области просмотра
        w = Gdx.graphics.getWidth();
        h = Gdx.graphics.getHeight();
        //создаём экземпляр камеры и устанавливаем размеры области просмотра
        camera = new OrthographicCamera(w,h);
        // центруем камеру w/2,h/2
        camera.setToOrtho(false);
        batch = new SpriteBatch();
        //инициализируем игру
        GameManager.initialize(w,h);
    }

    @Override
    public void dispose() {
        //уничтожаем batch и вызываем метод dispose класса GameManager
        batch.dispose();
        GameManager.dispose();
    }

    @Override
    public void render() {
        // Очищаем экран
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        //устанавливаем вид spriteBatch созданному нами объекту camera
        batch.setProjectionMatrix(camera.combined);
        //отрисовываем игровые объекты путём вызова метода renderGame класса GameManager
        batch.begin();
        GameManager.renderGame(batch);
        batch.end();
    }

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

}

Так как наша игра будет в двух измерениях (2D), мы будем использовать класс OrtographicCamera. Камера – это практически глаз, через который мы будем смотреть на наш игровой мир. Используем SpriteBatch для помощи отрисовки наших спрайтов. Далее мы узнаём размеры устройства, на котором запустится игра, чтобы в последующем их использовать для установки области просмотра:

//узнаём размеры для области просмотра
w = Gdx.graphics.getWidth();
h = Gdx.graphics.getHeight();

Далее мы создаём экземпляр камеры и устанавливаем для него область просмотра. После чего центруем область просмотра width(w)/2, height(h)/2 следующей строкой:

camera.setToOrtho(false);

Далее вызываем метод initialize() класса GameManager для установки игровых объектов и их свойств. В методе render() мы сначала очищаем экран белым цветом следующими строками:

// Очищаем экран
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

Затем передаём SpriteBatch координаты нашей камеры для визуализации:

//устанавливаем вид spriteBatch созданному нами объекту camera
batch.setProjectionMatrix(camera.combined);

Метод renderGame() класса GameManager вызывается между методами begin() и end() для отображения наших изображений (как и в принципе должна происходить отрисовка SpriteBatch).

 
А в методе dispose() мы уничтожаем созданный нами экземпляр batch класса SpriteBatch и вызываем метод dispose() класса GameManager для очистки памяти устройства после выхода игрока из нашей игры. Если вы сейчас запустите на своём устройстве или эмуляторе это приложение, то вот что вы должны увидеть:

В следующем уроке будем обнаруживать касания по экрану и открывать двери. Код и файлы, которые необходимо перекинуть в папку assets (для этого урока) вашего проекта можете скачать ниже:

Creating your cross-platform project (the easy way)

You can use python’s gdx-wizard script to setup a project containing all dependencies, paths, symbolical links and
assets pre-configurerd. A sample command to setup an iOS+Android project on Mac would be:

#call this on libgdx source folder
python gdx-wizard.py --gen-mode ios,android --root-dir ~/projects/ --project-name Test  \
--android-sdk /data/applications/android-sdk-linux_x86/ --package-name com.aevumlab.test \
--android-ndk /data/applications/android-ndk/ --ios-sdk-ver 6.0 --android-target android-10

To generate a base application for android and linux just change the gen-mode to «android,linux». You can safely call the script as many times
as you want as it will try to include only the new deployments. So you can start on linux and later on add the Mac backend without problems (I hope 🙂

iOS Note

When using Xcode to edit your new project, ensure that the «Base SDK» configuration is correctly pointed to the iOS SDK. I haven’t found a way to magically set
this parameter from cmake.

Android Note

You’ll still have to add the Gdx-Android backend which is located under src/backends/gdx-cpp-backend-android/android_support to your eclipse workspace and add it as a library
dependency to your project.

Building GDX++ (Linux/Ubuntu)

Assuming you have the latest Android NDK on «ANDROID_NDK_HOME» and the android SDK on «ANDROID_SDK_HOME»

Optional: I’m installing the built libraries and includes under build/local for convenience as you won’t need to sudo to install them.

git clone git://github.com/aevum/libgdx-cpp.git 
mkdir -p build/gcc/gdx build/android/gdx build/local

cd build/gcc/gdx

cmake ../../../libgdx-cpp -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../../local

make install

cd ../../android/gdx

ANDROID_NDK=PATH_TO_ANDROID_NDK cmake ../../../libgdx-cpp -DCMAKE_TOOLCHAIN_FILE=../../../libgdx-cpp/cmake/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release

make install

Differences from libgdx

Texture::newFromFile()

with the same parameters that you would expect on the constructor.

The pixmap class was converted to an interface

Analogically, the calls to create an PixMap now are:

Pixmap::newFromFile()
Pixmap::newFromPixmap()
Pixmap::newFromRect()

The Pixmap class has turned into an interface. This had to be done because we can have different pixmap implementors (currently Svg and Gdx2d).
The gdx_cpp::Graphics interface now have to handle the TextureData and Pixmap resolution and creation. This was made to decouple the texture class from determining
how to load and create TextureData (etc1, wich is not supported in all platforms per example).

What’s working

  • The linux backend has input, file and audio working
  • The android backend has input, file and audio working
  • SVG support through AntiGrainGeometry
  • iOS support
  • GLES 2

Объединение объектов

Объединение объектов является принципом повторного использования неактивных или «мертвых» объектов, вместо постоянного создания новых. Это достигается с
помощью создания пула объектов, и когда вам нужен новых объект, вы получаете его из этого пула. Если в пуле есть свободный объект, то он его вернет.
Если пул пустой или не содержит свободных объектов, то возвращается созданных новый экземпляр объекта. Когда объект больше не нужен, вы освобождаете его
и, это означает его возвращение обратно в пул. Таким образом, повторно используется память для размещения объектов и сборщик мусора просто счастлив.

Это жизненно важно для управления памятью в игре, которая часто порождает такие объекты как пули, препятствия, монстры и так далее.

libGDX предоставляет интерфейсы и классы для легкой работы с пулом.

  • Poolable
  • Pool
  • Pools

Реализация интерфейса означает, что объект имеет метод, который в libGDX автоматически вызывается при освобождении
объекта.

Ниже приведен краткий пример пула для пуль.

public class Bullet implements Poolable {

    public Vector2 position;
    public boolean alive;

    /**
     * Конструктор пули. Простая инициализация переменных.
     */
    public Bullet() {
        this.position = new Vector2();
        this.alive = false;
    }

    /**
     * Инициализация пули. Вызовите этот метод после получения пули из пула.
     */
    public void init(float posX, float posY) {
        position.set(posX,  posY);
        alive = true;
    }

    /**
     * Метод обратного вызова, когда объект освобожден.
     * Автоматически вызывается Pool.free() методом.
     * Необходимо сбросить каждое смысловое поле данной пули
     */
    public void reset() {
        position.set(0,0);
        alive = false;
    }

    /**
     * Метод вызывается при каждом кадре и обновляет пулю.
     */
    public void update (float delta) {

        // обновление позиции пули
        position.add(1*delta*60, 1*delta*60);

        // если пуля вне экрана, установка состояние в "мертвая"
        if (isOutOfScreen()) alive = false;
    }
}

В классе игрового мира:

public class World() {

    // Массив, содержащий активные пули.
    private final Array<Bullet> activeBullets = new Array<Bullet>();

    // Пул для пуль.
    private final Pool<Bullet> bulletPool = new Pool<Bullet>() {
        @Override
        protected Bullet newObject() {
            return new Bullet();
        }
    };

    public void update(float delta) {

        // если вам нужно создать новую пулю:
        Bullet item = bulletPool.obtain();
        item.init(2, 2);
        activeBullets.add(item);

        // если вы хотите освободить "мертвые" пули, верните их обратно в пул:
        Bullet item;
        int len = activeBullets.size;
        for (int i = len; --i >= 0;) {
            item = activeBullets.get(i);
            if (item.alive == false) {
                activeBullets.removeIndex(i);
                bulletPool.free(item);
            }
        }
    }
}

Класс Pools предоставляет статические методы для
динамического создания пулов любых объектов (используя
ReflectionPool). В приведенном выше примере,
это можно использовать в libGDX игре так:

Список файлов и проверка свойств

Иногда необходимо проверить конкретный файл на его наличие или просмотреть содержимое директории. предоставляет методы, чтобы сделать этот в
простой форме.

Вот пример, который проверяет существование конкретного файла и проверяет, является ли он директорией или нет:

boolean exists = Gdx.files.external("doitexist.txt").exists();
boolean isDirectory = Gdx.files.external("test/").isDirectory();

Просмотр списка директории столь же прост:

FileHandle[] files = Gdx.files.local("mylocaldir/").list();
for(FileHandle file: files) {
   // делаем что-нибудь интересное с файлом
}

Просмотр списка внутренних каталогов не поддерживается на Desktop.

Можно также запросить родительскую директорию файла или создать для файла в родительской директории.

FileHandle parent = Gdx.files.internal("data/graphics/myimage.png").parent();
FileHandle child = Gdx.files.internal("data/sounds/").child("myaudiofile.mp3");

будет указывать на , будет указывать на .

В FileHandle есть множество методов позволяющих проверять определенные атрибуты файла. Пожалуйста, для деталей обратитесь к Javadoc.

В HTML5 функции в основном нереализованные

На текущий момент функции в основном нереализованные на HTML5 back-end. Постарайтесь не полагаться на них, если целевым
приложением будет HTML5.

Пример непрерывной обработки ввода

Если вы хотите перемещать в игре персонажа, используя процессор ввода, то вы заметите, что персонаж будет двигаться только тогда, когда нажата клавиша. Для
непрерывной обработки событий ввода или перемещения спрайта, вы можете добавить флаг в класс персонажа.

public class Bob
{
    boolean leftMove;
    boolean rightMove;
    ...
    updateMotion()
    {
        if (leftMove)
        {
            x -= 5 * Gdx.graphics.getDeltaTime();
        }
        if (rightMove)
        {
            x += 5 * Gdx.graphics.getDeltaTime();
        }
    }
    ...
    public void setLeftMove(boolean t)
    {
        if(rightMove && t) rightMove = false;
        leftMove = t;
    }
    public void setRightMove(boolean t)
    {
        if(leftMove && t) leftMove = false;
        rightMove = t;
    }

Процессор ввода

Добавляем состояния игры (enum)

У нас будет три состояния в игре: START, CONFIRM, END:

  • START: Исходное состояние нашей игры, при которой все двери закрыты. Как только пользователь касанием выбирает дверь – откроется другая дверь с козой. Состояние игры меняется на CONFIRM;
  • CONFIRM: В этом состоянии у пользователя есть выбор: оставить свой вариант (выбрать ту же дверь, которую он указал в первый раз) или сменить своё решение и выбрать другую дверь. После того, как пользователь выберет дверь, она откроется. В этот момент игровая логика проверяет выиграл ли пользователь или проиграл. После чего состоянием игры меняется на END;
  • END: В этом состоянии игра окончена и происходит вывод сообщения о том, выиграл он или нет.

Мы объявим три состояния через enum и переменную level в классе GameManager (изменения в коде выделены):

static float width,height;

public static enum Level {
    START,
    CONFIRM,
    END
}
static Level level;

public static void initialize(float width,float height){

А в методе initialize() класса GameManager инициализируем переменную level состоянием START:

level = Level.START;

Теперь нам нужно слегка изменить объявление метода handleDoor() в классе InputManager и включить в список параметров индекс двери, которую хотим проверить:

public static boolean handleDoor(DoorClass door,float touchX,float touchY,int doorIndex){

Этот индекс будет передаваться методу handleDoor() в теле метода handleInput():

if (!door.isOpen) {
    if (handleDoor(door, touchX,touchY,i)) {
        break;

Для реализации задуманной нами игровой логики потребуется изменить код внутри метода handleDoor():

    public static boolean handleDoor(DoorClass door,float touchX,float touchY,int doorIndex){

        // Проверяем, находятся ли координаты касания экрана
        // в границах позиции двери
        if((touchX>=door.position.x) && touchX<=(door.position.x+ door.width) && (touchY>=door.position.y) && touchY<=(door.position.y+door.height) ){

            switch (GameManager.level) {
                case START:
                    //открыть случайную дверь из оставшихся
                    //после того, как пользователь выбрал предполагаемую им дверь
                    GameManager.doors.get(GameManager.getGoatIndices(doorIndex).random()).isOpen = true;
                    //меняем состояние нашей игры на CONFIRM
                    GameManager.level = GameManager.Level.CONFIRM;
                    break;

                case CONFIRM:
                    door.isOpen = true; //открыть выбранную дверь
                    GameManager.level = GameManager.Level.END;
                    //меняем состояние нашей игры на END
                    break;
            }
            return true;
        }
        return false;
    }

}

Через switch мы проверяем состояние игры в данный момент. Если игра находится в состоянии START, значит пользователь еще не выбрал ни одну из дверей. После того, как пользователь сделает свой выбор, мы используем метод getGoatIndices(), чтобы получить индексы дверей с козами. Затем, случайным образом выбирается одна из них и открывается пользователю. Состояние игры меняется на CONFIRM. Если игра находится в состоянии CONFIRM, то пользователь должен или подтвердить свой выбор или поменять его. После чего, открывается дверь, которую он выбрал и состояние игры меняется на END.

 
Состояние START:

Состояние CONFIRM:

Состояние END:

В следующем уроке научимся отображать текст и реализуем кнопку restart. А исходный код для всех классов на данный момент можно скачать внизу:

Главное меню

Рассмотрим класс.

package com.badlogic.drop;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;

public class MainMenuScreen implements Screen {

    final Drop game;

    OrthographicCamera camera;

    public MainMenuScreen(final Drop gam) {
        game = gam;

        camera = new OrthographicCamera();
        camera.setToOrtho(false, 800, 480);
    }

    // остальное опущено для краткости...

}

В этом фрагменте кода, мы делаем конструктор для класса, который реализует интерфейс Screen. Интерфейс Screen не предоставляет
какой-либо метод, поэтому вместо этого используется конструктор. Единственным необходимым параметром конструктора для игры
является экземпляр , так что если необходимо, то можно вызывать его методы и поля.

Последний метод в классе: render(float)

public class MainMenuScreen implements Screen {

    //public MainMenuScreen(final Drop gam)....

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0.2f, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        camera.update();
        game.batch.setProjectionMatrix(camera.combined);

        game.batch.begin();
        game.font.draw(game.batch, "Welcome to Drop!!! ", 100, 150);
        game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
        game.batch.end();

        if (Gdx.input.isTouched()) {
            game.setScreen(new GameScreen(game));
            dispose();
        }
    }

    // остальное опущено для краткости...

}

Этот код довольно прост, за исключением того, что нам нужно вызывать SpriteBatch и BitmapFont экземпляры из game поля, вместо создания собственных. Метод
отбражает текст на экране. libGDX поставляется с предварительно установленным шрифтом, Arial, так что можно
использовать конструктор по умолчанию и все равно получить шрифт.

Замет проверяется, было ли прикосновение к экрану, если это так, то мы устанавливаем GameScreen экземпляр и освобождаем ресурсы MainMenuScreen экземпляра.
Остальные методы, которые необходимы для реализации в MainMenuScreen остаются пустыми.

Файловые системы платформ

Здесь мы рассмотрим обзор парадигм файловых систем платформ, поддерживающихся в libGDX.

Desktop (Windows, Linux, Mac OS X)

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

Android

На Android ситуация немного сложнее. Файлы можно хранить внутри APK приложения, либо как ресурсы
или asset. Эти файлы доступны только для чтения. libGDX использует только
asset механизм, так как он предоставляет прямой доступ к байтовым
потокам и более напоминает традиционную файловую систему. Ресурсы отлично
предоставляются для обычных Android приложений, но вызывают проблемы при использовании в играх. Android совершает манипуляции во время их загрузки, например,
автоматически изменяет размер.

Asset хранятся в директории Android проекта и затем автоматически упаковываются в ваш APK файл при развертывании приложения. Ни одно другое
приложение не может получить доступ к этим файлам.

Файлы также могут храниться во внутренней памяти, где они доступны для чтения и записи. Каждое установленное приложение имеет специальную выделенную
внутреннею директорию для хранения. Эта директория тоже доступна только для этого приложения. Вы можете думать о таком хранилище как о частном рабочем
пространстве приложения.

Наконец, файлы можно хранить на внешнем накопителе данных, таком как SD карта. Внешние накопители не всегда могут быть доступны, например пользователь может
вытащить SD карту. Файлы в этом месте хранения следует считать не всегда доступными. Чтобы иметь возможность записи на внешние накопители, вам нужно будет
добавить разрешения в AndroidManifest.xml файл, смотрите разрешения ниже.

Javascript/WebGL

Обычное Javascript/WebGL приложение не имеет традиционной концепции файловой системы. Вместо этого, assets подобны изображениям, ссылающимся на URL адреса,
которые указывают на конкретные фалы одного или нескольких серверов. Современные браузеры поддерживают локальное хранилище данных, которое приближается к
традиционным файловым системам с чтением и записью.

libGDX предоставляет абстракцию файловой системы, доступной только для чтения.

Запись в файл

Как и для чтения файлов, предоставляет методы для записи в файл. Заметьте, что только локальные, внешние и абсолютные типы файлов поддерживаются
для записи в файл. Запись строки в файл работает следующим образом:

FileHandle file = Gdx.files.local("myfile.txt");
file.writeString("My god, it's full of stars", false);

Второй параметр метода указывает, должно ли содержимое быть добавлено к файлу. Если установлено значение false, то
текущее содержимое файла будут перезаписано.

Можно, конечно и записывать двоичные данные в файл:

FileHandle file = Gdx.files.local("myblob.bin");
file.writeBytes(new byte[] { 20, 3, -2, 10 }, false);

Есть много других методов в , которые облегчают запись различными способами, например использование . Смотрите дополнительные сведения
в Javadoc.

Back-end

libGDX пытается абстрагировать эти различия через множество интерфейсов, которые скрывают специфику платформы. Для каждой платформы libGDX поддерживает
так называемые back-end и реализует эти интерфейсы. Разработчик приложения не связан с back-end напрямую, вместо этого разработка ведется через
интерфейсы.

В настоящее время libGDX поддерживает 4 разных back-end.

  • Lwjgl: базируется на библиотеке Lightweight Java Gaming Library, которая является JNI оберткой конкретных оконных инструментов,
    OpenGL и OpenAL. Этот back-end работает на Windows, Linux и Mac OS X, если предоставлена доступность Java Runtime и видеокарта, поддерживающая как
    минимум OpenGL 1.5
  • Jogl: базируется на Jogl 1.1, еще одна JNI обертка OpenGL и Swing, а также OpenAL. Также направлен на Windows, Linux и Mac OS X.
    Сейчас Lwjgl более предпочтителен, так как он стабильнее, особенно когда дело доходит до полноэкранных приложений.
  • Android: базируется на Android API.
  • HTML5: базируется на GWT, SoundManager
    2, обновленной GWT WebGL и локальным хранилищем, связанным с Quake 2 GWT. Этот back-end
    будет компилировать Java код в чистый Javascript код. Конечных проект будет работать в Chrome, Safari, Firefox и последней версии Opera, а так же
    других браузерах, поддерживающих WebGL. В связи с характером GWT и Javascript, есть
    некоторые ограничения использования этого back-end.

Create your own dialogs.

In case you require are certain dialog (F.e. DatePicker, ProgressBar, ….) which is not supported by gdx-dialogs yet you can write your own dialog.

  1. Create a interface like this (in core project): GDXButtonDialog
  2. Create the implementation for Android like this (in android project): AndroidGDXButtonDialog
  3. Create the implementation for Desktop like this (in desktop project): DesktopGDXButtonDialog
  4. Create the implementation for iOS like this (in ios project): IOSGDXButtonDialog
  5. Create a fallback implementation with empty methods (in core project): FallbackGDXButtonDialog

If your dialog is written register it like this:

if(Gdx.app.getType() == ApplicationType.Android) {
	dialogs.registerDialog("package.for.your.dialog.interface.GDXButtonDialog", "package.for.your.dialog.os.specific.implementation.AndroidGDXButtonDialog");
}

else if(Gdx.app.getType() == ApplicationType.Desktop) {
	dialogs.registerDialog("package.for.your.dialog.interface.GDXButtonDialog", "package.for.your.dialog.os.specific.implementation.DesktopGDXButtonDialog");
}

else if(Gdx.app.getType() == ApplicationType.iOS) {
	dialogs.registerDialog("package.for.your.dialog.interface.GDXButtonDialog", "package.for.your.dialog.os.specific.implementation.IOSGDXButtonDialog");
}

else {
	dialogs.registerDialog("package.for.your.dialog.interface.GDXButtonDialog", "package.for.your.dialog.os.specific.implementation.FallbackGDXButtonDialog");
}

Use your own dialog:

dialogs.newDialog(GDXButtonDialog.class); // Use your dialog interface here

Note: Every platform specific implementation must have constructor even if it is empty. Android implementations must have a contructor accepting Activity parameter.

Increase your karma points 🙂 Share your dialog with us, add it to this repository and make a Pull Request.

##Release History

Release history for major milestones (available via Maven):

  • Version 1.3.0: Bugfix: Submodules had dependency on SNAPSHOT versions
  • Version 1.2.5: Bugfix: DesktopTextPrompt;
  • Version 1.2.4: Bugfix: DesktopTextPrompt;
  • Version 1.2.3: Bugfix: DesktopTextPrompt not showing default value;
  • Version 1.2.2: TextPrompt can now be used as a password field. Use setInputType(…);
  • Version 1.2.1: TextPrompt dialogs have new setMaxLength() method.
  • Version 1.2.0: gwt/html support
  • Version 1.1.0: ios-moe support, ios support, Android proguard setup now out of the box
  • Version 1.0.0: no changes, just released 0.2.0 as first stable build
  • Version 0.2.0: API Changes. You can create own dialogs now.
  • Version 0.1.0: Initial Release

##Reporting Issues

Something not working quite as expected? Do you need a feature that has not been implemented yet? Check the issue tracker and add a new one if your problem is not already listed. Please try to provide a detailed description of your problem, including the steps to reproduce it.

##Contributing

Awesome! If you would like to contribute with a new feature or a bugfix, fork this repo and submit a pull request.

##License

The gdx-dialogs project is licensed under the Apache 2 License, meaning you can use it free of charge, without strings attached in commercial and non-commercial projects. We love to get (non-mandatory) credit in case you release a game or app using gdx-dialogs!

Реализация класса GameManager

Теперь создайте новый пакет с именем managers внутри нашего основного – com.gdx.whackazombie. А внутри пакета managers создадим новый java класс – GameManager. Введите следующий код в этот файл:

package com.gdx.whackazombie.managers;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.Array;
import com.gdx.whackazombie.gameobjects.Zombie;

public class GameManager {

    static Array<Zombie>zombies; // массив наших зомби
    static Texture zombieTexture; // текстурное изображение нашего зомби
    private static float ZOMBIE_RESIZE_FACTOR = 500f;
    private static float ZOMBIE_VERT_POSITION_FACTOR = 3f;
    private static float ZOMBIE1_HORIZ_POSITION_FACTOR = 5.8f;
    private static float ZOMBIE2_HORIZ_POSITION_FACTOR = 2.4f;
    private static float ZOMBIE3_HORIZ_POSITION_FACTOR = 1.5f;

    public static void initialize(float width,float height){

        zombies = new Array<Zombie>();
        zombieTexture = new Texture(Gdx.files.internal("zombie.png"));

        // создание новых зомби и добавление их в массив
        for(int i=0;i<3;i++){
            zombies.add(new Zombie());
        }

        // установить позиции для каждого зомби
        zombies.get(0).position.set(width/ZOMBIE1_HORIZ_POSITION_FACTOR,height/ZOMBIE_VERT_POSITION_FACTOR);
        zombies.get(1).position.set(width/ZOMBIE2_HORIZ_POSITION_FACTOR,height/ZOMBIE_VERT_POSITION_FACTOR);
        zombies.get(2).position.set(width/ZOMBIE3_HORIZ_POSITION_FACTOR,height/ZOMBIE_VERT_POSITION_FACTOR);
        for(Zombie zombie : zombies){

            // установить спрайт для зомби, используя текстуру
            zombie.zombieSprite = new Sprite(zombieTexture);
            // установка размеров зомби
            zombie.width = zombie.zombieSprite.getWidth()* (width/ZOMBIE_RESIZE_FACTOR);
            zombie.height = zombie.zombieSprite.getHeight()* (width/ZOMBIE_RESIZE_FACTOR);
            zombie.zombieSprite.setSize(zombie.width, zombie.height);
            zombie.zombieSprite.setPosition(zombie.position.x, zombie.position.y);
        }

    }

    public static void renderGame(SpriteBatch batch){
    // Нарисовать(отобразить) каждого зомби
        //
        for(Zombie zombie : zombies)
            zombie.render(batch);
    }

    public static void dispose() {
    // утилизация текстуры крота, чтобы обеспечить отсутствие утечек памяти
        zombieTexture.dispose();
    }

}

Типы (хранения) файлов

Файл в libGDX представлен экземпляром FileHandle
класса. FileHandle имеет тип, который определяет где находится файл. Следующая таблица иллюстрирует наличие и местоположение каждого типа файла для каждой
платформы.

Тип
Описание, путь файла и особенности
Desktop
Android
HTML5
iOS
Classpath
Classpath файлы хранятся непосредственно в директории исходников. Они упакованы вместе с jar файлами и всегда доступны только для
чтения. Они имеют свое назначение, но по возможности нужно избегать их использования.

Да
Да
Нет
Нет
Внутренний
Внутренние файлы относятся к корневой или рабочей директории приложения на Desktop, к assets директории на
Android, и к директории GWT проекта. Эти файлы доступны только для чтения. Если файл не может быть найдет во
внутреннем хранилище, то файловый модуль возвращается к поиску файла в classpath. Это необходимо, если в Eclipse используется механизм ссылки на
asset директорию, смотрите настройку проекта.

Да
Да
Да
Да
Локальный
Локальные файлы хранятся относительно корневой или рабочей директории на Desktop и относятся к внутреннему (частному)
хранилищу приложений на Android

Обратите внимание, что локальный и внутренний тип в основном одно и то же для Dekstop.

Да
Да
Нет
Да
Внешний
Пути к внешним файлом являются относительными
на Android и
домашней директории текущего пользователя на Desktop системах.

Да
Да
Нет
Да
Абсолютный
Абсолютные файлы должны иметь полностью указанный путь. Примечание: Ради портативности, эта опция должна использоваться
только в случае крайней необходимости

Да
Да
Нет
Да

Абсолютные и classpath файлы в основном используются для таких инструментов, как редакторы на Desktop, которые имеют более сложные требования файлового
ввода/вывода. Для игр их можно спокойно игнорировать. Порядок, в котором вы должны использовать типы файлов выглядит следующим образом:

Внутренние файлы: все assets (изображения, аудио файлы и так далее), которые упакованные вместе с приложением являются внутренними
файлами. Если вы используете Setup UI, просто положите их в директорию Android проекта.

Локальные файлы: Если необходимо записывать небольшие файлы, например, сохранить состояние игры, используйте локальные файлы. В общем,
они имеют частный доступ для вашего приложения. Если вы хотите использовать ключ/значение хранилище, то вам следует посмотреть настройки предпочтения.

Внешние файлы: Если необходимо записывать большие файлы, например снимки экрана или скачивать файлы из интернета, то следует
использовать внешние накопители

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

Простой путь

Система сборки libGDX основана на Ant. Различные Ant скрипты отвечают за сборку разных частей libGDX.

Основной сценарий сборки называется build.xml и находиться в корневой директории libGDX репозитория. Он собирает дистрибутив libGDX, включая core API,
back-end, все расширения и Javadoc. Чтобы построить дистрибутив выполните следующие команды в shell.

ant -f fetch.xml
ant

Этим самым загрузятся последние версии нативных библиотек (скомпилированный C/C++ код для всех платформ) из
сервера сборки, так что вам не нужно делать их сборку самостоятельно. Затем будет вызван
основной сценарий для сборки всех Java частей.

Конечным результатом будет zip архив с названием libgdx-версия.zip и директория под названием dist, содержащая распакованный контент архива, который
будет, по сути, таким же, как и тот, который можно загрузить с nightly сервера сборки, плюс изменения, сделанные вами в исходниках.

Файл build.xml имеет target для каждого модуля. Каждая target настраивает несколько параметров (classpath, конечная директория и так далее), которые затем
передаются на вход build-template.xml файлу. Файл build-template.xml отвечает за компиляцию исходного Java кода, а также исходников нативного кода.
Последнее делается вызовом Ant сценария, называемого build.xml и находящегося в jni директории модуля. Если хотите использовать данный метод для
компилирования нативного кода, то это не удастся. Как скомпилировать нативные исходники смотрите информацию ниже.

Оцените статью
Рейтинг автора
5
Материал подготовил
Андрей Измаилов
Наш эксперт
Написано статей
116
Добавить комментарий