Разрабатывайте игры для всех экранов

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

Конкретные различия в опыте игроков включают следующее:

  • Форм-факторы устройств. Хотя телефоны предоставляют традиционные возможности устройств Android, можно взаимодействовать с играми на других форм-факторах. Устройства ChromeOS могут запускать контейнер Android, в котором отображается ваша игра. Планшеты, работающие под управлением Android, поддерживают несколько различных уровней точности. Устройства Android TV поддерживают более детализированные и захватывающие впечатления. Игроки могут моделировать многооконную среду с помощью инструмента расширения дисплея. А при использовании складных устройств игроки могут изменять размер экрана во время игрового сеанса.
  • Методы взаимодействия: игроки могут вводить данные, касаясь экрана устройства, но вместо этого они также могут использовать мышь, сенсорную панель, клавиатуру или контроллер. Кроме того, наличие инструментов расширения дисплея и складных устройств позволяет игрокам наслаждаться игрой на большом экране, что делает более длительными игровые сеансы и более сложные интерфейсы более осуществимыми.
  • Аппаратная поддержка. Некоторые устройства на базе Android не имеют аппаратного обеспечения, более типичного для портативных устройств, такого как камера на задней панели, GPS и возможность подключения к сети. Ваша игра должна адаптироваться к доступному оборудованию и корректно обрабатывать ситуации, когда определенные функции недоступны.

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

Лучшие практики игрового дизайна

При планировании дизайна и архитектуры вашей игры следуйте рекомендациям, описанным в следующих разделах.

Реагировать на изменения конфигурации вручную

Когда система Android обнаруживает изменение конфигурации , например изменение размера экрана, ориентации экрана или метода ввода, система по умолчанию перезапускает текущее действие. Чтобы сохранить состояние в приложении или игре, действие по умолчанию вызывает onSaveInstanceState() перед перезапуском и onRestoreInstanceState() после перезапуска. Однако этот процесс требует перезагрузки всех связанных служб и ресурсов. Дополнительные сведения об этом поведении по умолчанию см. в руководстве по обработке изменений конфигурации .

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

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

Создайте гибкую архитектуру

Чтобы добавить поддержку вашей игры на как можно большем количестве устройств, следуйте этим рекомендациям:

  • Развертывайте пакеты приложений Android вместо отдельных APK-файлов. Пакеты приложений Android позволяют упаковывать артефакты разного разрешения и разных моделей архитектуры, например x86, ARM, в один артефакт. Более того, пакеты приложений Android поддерживают более высокие ограничения размера вашей игры; Каждый базовый APK может иметь размер до 150 МБ, а размер самого пакета может достигать нескольких гигабайт.
  • Добавьте поддержку архитектур x86. Этот шаг повысит производительность вашей игры на устройствах, не поддерживающих ARM, поскольку теперь эти устройства могут выполнять инструкции без необходимости их предварительной трансляции.

Добавить поддержку Вулкана

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

Создание пользовательских обработчиков изменений конфигурации.

Чтобы объявить типы изменений конфигурации, которые ваша игра обрабатывает сама, добавьте атрибут android:configChanges к каждому элементу <activity> в вашем манифесте, который представляет экран или сложный интерфейс.

Следующий фрагмент кода демонстрирует, как объявить, что ваша игра заботится об изменении размера экрана, его ориентации и метода ввода:

<activity ...
    android:configChanges="screenSize|orientation|keyboard|keyboardHidden">
</activity>

Когда происходят объявленные изменения конфигурации, система теперь вызывает другой метод — onConfigurationChanged() . В этом методе добавьте логику для обновления пользовательского интерфейса вашей игры:

Обработка изменений конфигурации экрана

Ваша игра обрабатывает изменения размера и ориентации экрана вручную всякий раз, когда вы включаете значения screenSize и orientation соответственно в атрибут android:configChanges . Вы можете использовать эти новые значения для обновления содержимого вашей сцены и областей ввода игрока. Инструкции о том, как разработать макет игры, чтобы ее было легче обновлять, см. в руководстве по поддержке экранов разных размеров .

В реализации onConfigurationChanged() в вашей игре используйте переданный объект Configuration и объект Display оконного менеджера, чтобы определить обновленные значения размера и ориентации экрана соответственно.

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

Котлин

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    val density: Float = resources.displayMetrics.density
    val newScreenWidthPixels = (newConfig.screenWidthDp * density).toInt()
    val newScreenHeightPixels = (newConfig.screenHeightDp * density).toInt()

    // Get general orientation; either Configuration.ORIENTATION_PORTRAIT or
    // Configuration.ORIENTATION_LANDSCAPE.
    val newScreenOrientation: Int = newConfig.orientation

    // Get general rotation; one of: ROTATION_0, ROTATION_90, ROTATION_180,
    // or ROTATION_270.
    val newScreenRotation: Int = windowManager.defaultDisplay.rotation
}

Ява

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    float density = getResources().getDisplayMetrics().density;
    int newScreenWidthPixels = (int) (newConfig.screenWidthDp * density);
    int newScreenHeightPixels = (int) (newConfig.screenHeightDp * density);

    // Get general orientation; either Configuration.ORIENTATION_PORTRAIT or
    // Configuration.ORIENTATION_LANDSCAPE.
    int newScreenOrientation = newConfig.orientation;

    // Get general rotation; one of: ROTATION_0, ROTATION_90, ROTATION_180,
    // or ROTATION_270.
    int newScreenRotation = getWindowManager().getDefaultDisplay()
            .getRotation();
}

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

Качество экрана, специфичное для игры

