НОУ ІНТУІТ, Лекція, Створення додатків XNA

19.3. Використання засобів Windows Phone в іграх

інтуіт

Отримання значень прискорення за допомогою класу Accelerometer

Драйвер акселерометра вбудований у Windows Phone, і його можна використовувати для отримання значень як у програмах XNA, так і в програмах Silverlight.

У програмі необхідно створити екземпляр класу Accelerometer і призначити обробник події ReadingChanged , яка відбувається щоразу, коли акселерометр фіксує нові значення. У Silverlight можна використовувати ці значення як звичайні змінні, а також їх можна пов'язати з властивостями візуальних елементів. У XNA потрібно створити локальну копію нових значень і використовувати їх у методі Update .

Щоб використовувати клас Accelerometer , потрібно додати посилання посилання на бібліотеку Microsoft.Devices.Sensors , а також директиву using у файл коду. Для створення екземпляра класу Accelerometer та додавання обробника події можна використовувати наступний код:

Метод XNA Initialize викликається під час запуску програми. Після додавання обробника викликається метод Start, щоб програма почала отримувати значення від акселерометра.

Метод-обробник acc_ReadingChanged буде викликатись при кожній зміні значень:

Цей метод зберігає отримані значення в змінній типу Vector3 , і їх можна використовувати для управління рухом платформи в грі, що створюється нами:

Цей код використовує отримане значення координати X для управління рухом лівої платформи вгору та вниз. Зауважте, що гра працює в альбомній орієнтації, а значення акселерометра завжди видаються для портретної орієнтації.

Вирішення можливих проблем

Створена у нашому прикладі гра може час від часунекоректно працювати, оскільки код програми не враховує деякі важливі моменти.

Проблема пов'язана з методом, у якому відбувається зчитування та збереження значень з акселерометра. При цьому одночасно виконуються дві операції:

  • акселерометр генерує та зберігає нові значення;
  • метод Update використовує ці значення керувати ігровим об'єктом.

Однак, у Windows Phone одночасно може бути активним лише один процес, а паралельна робота зводиться до швидкого перемикання між активними процесами.

Проблема може виникнути під час наступної послідовності дій:

  1. Метод Update запускається і зчитує значення осі X .
  2. Відбувається подія класу Accelerometer, яка генерує нові значення по осях X, Y та Z.
  3. Метод Update зчитує нові значення осях Y і Z .

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

Цю проблему можна вирішити, якщо вказати, що операції отримання значень по осях повинні виконуватися як одна операція, щоб між ними не виконувався інший код процесу, який використовує ці значення. У мові C# для цього існує інструкція lock , яка не дозволяє отримати доступ до заданого об'єкта блокування, доки не виконається повністю вказаний блок коду. Для цього у програмі потрібно створити та використовувати об'єкт блокування:

Змінна accelLock має найпростіший тип даних object. У цій змінній не зберігаються жодні дані. Натомість він використовується як маркер, який може бутипризначений лише одному процесу. У методі Update має використовуватися змінена версія коду, яка також використовуватиме цей об'єкт блокування:

Коли процес спробує виконати блок коду програми, пов'язаний з інструкцією lock, він спробує отримати доступ до об'єкта блокування. Якщо об'єкт буде недоступний (його використовуватиме інша секція lock), то процес призупинить роботу і чекатиме, поки об'єкт не буде звільнений. Відповідно, тепер один метод не зможе перервати виконання іншого методу.

Однак такий підхід вимагає підвищеної уваги з боку програміста. Дуже важливо, щоб будь-який код у секції lock виконувався якнайшвидше, щоб іншим процесам не доводилося довго чекати доступу до об'єкта блокування. Інша проблема, яку необхідно уникати, – це взаємне блокування. Вона виникає у випадку, якщо один процес заблокував об'єкт A і очікує, доки не звільниться об'єкт B, а інший процес заблокував об'єкт B (перед тим як доступ до нього запросив перший процес) і чекає, доки не звільниться об'єкт A (який заблокував перший процес ). В результаті виходить, що обидва процеси припиняють роботу і можуть чекати скільки завгодно довго. При створенні програми необхідно уникати потенційної можливості створення такої ситуації.

Додавання звуків у гру

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

Звукові ефекти завантажуються як контент. Вони є WAV-файлами, завантажуються в пам'ять призапуску гри та відтворюються за запитом. Музичні файли також можуть бути частиною ігрового контенту, але відтворюються медіаплеєром.

Для створення аудіофайлів існують різні програми. Однак, створення та обробка звукових файлів не входить до теми нашого курсу.

Використовувати в грі звукові елементи дозволяє клас SoundEffect:

Клас SoundEffect містить метод Play, під час якого звук відтворюється:

Цей код відтворює звук під час зіткнення кулі з платформою. Це найпростіша форма відтворення звукового ефекту. Звук відтворюється відразу під час виклику методу, і програма продовжує працювати, не чекаючи закінчення його відтворення. Windows Phone може одночасно відтворювати кілька звукових ефектів. Апаратні засоби Windows Phone підтримує до 64 звукових каналів.

Використання класу SoundEffectInstance

