Розробка браузерної онлайн ігри на meteor

Доброго дня, мене звуть Олександр Зеленін і я веб-розробник. Останні півроку займався розробкою багатокористувацької космічної браузерної стратегії. На поточний момент ми вже знаходимося на стадії закритого бета тестування (доступного для вклалися) і запустили компанію на бумстартере.



В цьому пості хочу розповісти про процес розробки гри з нуля силами двох осіб.


Зміст
  1. Передумови
  2. Вибір платформи та інструментів взаємодії
  3. Початок розробки
  4. Баланс ресурсів
  5. Військовий баланс
  6. Вивантаження на живі сервера та оновлення
  7. Через 5 місяців
  8. Технічна частина
  9. Відповіді на питання
  10. Підсумок



Передумови

Після нового року я був у пошуках цікавого проекту. У вільний час я почитував joyreactor, і натрапив на цікаву гру, яку проводив з аудиторією всього сайту один хлопець, під ніком AlanWake. Гра являла з себе комікс з варіантами розвитку, за які голосували відвідувачі + свої варіанти в коментарях. Переміг варіант отримував розвиток. Після пари випусків з'явилися «фанатські» версії цієї всесвіту, і в підсумку все вийшло з-під контролю. До сьомого випуску вже сам автор заплутався в тому, що відбувається, оскільки не було ніякого контролю, а фанати хотіли, щоб додаткові історії так само враховувалися.
У восьмому випуску «Канал зв'язку закрився».
За пару тижнів гра зібрала більше чотирьох тисяч передплатників. Я написав автору з пропозицією розробити повноцінну гру і подивитися, що з цього вийде.


Вибір платформи та інструментів взаємодії

Перед нами стояв вибір: браузер, мобільний додаток, Steam (або будь-яка інша майданчик) гра.
Зваживши всі за і проти, вибір припав на браузерний варіант: працює на більшості пристроїв приблизно однаково, згодом гру можна конвертувати в додаток (як мобільний, так і настільне), так і для початку гри потрібно мінімальну кількість дій.
В якості інструменту взаємодії один з одним вибрали realtimeboard — онлайн дошку, на якій можна писати текст, розміщувати картинки, малювати і все це зручно пов'язувати один з одним. Файли ж синхронізували через папку в дропбоксе.
Гра почала набувати структуру.



Ми досить швидко визначилися з вимогами і форматом гри.
Обговорили масу схожих ігор, намагаючись виділити найкраще, прибравши неприємні моменти.
Вимоги:
  • Це PvE гра.
  • Гра циклічна (цикл приблизно рік). За цей час гравці або перемагають, або програють (все)
  • Гра повинна йти розмірено, що б був час малювати комікси між подіями
  • Гра не повинна вимагати постійної присутності і підняття по будильнику, при цьому забезпечуючи контентом тих, хто хоче більше.
  • Пожертви не повинні значно впливати на геймплей, пріоритетно декоративні
  • Додаткові облікові записи не дають переваг
  • Гра повинна подобається нам самим



Початок розробки

За пару днів був зроблений прототип на node bootstrap'ом, в якому була можливість зареєструватись, будувати шахти і радіти припливу ресурсів. Коли стало ясно, що рухаємося в потрібному напрямку, я вирішив, що буду розробляти все на новому для мене meteor (як згодом виявилося, не дарма), аргументувавши це тим, що навіть якщо з грою будуть проблеми, то, як мінімум, будуть хороші знання нової технології.
Розгорнув робоче оточення, поставив метеор і почав писати.
Метеор мені відразу сподобався:
  • Розгортка однією командою
  • Безліч готових бібліотек, що підключаються легше, ніж коли-небудь (в іншому, на ноду не сильно складніше)
  • Автоматичне оновлення сторінок, при зміні вмісту (навіть картинок)
  • Бьютифаер/углифаер коду, в залежності від оточення
  • Кошти для дебага
  • Можливість писати в БД з консолі браузера (отключаемое для продакшену)
  • Розбиття коду на Клієнт, Сервер і Загальне.
  • «Реактивність». Моментальне відображення змін у базі у всіх клієнтів.


