uk:authors_main:task_editor:advanced:inventory

Інвентар гравця

Інвентар — це сумка з предметами, які гравець знаходить упродовж гри і застосовує до речей на рівні: ключ до замка, лом до кришки, монету до автомата. Предмет — це рядок-ключ (hammer123), і вся гра з ним зводиться до кодів: застосував предмет — рушій увів за гравця код.

Версій інвентаря дві, і вони живуть поруч.

  • Друга — панель унизу екрана, сумка з лічильником, предмети застосовуються до зон на картинці завдання. Вмикається одним рядком у скрипті, місця в тексті завдання не потребує. Про неї вся ця сторінка.
  • Перша — список предметів у відведеному автором блоці, у предмета дві кнопки: «око» і «застосувати». Вона працює як працювала й описана наприкінці сторінки; в ігор, що йдуть, її не забирають.

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

Унизу екрана — кнопка-сумка. На ній загальна кількість предметів і окремо «+N» — скільки нових; поки нові є, сумка подригує.

Згорнута сумка: скільки всього предметів і скільки з них нових

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

Розкрита панель: смуга предметів унизу екрана, новий предмет підсвічено

Застосувати предмет можна двома способами, і вони рівноправні:

  • перетягнути предмет на місце застосування;
  • натиснути на предмет, а потім на місце застосування.

Щойно предмет «у руках», на рівні загоряються всі місця, куди його можна застосувати, — зони. Поряд із сумкою тієї ж миті з’являються ще два приймачі: «застосувати» (без зони, просто саме по собі) і «око» — подивитися предмет великим.

Предмет у руках: на картинці загорілися зони, поряд із сумкою — «око» і «застосувати»

Відпустив повз або натиснув порожнє місце — предмет повернувся в сумку.

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

Розкрита панель і місце, до якого гравець догортав смугу, переживають перезавантаження сторінки: код уведено, рівень змінився — сумка лишилася відкритою на тому самому місці.

Панель притиснута до низу вікна, а не стоїть у тексті завдання, тому на телефоні предмет і місце застосування не зобов’язані вміщатися на екран одночасно.

Вузький екран: смуга і приймачі притиснуті до низу й не їдуть зі скролом

У скрипт завдання (поле внизу рівня):

showInventoryItems2({gameId: 1234});

Більше нічого не треба: ні блоку в тексті завдання, ні id — панель рушій малює сам.

gameId — гра, у теці якої лежать картинки предметів. Можна не вказувати, тоді береться поточна гра, — але див. про копіювання гри.

Виклик має стояти саме у скрипті завдання. Рушій під’єднує другу версію, побачивши showInventoryItems2 у скрипті рівня; з тексту завдання, з бонуса чи із спільної шапки гри він її не під’єднає — функції просто не буде.

І виклик має бути один: він забирає накопичений список предметів, і другий за те саме промальовування намалює порожню сумку.

Предмет видається з «Тексту після розв’язання» бонуса — у режимі «Джерело»:

<script>
addInventoryItem('hammer123');
</script>

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

<script>
removeInventoryItem('hammer123');
</script>
Тексти розв’язаних бонусів рушій виконує заново на кожному промальовуванні сторінки. Тому список предметів не зберігається ніде: він щоразу збирається з нуля з того, що вже розв’язано. Сервер про предмети не знає нічого.

Із цього ж випливає і зворотний прийом: видавати предмети не бонусами, а самим скриптом завдання, порахувавши за введеними кодами, що зараз має лежати в сумці. Так зроблено рівень-приклад із полицею — книжку можна поставити, зняти й замінити іншою, і окремих кодів на це не треба.

Наскрізний бонус. Предмет, виданий наскрізним бонусом, звичайним бонусом рівня не забрати — тільки наскрізним із більшим порядковим номером.

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

Картинка предмета шукається за іменем файлу: item_<ключ> — іконка у смузі, item_<ключ>_big — те, що відкривається за «оком».

Заливати обидві руками не треба. Залийте одну картинку з іменем item_hammer123.png у файли гри: якщо вона від 512 точок по обох сторонах, рушій сам розкладе її на іконку і велику версію. Дрібніша — лишиться одним файлом, і «око» покаже її ж.

У списку залитих файлів у такої картинки з’являється готовий рядок addInventoryItem('hammer123') — за кліком він копіюється в буфер. Вставляти в бонус треба саме його: предмет під’єднується ключем, а не адресою файлу.

Ім’я такого файлу рушій зберігає як є, навіть якщо галочку «Зберегти назву» знято: інвентар шукає картинку за іменем. Ключ береться з імені разом із регістром — це рівно той рядок, що йде в addInventoryItem().

Формат

Типово рушій шукає .jpg. Картинки в іншому форматі — зокрема прозорі png, заради яких у панелі й зроблено слот і тінь, — оголошуються один раз на гру, у «Спільному HTML-заголовку»:

<script>
setInventoryImageExt('png');
setInventoryBigExt('png');
</script>