Клас SoundEffect зручно використовуватиме швидкого відтворення звуків. Однак, у деяких випадках звукові ефекти гри повинні багато разів повторюватися, змінювати тон або використовувати панорамування. Для отримання додаткового контролю над звуком можна створити екземпляр класу SoundEffectInstance для особливого звукового ефекту. Його можна як дескриптор звуку гри.

Наприклад, можна створити звук безперервно працюючого двигуна. Для цього можна використовувати екземпляр класу SoundEffect, який містить зразок звуку двигуна, завантажений з елемента ігрового контенту. Використовуючи цей об'єкт, потрібно створити екземпляр класу SoundEffectInstance, який представлятиме дескриптор звуку:

Тепер можна використовувати методи та властивості класу SoundEffectInstance для керування відтворенням звуку та додавання звукових ефектів:

Цейкод відтворює звук, якби його було зупинено.

Клас SoundEffectInstance розглядається як дескриптор звукового каналу у пристрої Windows Phone. Не рекомендується створювати їх у великій кількості, щоб програма не вичерпала звукові канали.

Відтворення звуку в Silverlight

Програма Silverlight може використовувати XNA для відтворення звуків. Для цього потрібно додати до програми Silverlight посилання на бібліотеки XNA та завантажити звук із ресурсів проекту. Рекомендується використовувати директиву using у файлах коду, де буде викликатись відтворення звуків:

При цьому не можна використовувати багато елементів XNA, але можна використовувати класи аудіо.

Для звукових ресурсів, що додаються, можна створити в проекті окрему папку, наприклад, Sound . Звукові ресурси додаються як елемент контенту.

Оскільки в Silverlight немає контент-менеджера , для завантаження звуку з файлу потрібно використовувати інші можливості, наприклад, можна використовувати методи, що завантажують звук із потоку:

Клас TitleContainer є частиною рішення Silverlight і може відкрити будь-який елемент контенту у проекті як потік. Після виконання цієї команди у програмі Silverlight можна використовувати звук, завантажений у змінну beep класу SoundEffect.

Відтворювати звук у програмі Silverlight можна так само, як і у програмі XNA:

Також можна використовувати SoundEffectInstance для керування звуковими ефектами.

Однак, до програми Silverlight необхідно додати певні дії для перевірки правильності відтворення звуку. Як було викладено раніше, у грі XNA метод Update викликається 30 разів на секунду. При цьому оновлюються деякі системні елементи, включаючи відтворення звуку.Програма Silverlight таких дій не виконує і їх потрібно реалізувати, щоб звук правильно відтворювався:

Цей метод потрібно викликати 30 разів на секунду, інакше відтворення звуку може завершитися невдачею, а програма може бути зупинена. Для цього можна використовувати таймер, який генерує події через певні часові відтинки, і до обробника події можна додати потрібний код.

У просторі імен System.Windows.Threading описаний клас DispatcherTimer. Код для створення та запуску таймера може виглядати так:

Метод-обробник timer_Tick повинен просто оновлювати XNA:

За допомогою таймера у програмі Silverlight можна створювати різні додаткові ефекти, наприклад, анімований фон, годинник, що цокає і т.п.

Керування розмірами та орієнтацією екрану

Об'єкт гри graphics надає багато властивостей, які можна використовувати в іграх для керування розміром та орієнтацією екрану:

Для підтримки різних режимів орієнтації можна поєднувати відповідні значення за допомогою логічної операції АБО.

Якщо у грі потрібно обробити подію зміни орієнтації екрану, можна створити метод-обробник події OrientationChanged :

У методі Window_OrientationChanged можна змінити розмір всіх об'єктів на екрані для нової орієнтації гри. За замовчуванням орієнтацію найкраще задати в конструкторі класу Game .

Вибір розміру екрану

У грі можна вказати певний розмір екрану:

Якщо встановити певний довільний розмір екрана, гра змушує екран працювати в заданій роздільній здатності. Розміри впливають на орієнтацію екрана. При цьому апаратні засоби екрана Windows Phone масштабуватимуть зображення із зазначеною роздільною здатністю під реальний розмір екрану. ТакимТаким чином, гра виглядатиме однаково і на майбутніх пристроях з іншою роздільною здатністю екрана.

Автоматичне масштабування екрана можна використовувати для підвищення продуктивності гри, що розробляється:

Ці рядки вказують розмір екрана, який менший за екран більшості пристроїв Windows Phone. Фактично екран з такими розмірами в чотири рази менший за стандартний екран. Однак, апаратні засоби Windows Phone масштабують зображення, і воно виглядатиме правильно і на більшому екрані. У іграх, у яких зображення швидко змінюється, це помітно, але фактично вчетверо менший дозвіл значно підвищить ефективність роботи графічної підсистеми.

За промовчанням значення властивості IsFullScreen дорівнює false.

Вимкнення тайм-ауту екрану

Клас Guide є частиною XNA і дозволяє отримувати інформацію про обліковий запис гравця в Xbox Live, ігрові досягнення і т.д. Використовувати можливість відключення екранної заставки слід з обережністю, оскільки при цьому буде витрачатися енергія акумулятора, доки гра не буде закрита, навіть якщо користувач не виконуватиме жодних дій.