Останнє мені спочатку не сподобалося, т. к. волію більший контроль, але, як виявилося, я просто не дочитав документацію, і все чудово налаштовується.
З мінусів можу лише відзначити його неможливість роботи з кільцевими посиланнями. Можна, звичайно, сказати, що будь-яку задачу можна вирішити і без них… так, можна. Але це теж саме як говорити, що goto завжди поганий (для більшості програмістів поганий, оскільки не вміють використовувати, так. Було вже у ряді статей тут.).


Баланс ресурсів

Через якийсь час прийшов час прорахувати баланс. З «терміном» гри ми визначилися відразу, так що саме цей час бралося за основу. Максимально через рік у користувача вже повинно бути «все». В принципі капа можна досягти і значно швидше, але в цілому розрахунок був на звичайних користувачів.
Для розрахунку вартості будівель вони були виписані в таблицю, їм був вказаний максимальний рівень вказані вартості «від балди». Написав простеньку експоненційну формулу для розрахунку видобутку. Були побажання щодо початкової і кінцевої (на останньому рівні) видобутку — їх брали просто з голови, як «комфортні» цифри.



Після того як все було занесено в таблицю хоч у якомусь вигляді, почав підбирати коефіцієнти для вартості і видобутку, дивлячись як змінюються ціни і час будівництва (від першого до останнього рівня), підбираючи приблизно так, щоб вимагали близько 4 місяців незалежно від інших факторів.
Як тільки коефіцієнти були підібрані, вийшов очікуваний графік розвитку. Ще трохи підкрутили ціни, формулу можна впроваджувати!
Я відразу ж спробував закласти можливість варіювати баланс, залежно від тестів, тобто збільшувати/зменшувати кількість рівнів впливаючи на «плавність» розвитку, при цьому зберігаючи початкові і кінцеві значення.
У нас є три основних ресурсу (люди, метал, кристал), і два додаткових (честь, брудні галактичні кредити). В залежності від стадії гри відчувається брак тих чи інших ресурсів (крім кредитів), але, якщо грамотно спланувати всі (що вдалося деяким нашим тестерам) можна розвиватися практично без простоїв.


Військовий баланс

Битви у нас поділяються на два типи: наземні і космічні.
У наземних безпосередньо взяти участь не можна — це пряма сюжетна лінія. На Землю можна відправляти війська, вони приєднуються до об'єднаної армії всіх гравців. Пересування цієї армії контролюються щоденними опитуваннями всього сервера.
На поточний момент є по 10 видів юнітів з кожної сторони. У кожного юніта є параметри атаки, захисту, пріоритети атаки, а також особливі характеристики (атакує/не атакує повітряні цілі, тригерні здібності тощо). Для успішних операцій необхідна хоча б мінімальна координація гравців сервера, щоб відсилати необхідні для найближчих боїв підкріплення, в залежності від типу точки і видів супротивників.
Космічні ж навпаки, індивідуальні для кожного гравця.
На поточний момент є 4 види кораблів + флагман, а також торговельне судно.
Баланс обчислювався схожим чином. Тобто за основу брали вартість, і постачали її характеристиками, додаючи бонуси.
Так само в космосі зробили поділ за місій. Можна вибрати тип і рівень місії, подивитися приблизну кількість військ (як в третіх героях) і в бій.

Ах, так. Як вирішити питання зі вставанням по будильнику що б врятувати флот? Легко. Зробіть так, щоб флоту гравця так чи інакше був Кінець, і, звичайно ж впишіть це в геймплей.


Вивантаження на живі сервера та оновлення

Після створення файла налаштувань для Meteor Up вивантаження оновлення представляє з себе всього 1 команду:
відомстві deploy

Всі. Метеор сам завантажується на продакшн, оновлює файли, запускає потрібну кількість процесів, сам перезавантажиться, якщо впав і оновлює все на клієнтах.


Через 5 місяців

У гру вже можна більш-менш грати. Будівлі будуються, ресурси капають, завдання видаються, флоти літають, армія будується. Настав час заявити про себе.
Було вирішено в якості старту запуститися на бумстартере, т. к. аудиторія спочатку виключно російськомовна. Пару тижнів готували, склепали ролик на коліні і запустилися.



Перші два дні це пост про новини для ключової аудиторії — «конверсія» 1 до 5. Тобто кожен 5 відвідавши сторінку на бумстартере зробив внесок.
Далі цікаво, але, в принципі, очікувано. Публікації на різних новинних ресурсах, в ігрових пабликах і т. п. — конверсія близька до нуля. Тобто основний ефект був від заздалегідь підготовленої аудиторії. Від інших — майже немає.
Сплеск через п'ять днів — вихід чергового коміксу на реакторі.



