GUI в грі World of Tanks. Частина перша: еволюція інтерфейсів гри

    image
 
Сьогодні ми проведемо екскурс в історію розвитку Graphical User Interface (GUI) у грі World of Tanks.
 
Гра пройшла довгий шлях до успіху, і її GUI змінювався і повністю перероблявся кілька разів в гонитві за зростаючими вимогами армії танкістів, яка неухильно росла.
 
Пропрацювавши у відділі GUI Programming два з половиною роки, я отримав уявлення про те, як розвивався сам інтерфейс в технологічному плані і як змінювалися підходи та процеси, це розвиток супроводжували.
 
 
Перші кроки: використання інструментів BigWorld
Починалося все з того, що в грудні 2008 народилася ідея проекту. Всі, хто грав в танки, думаю, знають, що початковою ідеєю було зробити гру про ельфів і орків, але, коли гарненько все продумали, вирішили зупинитися на танках (див. заголовне фото).
 
Гру почали робити на движку BigWorld, який надавав власний набір інструментів для створення GUI. Ми пішли шляхом найменшого опору і робили перші інтерфейси саме на BigWorld GUI.
 
Як це працювало з точки зору технічної реалізації:
 
 
     
  • декларативно в XML описувалася структура і візуальна частина GUI;
  •  
  • загальний layout для великої вьюха — стилі самої вьюха і набір основних блоків, її які становлять, описаний в XML;
  •  
  • кожен з блоків описаний в окремому XML із зазначенням використовуваних стилів і компонентів. Для компонентів задавалися їх налаштування (іменування, локалізаціонние повідомлення, посилання на стилі);
  •  
  • стилі описувалися в окремих XML-файлах, де задавалися розміри, позиції, використовувані текстури, шрифти, кольори, z-order і бог знає що ще;
  •  
  • при старті клієнта всі ці XML-файли вантажилися в Python і Парс, після чого починався процес створення інтерфейсів, їх ініціалізації та підключення до ігрової логіці.
  •  
Ось приклад, видерті з надр SVN-проекту:
 
 hangar.xml — опис блоків UI в ангарі:
 
 
<hangar>
    <styles>
        <style>window</style>
        <style>hangar:window</style>
    </styles>
    <childs>
        <AccountBlock>
            <name>account_info</name>
            <import> components/account </import>
        </AccountBlock>
        <Fitting>
            <name>fitting</name>
            <import> components/fitting </import>
        </Fitting>
...
    </childs>
</hangar>

 account.xml — опис блоку з інформацією про акаунт:
 
 
<account>
    <styles>
        <style>hangar:account_info</style>
    </styles>
    <childs>
        <TextLabel>
            <name>account_name</name>
            <text></text>
            <textElideMode>ElideRight</textElideMode>
            <styles>
                <style>hangar:account_name</style>
            </styles>
            <toolTip>
                <format>#tips:hangar/account_name</format>
            </toolTip>
        </TextLabel>
        <TextLabel>
            <name>account_exp</name>
            <text>#menu:hangar/account_info/experience</text>
            <styles>
                <style>hangar:account_exp</style>
            </styles>
            <toolTip>
                <format>#tips:hangar/account_exp</format>
            </toolTip>
        </TextLabel>
...
    </childs>
</account>

 styles / common.xml — опис стилів для загальних компонентів:
 
 
<style>
	<window>
		<bgcolor> 200 200 200 255</bgcolor>
		<overlaycolor> 255 255 255 255 </overlaycolor>
		<border>
			<texture>gui/maps/window_border.tga</texture>
			<size> 5 </size>
		</border>
		<focus>
			<bgcolor> 255 255 255 255</bgcolor>
		</focus>
	</window>
…
</style>

 styles / hangar.xml — опис стилів для компонентів в ангарі:
 
 