В следующих разделах описано, как настроить реакцию вашей игры на изменения размера экрана или ориентации экрана в зависимости от качества вашей игры:

Полноэкранный режим

На некоторых платформах, таких как ChromeOS, приложения и игры Android по умолчанию могут работать в оконном режиме и изменять их размер. Если ваша игра должна всегда работать в полноэкранном режиме, вы можете установить для атрибута android:resizeableActivity значение false в одном из элементов <activity> , как показано в следующем фрагменте кода:

<activity ...
    android:resizeableActivity="false">
</activity>

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

Ориентация экрана

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

<activity ...
    android:screenOrientation="landscape">
</activity>

Качество экрана для конкретного устройства

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

Соотношение сторон

Некоторые устройства поддерживают разные соотношения сторон. Например, складные устройства предназначены для поддержки соотношения сторон 21:9 в сложенном состоянии. Чтобы справиться с этим потенциальным разнообразием соотношения сторон, выполните хотя бы одно из следующих действий:

  • Целевой Android 8.0 (уровень API 26) или выше.
  • Сделайте сцену и интерфейс вашей игры изменяемыми. Установите android:resizeableActivity значение true на устройствах под управлением Android 7.0 (уровень API 24) и выше.
  • Объявите максимальное поддерживаемое соотношение сторон. В атрибуте <meta-data> , связанном с вашей игрой, установите android.max_aspect равным 2.4 , как показано в следующем фрагменте кода. Однако имейте в виду, что соотношение сторон, превышающее указанное вами, приводит к тому, что игра отображается на дисплее в виде почтового ящика .

    <application>
    <meta-data android:name="android.max_aspect"
               android:value="2.4" />
    </application>
    

Несколько действий видны одновременно

Многие современные устройства поддерживают различные макеты экрана, включая разделенный экран, «картинка в картинке» и большие области отображения. При использовании одного из этих макетов система может одновременно отображать несколько действий.

На устройствах под управлением Android 9 (уровень API 28) или выше возможно одновременное возобновление всех наиболее видимых действий. Однако для того, чтобы такое поведение работало, и ваша игра, и OEM-производитель устройства должны включить эту функциональность. Вы можете добавить поддержку в свою игру, установив android.allow_multiple_resumed_activities значение true в манифесте вашей игры, как показано в следующем фрагменте:

<application>
    <meta-data android:name="android.allow_multiple_resumed_activities"
               android:value="true" />
</application>

Затем вы можете протестировать свою игру на разных устройствах, чтобы увидеть, какие из них обеспечивают OEM-поддержку, необходимую для правильной работы нескольких возобновлений.

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

Работа с различными типами моделей взаимодействия.

Ваша игра обрабатывает наличие и доступность клавиатуры вручную всякий раз, когда вы включаете значения keyboard и keyboardHidden соответственно в атрибут android:configChanges . Вы можете использовать эти новые значения для обновления основного метода ввода вашей игры.

При настройке игры для поддержки нескольких типов пользовательского ввода имейте в виду следующее:

  • Обнаруживайте методы ввода, а не отдельные устройства. Такой образ мышления позволяет улучшить взаимодействие с игроком, не уделяя слишком много внимания конкретному устройству, которое может быть у игрока.
  • Включите атрибут keyboardHidden в список изменений конфигурации, обрабатываемых вручную. Таким образом, ваша игра сможет отслеживать, когда клавиатура физически подключена к устройству, но непригодна для использования.
  • Определите методы ввода, которые доступны в настоящее время. Для этого вызывайте getInputDeviceIds() при запуске игры и после каждого изменения конфигурации.

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

    • Игроки обычно используют клавиатуру или игровой контроллер для выполнения быстрых последовательностей кнопок.
    • Игроки обычно используют сенсорный экран или тачпад для выполнения более сложных жестов.
    • Игроки обычно используют мышь для более точного ввода.

В следующих разделах представлены рекомендации для конкретных типов устройств ввода.

Клавиатура

Создавая раскладку клавиатуры для своей игры, учитывайте, как игрок перемещается по заданной сцене, а также как он взаимодействует с настройками вашей игры.

Клавиши WASD или клавиши со стрелками обычно лучше всего подходят для управления движением персонажа. Также лучше всего назначить определенную клавишу для каждого важного действия или навыка, который управляемый персонаж может выполнять в вашей игре. Чтобы максимально повысить удобство игры, рассмотрите возможность добавления в игру поддержки пользовательских привязок клавиш.

Игроки также должны иметь возможность открывать меню вашей игры и перемещаться по ним с помощью клавиатуры. Клавиша Esc — это распространенное назначение для приостановки сцены и отображения меню игры.

Дополнительную информацию о поддержке ввода с клавиатуры в вашей игре см. в руководстве по поддержке навигации с клавиатуры , а также в руководстве по обработке действий с клавиатуры .

Игровой контроллер

Дополнительную информацию об обработке ввода контроллера в игре см. в руководстве по поддержке игровых контроллеров .

Мышь или тачпад

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

На устройствах под управлением Android 8.0 (уровень API 26) и выше вы можете использовать API захвата мыши, чтобы помочь в процессе захвата указателя. В играх, которые реагируют на высокоточный ввод, вы можете получить текущие координаты указателя, вызвав методы getX() и getY() .

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

Проверьте свою игру

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

Обновите свой план тестирования

При проверке функциональности вашей игры включите следующие тестовые примеры:

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

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

Рекомендации по тестированию игры см. в руководстве «Основы тестирования» .

Используйте инструменты тестирования и отладки

Вы можете выполнять тесты, используя различные инструменты, поддерживаемые платформой: