Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Документация jMonkeyEngine
        jMonkeyEngine Уроки и Документация
            Документация для продвинутых пользователей
                Сохранение и загрузка игр(.j3o)

Сохранение и загрузка игр(.j3o)

Опубликованно: 08.05.2017, 18:11
Последняя редакция, Andry: 07.07.2017 20:38

Spatial (то есть узлы и геометрия) могут содержать аудио и световые узлы, эмиттеры частиц, элементы управления и пользовательские данные (счет игрока, здоровье, инвентарь и.т.д.). Для вашего дистрибутива игры, вы должны преобразовать все оригинальные модели в более быстрый двоичным формат. Вы сохраняете отдельные Spatial объекты, а также сцены, используя com.jme3.export.binary.BinaryExporter.

Формат двоичного файла jMonkeyEngine называется .j3o. Вы можете конвертировать, просматривать и редактировать .j3o файлы и их материалы в jMonkeyEngine SDK и составлять сцены (сюда не входят монтажные сетки). Для преобразования вы можете использовать BinaryExporters или контекстное меню в SDK.

Система сериализации jMonkeyEngine — это интерфейс com.jme3.export.Savable. BinaryExporter JME3 может записывать стандартные Java-объекты, объекты JME3 и примитивные типы данных, которые входят в пользовательские данные Spatial объекта. Если вы используете классы пользовательских игровых данных, см. ниже, как сделать их «Savable.

Существует также com.jme3.export.xml.XMLExporter и com.jme3.export.xml.XMLImporter, который аналогичным образом преобразует jme3-пространства в формат XML. Но вы не использовали бы это для загрузки моделей во время выполнения (довольно медленно).

Образец кода

Сохранение Узла(Node)

Следующий пример переопределяет stop() в SimpleApplication, чтобы сохранить корневой узел в файл, когда пользователь закрывает приложение. Сохраненный корневой узел является обычным двоичным файлом .j3o, который вы можете открыть в SDK.

Обратите внимание, что при сохранении модели с текстурами, ссылки на эти текстуры сохраняются как абсолютные пути, и при загрузке файла j3o текстуры должны быть доступны по этому пути(по отношению к корню assetmanager, по умолчанию каталог для ресурсов), с которого они были загружены. Вот почему SDK управляет преобразованием на уровне проекта.
  /* Это вызывается, когда пользователь закрывает приложение. */
  @Override
  public void stop() {
    String userHome = System.getProperty("user.home");
    BinaryExporter exporter = BinaryExporter.getInstance();
    File file = new File(userHome+"/Models/"+"MyModel.j3o");
    try {
      exporter.save(rootNode, file);
    } catch (IOException ex) {
      Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Error: Failed to save game!!", ex);
    }
    super.stop(); // продолжить выход из игры
  }

Загрузка Узла(Node)

Следующий пример переопределяет simpleInitApp() в SimpleApplication для загрузки Models/MyModel.j3o при инициализации игры.

  @Override
  public void simpleInitApp() {
     String userHome = System.getProperty("user.home");
     assetManager.registerLocator(userHome, FileLocator.class);
     Node loadedNode = (Node)assetManager.loadModel("Models/MyModel.j3o");
     loadedNode.setName("loaded node");
     rootNode.attachChild(loadedNode);
  }
Здесь вы видите, почему мы сохраняем пользовательские данные внутри Spatial объектов — поэтому что его можно сохранить и загрузить вместе с файлом .j3o. Если у вас есть игровые данные вне Spatials, вы должны запомнить save() и load(), а также get() и set() сами.

Пользовательский класс Savable

JME BinaryExporter может писать стандартные объекты Java (String, ArrayList, buffers и.т.д.), Объекты JME (Savables, такие как Material) и примитивные типы данных (int, float и.т.д.). Если вы используете какой-либо пользовательский класс вместе с Spatial, тогда пользовательский класс должен реализовать интерфейс com.jme3.export.Savable. Есть два распространенных случая, когда это уместно:

  • Spatial несет любые пользовательские элементы Control.
    Пример: Вы использовали что-то вроде mySpatial.addControl(myControl);
  • Пользовательские данные Spatial могут содержать пользовательский Java-объект.
    Пример: вы использовали что-то вроде mySpatial.setUserData(«inventory», myInventory);

Если ваши пользовательские классы (пользовательские данные или Control) не реализуют Savable, то BinaryImporter/BinaryExporter не могут сохранить Spatial!

Поэтому каждый раз, когда вы создаете пользовательский класс Control или пользовательские данные, не забудьте внедрить Savable:

import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable;
import com.jme3.material.Material;
import java.io.IOException;

public class MyCustomClass implements Savable {
    private int      someIntValue;   // некоторые пользовательские данные
    private float    someFloatValue; // некоторые пользовательские данные
    private Material someJmeObject;  // некоторые пользовательские данные

    ...
    // ваш другой код ...
    ...

    public void write(JmeExporter ex) throws IOException {
        OutputCapsule capsule = ex.getCapsule(this);
        capsule.write(someIntValue,   "someIntValue",   1);
        capsule.write(someFloatValue, "someFloatValue", 0f);
        capsule.write(someJmeObject,  "someJmeObject",  new Material());
    }

    public void read(JmeImporter im) throws IOException {
        InputCapsule capsule = im.getCapsule(this);
        someIntValue   = capsule.readInt(    "someIntValue",   1);
        someFloatValue = capsule.readFloat(  "someFloatValue", 0f);
        someJmeObject  = capsule.readSavable("someJmeObject",  new Material());
    }
}

Чтобы сделать пользовательский класс более безопасным:

  1. Внедрите Savable и добавьте методы write() и read(), как показано в примере выше.
  2. Выполните следующие действия для каждого поля без временного класса:
    • Добавьте одну строку, которая write()(запишет) данные в капсулу вывода JmeExport.
      • Укажите переменную, чтобы сохранить, дайте ей имя типа String (может быть таким же, как имя переменной), и укажите значение по умолчанию.
    • Добавьте одну строку, которая read…()(считает) s данные в капсулу ввода JmeImport.
      • В левой части задания укажите поле класса, которое вы восстанавливаете.
      • С правой стороны используйте соответствующий метод capsule.read…() для типа данных. Укажите String имя переменной (должно быть таким же, как вы использовали в методе write()), и снова укажите значение по умолчанию.
Как и при любой сериализации, помните, что если вы когда-либо меняете типы данных в пользовательских классах, обновленные методы read() больше не смогут читать ваши старые файлы. Также должен быть конструктор, который не принимает параметров.

Переведено для jmonkeyengine.ru, оригинал
Автор перевода: Andry

Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.