Будь-який ігровий програміст рано чи пізно стикається з потребою зберігати прогрес. Адже можливість продовжити гру з місця збереження – один із визначальних факторів, який впливає на рішення гравця повернутися. А для ігор, які передбачають багатогодинне проходження, можливість зберігати прогрес є обов’язковим атрибутом.
Можливо, ви очікуєте, що реалізація збереження прогресу у Flash виявиться складною. Та на щастя до мови ActionScript 3 включено клас SharedObject, який суттєво спрощує життя програмістам. У всіх своїх іграх починаючи із Symbiosis я використовував його можливості. А сьогодні мені хотілося б розповісти про принципи роботи SharedObject та поділитися практичними прикладами реалізації збереження прогресу.
Клас SharedObject використовується для збереження невеликих об’ємів даних на комп’ютері користувача. Його робота дуже схожа на роботу кеша браузера. Єдина відмінність полягає в тому, що файли, які створюються внаслідок роботи SharedObject не зберігаються разом із файлами cookies, які генеруються браузером, а отже й не видаляються, коли ви очищуєте кеш.
SharedObject може використовуватися, наприклад, для збереження інформації про кількість пройдених рівнів чи набраних очків. Таким чином, коли гравець повторно заходить у гру – він не змушений починати все з початку.
Наведений нижче флеш-кліп наочно демонструє роботу SharedObject. Ви можете як завгодно змінити позицію об’єктів на екрані і флеш запам’ятає їх розташування навіть якщо ви оновите сторінку.
Далі ми детально розглянемо код цього прикладу, але перш, ніж це зробити, давайте розберемося з основами роботи SharedObject.
Створення об’єкта SharedObject: метод getLocal()
Для створення екземпляра SharedObject вам не потрібно використовувати ключове слово new, як це буває при роботі із абсолютною більшістю класів у ActionScript 3. Натомість доведеться використовувати метод getLocal(). Цей метод перевіряє, чи існує раніше збережений екземпляр об’єкта SharedObject, і створює новий об’єкт тільки за умови його відсутності. Якщо ж об’єкт існує – метод просто відновить його із пам’яті та зробить доступним для маніпуляцій.
Ось як це виглядає на практиці:
var mySharedObject:SharedObject; mySharedObject = SharedObject.getLocal("mySharedObjectID");
або однією стрічкою:
var mySharedObject:SharedObject = SharedObject.getLocal("mySharedObjectID");
Змінна mySharedObject – це посилання на екземпляр класу SharedObject, який ви будете використовувати у програмі, а ідентифікатор mySharedObjectID – це своєрідний код, який використовується для збереження та відновлення створеного раніше екземпляру. Важливо щоб ідентифікатор був унікальним, оскільки в іншому разі можуть виникати конфлікти між об’єктами SharedObject, які були створені різними програмами.
Особисто я використовую ідентифікатор типу jarofed + назва_проекту, наприклад jarofedSymbiosis. Ймовірність, що такий ідентифікатор співпаде з ідентифікаторами, які використовуються іншими авторами, мінімальна. Ви ж можете вигадати свій власний підхід до створення унікальних ідентифікаторів.
Важливо розуміти, що один об’єкт SharedObject може зберігати багато елементів даних. Тому, наприклад, якщо вам потрібно зберігати рівень, до якого дійшов гравець, та знайдені ним артефакти – вам не доведеться створювати кілька об’єктів SharedObject. Об’єм даних, доступних для збереження, обмежується тільки розміром файлу, який буде зберігатися на комп’ютері кінцевого користувача. За замовчуванням розмір не повинен перевищувати 100KB, але якщо програмі знадобиться більше місця для збереження даних, то вона повідомить про це користувача спливаючим вікном із можливістю розширити доступний об’єм пам’яті.
Збереження даних в об’єкті SharedObject
Ми вже розібралися, як створити екземпляр класу SharedObject. Наступним кроком є збереження даних, які потім будуть використовуватися в програмі. Для цього в класі SharedObject передбачена спеціальна змінна-контейнер .data типу Object, всередині якої можна зберігати будь-які дані.
Наприклад, код для збереження імені та прізвища гравця (в окремих контейнерах) може виглядати так:
mySharedObject.data.firstName = "Petro"; mySharedObject.data.lastName = "Poroshenko";
За допомогою цього коду ми вносимо дані щодо імені та прізвища у відповідні контейнери для збереження. Але це не означає, що вони будуть автоматично записані у файл, який зберігається на комп’ютері. Щоб ініціювати запис, нам потрібно використати метод flush():
mySharedObject.flush();
Ось як в результаті виглядатиме весь код запису даних у об’єкт SharedObject:
var mySharedObject:SharedObject; mySharedObject = SharedObject.getLocal("mySharedObjectID"); mySharedObject.data.firstName = "Petro"; mySharedObject.data.lastName = "Poroshenko"; mySharedObject.flush();
Отримання та видалення даних, збережених у SharedObject
Отримання даних з об’єкту SharedObject, дуже схоже на процес збереження, але є протилежним до нього.
Після того, як ми відновили об’єкт SharedObject з файлу вже знайомим способом:
var mySharedObject:SharedObject; mySharedObject = SharedObject.getLocal("mySharedObjectID");
ми отримуємо доступ до контейнера .data і всіх збережених у ньому даних.
Наступний код:
trace(mySharedObject.data.firstName); trace(mySharedObject.data.lastName);
видасть результат Petro Poroshenko.
Якщо ж з якихось причин нам потрібно видалити дані, збережені в об’єкті SharedObject, це можна зробити з допомогою метода clear():
mySharedObject.clear();
Використання SharedObject на практиці
Після того, як ми розібралися з основними методами роботи з SharedObject, можна детальніше розглянути код прикладу з позиціонуванням геометричних фігур, який наведений на початку статті.
var _btnCircle:MovieClip = new btnCircle(); _btnCircle.x = 100; _btnCircle.y = 140; addChild(_btnCircle);
Спершу ми створюємо MovieClip _btnCircle, для наповнення якого використовуємо заздалегідь приготований графічний клас btnCircle, позиціонуємо його та додаємо на сцену. Про створення об’єктів MovieClip та їх використання у коді можна детальніше прочитати за посиланням.
var SO:SharedObject; SO = SharedObject.getLocal("jarofedGeometry", "/"); if (SO.data.circle_x) { _btnCircle.x = SO.data.circle_x; _btnCircle.y = SO.data.circle_y; }
Наступним кроком буде створення об’єкта SharedObject.
Зверніть увагу на другий параметр в методі getLocal(). Параметр (“/”) потрібен для більш надійної роботи SharedObject. Адже за замовчуванням файли, які генеруються класом SharedObject, зберігаються відповідно до розташування вашого флеш файла на сайті. Це означає, що об’єкт SharedObject, який був створений файлом www.testsite.com/testswf/testswf.swf, перестане працювати, якщо ви перемістите файл на іншу сторінку цього ж сайту www.testsite.com/testswf2/testswf.swf Щоб уникнути таких незручностей, другим параметром методу getLocal() ми ініціюємо збереження файла SharedObject у кореневу директорію. А отже він буде доступний не залежно від того, на якій сторінці сайту буде знаходитися ваш флеш-файл.
Після того, як ми ініціювали об’єкт SharedObject, ми перевіряємо, чи існують раніше збережені позиції нашого круга? Якщо так – ми перепозиціоновуємо круг відповідно до позиції, збереженої у SharedObject.
_btnCircle.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); _btnCircle.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); private function onMouseDown(e:MouseEvent):void { _btnCircle.startDrag(); } private function onMouseUp(e:MouseEvent):void { _btnCircle.stopDrag(); SO.data.circle_x = _btnCircle.x; SO.data.circle_y = _btnCircle.y; SO.flush (); }
Насамкінець ми додаємо слухачі подій натискання та відпускання лівої клавіші миші. Детальніше про слухачі подій можна прочитати у однойменній статті.
Коли ми натискаємо на ліву клавішу миші, наш круг починає рухатися за курсором. Коли ми відпускаємо клавішу – круг перестає рухатися і ми ініціюємо збереження його нових координат у SharedObject.
Залишилося тільки повторити код для квадрата та трикутника – і ви отримаєте результат, подібний до наведеного на початку статті.
Сподіваюся, стаття не була занадто складною для розуміння і тепер ви зможете використовувати SharedObject для збереження прогресу у власних іграх. Якщо ж у вас все-таки залишилися запитання – не соромтеся задавати їх у коментарях.