Іконка і великий вигляд оголошуються окремо: вони можуть бути в різних форматах. Поштучний виняток — другим аргументом:

addInventoryItem('map7', {icon: 'png', big: 'png'});

Розширення не входить у ключ: ключ — це код, який іде на сервер.

Картинки при копіюванні гри

Картинки предметів беруться з теки тієї гри, чий номер ви передали. Копіювання гри файли не копіює, тому в копії картинки зникнуть — якщо gameId не названо явно або він указує на саму копію.

Прив’яжіть інвентар до гри, у яку залито картинки:

showInventoryItems2({gameId: 3493});

Той самий номер можна задати один раз на всю гру, у «Спільному HTML-заголовку», — він копіюється разом із грою:

<script>
setInventoryGameId(3493);
</script>

Зона — місце на рівні, до якого застосовують предмет: двері, замок, торговець, слот полиці. У зони є код.

Коли гравець застосовує предмет до зони, рушій уводить складений код: код зони + ключ предмета. Лом (crowbar) на зону lid — це код lidcrowbar. Такий код і має стояти в бонуса, який відкриває кришку.

Лом на важіль: код — це ім’я зони плюс ключ предмета

Зона, під яку коду немає, просто відповідає «не підійшло», і предмет повертається в сумку. Вигадувати «порожні» зони не потрібно: зона без відповідного предмета нічим не загрожує.

Застосування без зони — «застосувати» поряд із сумкою — уводить код, що дорівнює ключу предмета (як у першій версії).

Код зони і ключ склеюються без роздільника, тому імена варто розводити самому: зона slot із предметом 1book і зона slot1 із предметом book дадуть один і той самий код.

Перевіряти на боці гравця, який предмет до якої зони підходить, рушій не вміє і не буде: тоді правильна відповідь лежала б у джерелі сторінки. Будь-який предмет на будь-яку зону — це просто код, і відповідає на нього сервер.

Чотири способи, і всі вони про одне й те саме — точку і радіус навколо неї. Різняться тим, звідки береться точка.

Точка на картинці (інлайновий svg)

Основний спосіб, коли на картинці кілька місць застосування. У тексті завдання, у режимі «Джерело»:

<svg viewBox="0 0 800 600">
  <image href="https://cdn.qeng.org/f/g/1234/room.jpg" width="800" height="600"/>
  <circle data-inventory-zone="door" cx="410" cy="255" r="40" fill="none"/>
  <circle data-inventory-zone="chest" cx="96" cy="470" r="55" fill="none"/>
</svg>

Координати живуть у системі viewBox, тобто прив’язані до картинки, а не до екрана: телефон, десктоп, поворот, зум — точка лишається на тому самому місці малюнка. Перераховувати нічого не треба.

r — радіус застосування в одиницях картинки. На малому екрані картинка стискається, і разом із нею стискалася б зона, — рушій сам піднімає область влучання до пальця.

Годяться не тільки circle: у будь-якої фігури береться її габаритний прямокутник.

Картинка, вставлена як <img>, так не розмічається: у зовнішнього svg немає доступного рушієві вмісту. Для картинки в <img> — спосіб із відсотками нижче.

Відсотки на картинці

Найдешевший спосіб, коли svg розводити не хочеться:

<img src="..." data-inventory-zones="door:41,42 chest:12,78,6">

Через двокрапку — код зони, далі відсотки від розмірів самої картинки: x, y і (необов’язково) радіус. Зон в одному атрибуті може бути скільки завгодно, через пробіл.

Свій значок так задати не можна — тільки спільний на всі зони носія. Потрібен свій у кожної — беріть data-inventory-zone на окремих елементах або addInventoryZone().

Будь-який елемент сторінки

<div data-inventory-zone="npc">Торговець</div>
<img src="..." data-inventory-zone="lock">

Область влучання — прямокутник елемента цілком. Це відповідь для випадку «зона — це блок тексту, картинка цілком або кнопка».

Зі скрипта

Зона, якої на рівні спочатку немає, оголошується викликом — у скрипті завдання або в «Тексті після розв’язання» бонуса:

addInventoryZone('box', {el: '#room', x: 120, y: 150, r: 45});

Перший аргумент — код зони. Далі:

Поле Що означає
el носій: селектор або елемент. Обов’язковий — він задає систему координат
x, y позиція всередині носія; без них — центр елемента, а область влучання — весь його прямокутник
r радіус застосування; без нього — розмір значка, піднятий до пальця
icon свій значок зони; без нього спільний

Одиниці визначає носій: інлайновий svg — координати його viewBox, будь-який інший елемент — відсотки його прямокутника (радіус — відсотки меншої сторони). Ті самі {x: 150, y: 262} на svg і на картинці означають різне. Абсолютних екранних координат немає навмисно: вони поїхали б на першому ж іншому екрані.

Повторний виклик із тим самим кодом не заводить другу зону, а оновлює наявну. Отже, зону можна й рухати: перерахував позицію — покликав ще раз.

Прибрати — removeInventoryZone('door'). Зону з розмітки цей виклик теж зніме, але тільки до найближчого автооновлення: html прийде із сервера знову, і зона повернеться. Прибирати її треба там само, де прибирається все інше на рівні, — шаблоном на сервері.

Зона зі скрипта перекриває зону з розмітки з тим самим кодом.

Типово в усіх зон один спільний напівпрозорий значок. Свій задається в розмітці атрибутом data-inventory-zone-icon або полем icon у addInventoryZone(), і вид його оголошувати не треба — рушій розрізняє сам:

<circle data-inventory-zone="door" data-inventory-zone-icon="fa-lock" .../>
<circle data-inventory-zone="gate" data-inventory-zone-icon="/f/g/123/door.png" .../>
<circle data-inventory-zone="safe" data-inventory-zone-icon="🔑" .../>
  • fa-lock — значок font-awesome;
  • шлях або адреса — своя картинка;
  • будь-що інше — просто символ.

Набір зон зазвичай залежить від того, що гравець уже зробив: у розкритої скрині зон немає, щілина автомата з’являється разом із монетою. Розмітку під це зручно збирати шаблонами {% match bonus_N %} — вони рахуються на сервері, тому в джерелі сторінки у гравця лежать тільки ті шари і зони, що видно зараз.

У скрипті завдання шаблони працюють так само, але рядки шаблона коментуються подвійним слешем — рушій знімає коментар сам:

// {% match bonus_2}:{
//   {%= leverdncrowbar}:{
addInventoryZone('leverup', {el: '#quest_room', x: 288, y: 305, r: 45});
//   %}
//   {%= ?}:{
addInventoryZone('leverdn', {el: '#quest_room', x: 315, y: 112, r: 45});
//   %}
// %}
  • Ключ предмета — це код. Крапки, лапки і розширення в нього класти не можна.
  • Застосування завжди мовчазне: у формі відповідей нічого не з’являється. Весь зворотний зв’язок — на самому предметі й на зоні.
  • Вердикт рушій читає з блоку «Попередні відповіді». Якщо моніторинг на рівні вимкнено, предмет просто мовчки повернеться в сумку — без зеленого й червоного.
  • Той самий неправильний код удруге не йде на сервер. Предмет повернеться одразу, з тим самим вердиктом, що й минулого разу, — спроба не витрачається.
  • Схований носій зони не дає. Зона на елементі всередині згорнутого <details>, на display: none або на ще не завантаженій картинці не з’явиться — доти, доки носій не покажеться. Перерахунок рушій робить сам: при зміні розмірів вікна, завантаженні картинки і тієї миті, коли гравець бере предмет.
  • Поки предмет у руках, значок зони лежить поверх сторінки і перехоплює клік по тому, що під ним, — зокрема по вашій кнопці.
  • Синоніми бонуса — це стан. Значення бонуса в шаблоні — його остання введена відповідь, а кожен новий синонім заміняє попередній. Тому важіль ходить туди-сюди, а книжка ставиться і знімається: два синоніми в одного бонуса замість двох бонусів.
  • Опис бонуса %hide% не видно в джерелі сторінки до розв’язання — ланцюжок застосувань не підглянути.
  • Схований рушієм бонус друкується без введеної відповіді. Якщо відповідь потрібна скрипту, ховайте блок бонусів стилем, а не позначкою.
  • Панель живе поза автооновлюваною частиною сторінки: чужий код або нова підказка її не закриють і вибраний предмет не заберуть.
  • Розкрита панель відсуває низ сторінки. Свій притиснутий до низу блок із нею посперечається.

Чого в інвентаря немає: кількості (предмет або є, або немає — «три монети» робляться трьома предметами чи кодами), сортування і перетягування предмета на предмет.

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

В обох рівнів усередині є розділ «Як так зробити?» з розбором.

Працює як працювала. Різниться тим, що інвентар малюється у відведеному автором блоці, зон немає, а у вибраного предмета дві кнопки — «око» і «застосувати».

Інвентар першої версії: предмети приходять за розв’язані бонуси

Вибраний предмет: «око» показує картинку великою, галочка — використовує предмет

  1. У текст завдання (у режимі «Джерело») — блок, де показувати список:
<div id="inventory_container">Завантаження інвентаря...</div>
  1. У скрипт завдання — виклик:
showInventoryItems('inventory_container');

Другим параметром — та сама прив’язка картинок до чужої гри: showInventoryItems('inventory_container', 1234).

Предмети видаються і забираються так само, addInventoryItem() і removeInventoryItem() у «Тексті після розв’язання» бонуса. Кнопка «застосувати» вводить код, що дорівнює ключу предмета.

Предмет приходить за бонус, а «використати» вводить його код за гравця

Приклад у грі: Інвентар.

  • uk/authors_main/task_editor/advanced/inventory.txt
  • Востаннє змінено: 2026/09/18 06:51
  • (зовнішнє редагування)