<style>
	<window>
		<color>0 0 0 255</color>
		<bgcolor>255 255 255 255</bgcolor>
	</window>
	<account_info>
		<position><x>10</x><y>10</y><z>0.9</z></position>
		<height>32</height>
		<bgcolor>100 100 100 255</bgcolor>
		<color>200 200 200 255</color>
	</account_info>
	<account_name>
		<height>100%</height>
		<textAlign>LEFT</textAlign>
		<position><x>10</x></position>
	</account_name>
	<account_exp>
		<height>100%</height>
		<horizontalAnchor>RIGHT</horizontalAnchor>
		<font>default_smaller.font</font>
	</account_exp>
…
</style>

Начебто все дуже структуровано і зрозуміло. Але, як виявилося, у такого підходу було кілька мінусів:
 
 
     
  • робота з багаторівневими XML складна в розумінні і приводила до великої кількості помилок, які важко локалізувати і виправити (наприклад, описки в іменуванні компонентів і шляхах до текстур, порушення структури XML-документа);
  •  
  • відсутність візуального середовища розробки. Єдина можливість одержання візуального результату — запуск клієнта гри і відтворення необхідного оточення для перегляду потрібного інтерфейсу. Уявити, як все це буде виглядати, подивившись на XML, було просто нереально;
  •  
  • погана продуктивність при обробці користувача введення (особливо це було помітно в чаті);
  •  
  • невеликий набір компонентів з коробки і складність додавання нових компонентів;
  •  
  • висока залученість програмістів в процес створення і внесення змін (навіть мінімальних) в GUI;
  •  
  • відсутність інструменту для створення анімації.
  •  
Всі ці мінуси приводили до створення інтерфейсів в стилі Programmer Art. За схематичного начерку програмісти робили layout в XML, і тільки потім художники створювали необхідні текстури і передавали все назад програмістам для фінальної налаштування і напілінга. Ось приклад такого інтерфейсу (на фото — робоче місце керівника проекту Олександра Шиляева із запущеним танковим клієнтом на стадії закритого альфа-тесту):
 
 image
 
Одна з перших версій бойового інтерфейсу:
  
 image
 
І трохи пізніша його версія:
  
 image
 
Дуже швидко стало зрозуміло, що такий підхід — тупиковий. Був проведений аналіз ринку middleware-рішень. Як виявилося, мейнстрімом в розробці GUI на той момент було рішення від Scaleform: практично всі AAA-проекти використовували його в розробці, і результати виглядали дуже привабливо.
 
 
предрелізний період: перехід на Scaleform
Scaleform пропонував використовувати Flash для розробки GUI. По суті, рішення складалося з трьох частин:
 
 
     
  • кастомной реалізації Flash Player, яку можна було вбудувати в ігровий клієнт;
  •  
  • набору інструментів для експорту SWF в спеціалізований формат;
  •  
  • бібліотеки компонентів CLIK — набору стандартних UI-компонентів і класів, які давали можливість прискорити розробку.
  •  
Восени 2009 року була куплена ліцензія, і почався новий етап розвитку GUI в проекті. На перших порах все виглядало багатообіцяюче: процес розробки Flash був відпрацьований роками, а розробників, знали і любили цей процес, було дуже багато. Однак виявилося, що ситуація на ринку праці в Білорусі на той момент складалася так, що більшість Flash-розробників вже сиділо на цікавих і «жирних» проектах, і швидко знайти і залучити якісні кадри з боку було складно.
 
З цієї причини в терміновому порядку вчити Flash почав весь відділ GUI (до цього вони робили php, Java і займалися веб-розробкою). Вчилися і починали роботу на ActionScript 2, так як Scaleform на той момент ще не підтримував ActionScript 3. Ось що виходило на перших порах:
 
 image
 
За півроку весь інтерфейс ангара був перероблений на Flash. Як я вже писав, pipeline розробки на Flash — відпрацьований і логічний процес. Дизайнери створюють ескізи, і програмісти втілюють їх у грі.
 
Ескіз:
  
 image
 
Реалізація:
 
 image
 
У лютому 2010 року почалося закрите бета-тестування проекту з уже оновленим ангаром. А ось бойовий інтерфейс все ще був на Python:
 
 image
 
Навесні 2010-го прийшов і його черга переходити на Scaleform. Коли це сталося, ігрове співтовариство розділилося на два табори. Одним все подобалося (або вони просто не помітили великої різниці) — і вони мовчки продовжували бадьоро рубатися в танки. Інші ж почали відкладати гори цегли на адресу «кривавої картоплі», кажучи про те, що нові приціли і елементи інтерфейсу не відповідають сеттінгу, що не вистачає рваного металу, болтів і заклепок, що приціли мають бути історичності, а не схожими на елементи управління космічним кораблем.
 
Один з робітників ескізів нового бойового інтерфейсу:
  
 image
 
Реалізація бойового інтерфейсу на Scaleform:
  
 image
 
Але з часом невдоволення пройшло, так як нові інтерфейси привнесли багато нового в геймплей. Гра стала динамічніше, інтуїтивно зрозуміліше і інформативніше.
 
Крім цього, використання Scaleform відкрило можливості по кастомізації інтерфейсів. Будь-який школяр, що вміє мінімально працювати з Flash, міг декомпілювати SWF з дистрибутива гри і на свій розсуд змінювати все — від використовуваних зображень і шрифтів, до логіки роботи коду. З'явилися моди, що замінювали приціли на історичність, «ляльку» танка на більш брутальну або, навпаки, минималистичную. Можна було знайти моди для будь-якої частини інтерфейсу в бою. Були моди і для ангара: годинник, калькулятори, багаторівнева карусель і т. д.
 
Керівництво Wargaming кілька разів змінювало своє ставлення до модам. Спочатку, оскільки це були поодинокі випадки, їх просто ігнорували. З часом і збільшенням їх числа і популярності — почали придивлятися і зрозуміли, що деякі з модів можуть дати ігрову перевагу котрі використовують їх гравцеві. Розробку стали вести за принципом «клієнт в руках ворога». Це, звичайно, не означає, що гравці — наші вороги. Нашим завданням стало максимально убезпечити гравців від чужих спроб отримати ігрову перевагу.
 
Ситуація на ринку модов стала ретельно моніторитись. Тепер у випадку виявлення небезпечних чи змінюють ігровий баланс модов ми оперативно реагуємо і закриваємо можливість їх використання, змінюючи логіку роботи клієнта. Останнім кілька років виготовлення чесних модов підтримується. По суті, це user generated content — гравці роблять ці моди для себе та інших гравців, що підвищує цінність нашого продукту.
 
Але повернемося до історії. Робота зі Scaleform дуже освіжила GUI і дала поштовх до його розвитку в проекті. Функціонал розростався і ускладнювався за час проходження закритої і відкритої бети і виходу проекту в реліз в серпні 2010. Додавалися нові фічі, доопрацьовувалися і наверталися вже існуючі. Змінювався дизайн, пробувалися різні підходи до подання інформації у грі та організації взаємодії з гравцем.
 
Варіанти реалізації фільтра техніки:
  
 
 
Зміни мінікарти:
 
 image
 
 
Постреліз: проблеми зростання і шляхи їх рішень
Із зростанням кількості коду і Ассет стали виповзати різні косяки.
 
Маркетинг Scaleform обганяв реальну розробку продукту і, як виявилося, багато із заявлених фіч або працювали не так, як хотілося, або сильно били по продуктивності, або взагалі були в зародковому стані. Була виконана величезна робота з поліпшення продуктивності Scaleform-плеєра, причому як з нашого боку, так і з боку розробників технології.
 
Що збільшився обсяг коду приводив до цікавого спецефектів. Кожна вьюха (або вікно) лежала у своїй FLA, містила свої Ассет і код і компілювати в окремий SWF-файл. Таких SWF було дуже багато, і на Рантайм вони довантажувати в клієнт для показу потрібного віконця або елемента керування, і, що характерно, порядок завантаження міг змінюватися залежно від того, що робив користувач в грі.
 