На поточний день зареєстровано 365 користувачів. Онлайн в середньому тримається в районі 75-150 осіб.



Завантаження перевищує 5% тільки в момент оновлення. Високі стрибки споживання і часу відповіді — оновлення гри, рівнозначно тому що всі разом натиснули F5 зі скиданням кеша. За попередніми підрахунками сервер повинен витримувати до 5 000 чоловік онлайн без збоїв, за умови, що оновлення будуть припадає на малий онлайн.
Буквально вчора в результаті збою процеси падали протягом секунди і знову піднімалися, завантаження зросла до 50%, але при цьому на саму гру це не вплинуло ніяк, за винятком порожнього списку учасників в чаті. Тобто навіть в критичній ситуації система досить стабільна.

Тепер робоча дошка виглядає так, і управляти контентом стає все складніше.



До речі, ось ця велика частина праворуч — правки та пропозиції від користувачів. Хоча, ймовірно, не коректно порівнювати, т. к. тексти і опису ми не розміщували на дошці, але все ж.


Технічна частина

В метеорі дуже зручно поділ коду: клієнтська частина (client), загальна частина (lib) і серверна (server). Загальна частина доступна в обох частинах проекту рівнозначно, що дозволяє покласти в неї всі основні об'єкти гри, які потрібні і там і там.



CSS
Для стилів я використовувати Stylus, тому що він мені дуже подобається. По-перше, у нього приємний синтаксис, з якого прибрано все зайве, а по-друге він збирається в css на ноде, без будь-яких додаткових мов. Ну і готовий модуль пересобирает і довантажує на сторінку стилі прямо на льоту. Стилі розбиті по релевантним файлів, але «жирний» main, з нього ще не все рознесений — час рефакторінгу ще прийде.

HTML
Всі шаблони пишуться для шаблонизатора Spacebars, вбудованого в метеор. Я не дуже люблю logicless шаблонизаторы, і довелося миритися з рядом моментів. Я вважаю, що повинна бути можливість описувати все, що відноситься виключно до зовнішнього вигляду прямо в шаблонах. Для кожного простого порівняння необхідно заводити хелпер. Навіть для звичайного порівняння:
UI.registerHelper('eq', function (a, b) {
return a === b;
});

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

Роутер
Для визначення шляхів застосування використовував iron router. Досить зручний і добротно зроблений роутер, дозволяє навісити певні дії на перехід за посиланням, досить гнучко дозволяє описувати шляху, дає можливість передати потрібні дані відразу в шаблон, а не тільки через хелпери.
Router.route('/logout', function () {
Meteor.logout);
this.redirect('index');
});


Контролери
Не зовсім коректно. Контролерів тут, як таких, немає на фронті. До кожного шаблону можна прив'язати helpers і events. Хелпери повертають значення шаблон, а події відповідають за дії в ньому. В якості композитора сторінок виступає, в принципі, роутер.
Хоча, звичайно ж, ніхто не заважає рознести логічні елементи з різних файлів і зручно згрупувати.

Ігрові об'єкти
Є клас Item, містять зовсім базові дані, які є/можуть бути у кожного об'єкта: ім'я, опис, вимоги, ефекти. Так само містить базові методи, такі як price(), currentLevel(), meetConditions(), has() і т. п.
Від нього вже успадковуються об'єкти з додатковим/зміненою поведінкою: GlobalItem, Building, Unit, EnemyUnit, Hero, Research, GlobalResearch.
Об'єкти з префіксом Global є загальними на весь сервер, і реалізують відповідні механіки загальних вкладень у дослідження/героя.

Система ефектів
Мені дуже подобається система ефектів, яку вдалося зробити. Кожен об'єкт може володіти одним або декількома ефектами. Ефекти поділяються на 4 типи: впливають на видобуток, що впливають на ціну (і час), що впливають на бойові характеристики, а також спеціальні ефекти, які унікальні.
Ось приклад опису ефекту одного з поліпшень:
new Game.Effect.Military({
pretext: '+',
aftertext: '% до броні піхоти',
condition: {
type: 'unit',
group: 'ground',
special: 'infantry'
},
priority: 2,
affect: 'life',
result: function(level) {
level = level || this.currentLevel(); 
return level * 30;
}
})


Можна описати текст до і після значення, описати об'єкт, до якого застосовується ефект по ряду критеріїв (якщо не вказувати ні одного критерію — ефект діє на все, на що застосовується). Пріоритет — порядок при обчисленнях підсумкового значення: непарні пріоритети мають фиксированые значення, парні процентні. Тобто якщо у нас є ефект, який дає +10 броні з пріоритетом 1, а потім ефект, який дає 30% з пріоритетом 2, і після нього ще один +5 з пріоритетом 3, то в результаті отримаємо (базова броня + 10) * 1.3 + 5.
Якщо є кілька ефектів з однаковим пріоритетом, вони спершу підсумовуються, і вже потім застосовуються. Наприклад, 2 ефекту по 10% дадуть множник(1 + (0.1 + 0.1)).
Спеціальні ефекти можуть впливати на унікальні параметри гри, наприклад, знижуючи час перезарядки гипердвигателей (зустрічається всього в 1 місці).

Таким чином ми реалізували гнучку систему взаємодій будівель, поліпшень і всього іншого.
Можна отримати список ефектів, які можна застосувати до об'єкта, і працювати з ними як заманеться. Наприклад, вивести з чого складається приплив населення.
Завдання
Ми розділили завдання на: лінійка завдань, тригерних завдання, щоденне завдання. Крутейшей особливістю в плані реалізації є те, що я можу прив'язатися до будь-якої події в грі, як-то на видачу завдання так і умови виконання.
Досягалося це простим способом — завдання має функцію, яка повертає true/false, чи виконано завдання. Наприклад:
isDone: function() {
return Game.Buildings.has('residential', 'house');
}

Таким чином можна навісити подія хоч на повідомлення в чаті, хоч на вхід у гру після дощику в четвер.

Щоденні завдання, на поточний момент, представляють із себе просто опитування з кількома варіантами відповіді і варіанти розв'язки, частково випадкові, частково залежні від будь-яких дій раніше.

Робота з базою
За замовчуванням метеор поставляється з MongoDB. Це дуже зручна документо-орієнтована бд. Легко масштабується, легко писати запити, легко модифікувати. Зберігає всі дані в JSON, і, не маючи суворої структури, дозволяє додавати/прибирати поля на лету, завдяки чому, по суті, міграції не потрібні (за винятком випадків, коли нові поля старих записів треба заповнити значеннями).
Для роботи з певною колекцією я заводив окремий клас, і все, що було потрібно — гнав через нього. Наприклад, для списання ресурсів досить викликати Game.Resources.spend(price);


Відповіді на питання

Чому браузерна? Я думав браузерні ігри вимерли.
1) Я знаю можливості браузера краще ніж інших платформ
2) Працює на більшості пристроїв без додаткового доопрацювання.
3) Можливість зібрати повноцінні програми в майбутньому без великих трудовитрат

Вам вистачить 200 000 рублів що б зробити гру?
Гра вже на стадії бета тестування. Цих коштів нам вистачить що б випустити всі заплановані компоненти.

Що буде якщо ви не зберете кошти?
Будемо шукати інвестора.
По суті без реклами ми зібрали непогану стартову аудиторію, а це вже щось та важить.

Коли повноцінний запуск і що там буде?
Запуск планується в середині жовтня.
Будівлі, поліпшення, загальні поліпшення, герої, наземні війська, комічні війська, різні види космічних боїв, загальні (всім сервером) бої на Землі, тимчасові підсилювачі, особиста палата з декораціями, яку всі можуть дивитися, альянси, босі, купа різних завдань з відсиланнями до ігор, книг, фільмів і різних подій. А так само комікс, на розвиток якого впливає кожен гравець.


Підсумок

Пройдено великий шлях, але на відпочинок немає часу. Ще багато всього заплановано, багато треба встигнути до релізу, який очікується в жовтні.

Спец-код для тих, кому він потрібен: «Habrahabr».

Буду дуже радий відповісти на будь-які питання стосовно розробки та доповнити статтю.
Якщо у вас немає хабра-аккаунта, але є питання:
Пошта: zav.work@gmail.com
Skype: Zav_39

Дякую за увагу.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.