Проблема полягала в тому, що якщо змінювався код, який використовувався в декількох SWF, і після змін не всі ці SWF перезбирати, то на Рантайм могло статися таке. Першою завантажувалася SWF із застарілим кодом, і в кращому випадку все працювало по старому, а в гіршому — відбувалося падіння клієнта. Зрозуміти, що саме призводить до таких результатів, було важко. Нам доводилося придумувати інструменти та методики, що дозволяли відстежувати, що саме потрібно пересобрать після змін.
 
Також існувала проблема з якістю і консистентних коду і використанням різних патернів і стилів програмування. Так вийшло тому, що розробку на Flash в проекті починали люди, які не були професійними Flash-розробниками. Вони вчили Flash «в бою», і у кожного був свій бекграунд (C + +, php, Java). Виходило так, що при роботі в різних частинах проекту потрібно було переключатися з одного підходу на інший.
 
Ще однією болем була взаємодія Flash з Python. Передавати дані в будь-яку сторону можна було тільки у вигляді примітивних типів, що, звичайно ж, не задовольняло нашим запитам. Шляхів вирішення було два: використовувати JSON або ж розкладати всі складні типи в довгі масиви на одному кінці і збирати з цих масивів об'єкти на іншому.
 
Перший підхід добре працював, коли об'єкти були маленькими. Але при зростанні розміру об'єктів обсяги результуючих рядків росли, і це позначалося на швидкості виконання коду — вона падала. Другий підхід швидко працював, але був складний для розуміння при прочитанні коду і вимагав титанічних зусиль при реалізації змін в структурі даних.
 
До того моменту, коли всі ці проблеми стали сильно гальмувати розробку, Scaleform вже довів підтримку ActionScript 3 до прийнятного рівня. У нас визрівав план перевести інтерфейси ангара на нову версію мови і паралельно провести реструктуризацію проекту і створити свій framework, що дозволяє швидко і за певними правилами додавати нову функціональність в проект.
 
Роботи з підготовки переходу на ActionScript 3 почалися в кінці 2012 року. Як ми вирішували стоять перед нами проблеми, і які завдання ставили.
 
 Проблема: проблеми з різними версіями коду в різних SWF.
 Рішення: весь код додатку вкомпілівается в один SWF-файл, який завантажується при старті програми.
 
 Проблема: комунікація Flash <-> Python.
 Рішення: перехід на використання Direct Access API. Цей механізм дозволяє передавати складні об'єкти даних за допомогою автоматичної сериализации / десеріалізациі їх на рівні C + +. Також використання цього підходу збільшує продуктивність за рахунок того, що посилання на Flash-об'єкти можна передавати в Python і проводити маніпуляції над ними в Python безпосередньо, замість пошуку потрібного об'єкту в Flash по повному шляху до нього при кожній необхідності передачі даних.
 
 Проблема: стандартизація та уніфікація коду.
 Рішення: ми реалізували сервісну інфраструктуру і визначили набори інтерфейсів і базових класів, реалізуючи які нова функціональність додається в проект.
 
 Проблема: автоматизація збірки і додавання нового функціоналу в проект.
 Рішення: для збірки ми використовуємо Maven. Проект був реструктуровано і розбитий на більш логічні підпроекти і підсистеми. Для автоматизації додавання нового функціоналу ми використовували YAML в якості мови для опису інтерфейсів взаємодії Flash і Python. На базі YAML автоматично при складанні генерується код і створюються необхідні сутності — як у Flash, так і в Python. Все, що залишається зробити, це написати код і визначити точку входу для запуску нової функціональності.
 
Так, у вересні 2013 з виходом версії 8.8 лобі гри було повністю перероблено на ActionScript 3.
 
Ось і все на сьогодні. Деталі про структуру проекту та плани на майбутнє читайте в наступній статті.
    
Джерело: Хабрахабр

0 коментарів

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