
Я побудував гру у захист замку з нуль залежностями — штучне інтелектуальне мистецтво, процедурний звук та близько 3 200 рядків чистого JS
https://ift.tt/lv2ZMYq
Немає React. Немає Phaser. Немає Pixi.js. Немає npm install. Просто <canvas>, ванільний JS та Web Audio API.
🎮 Грати тут · 📖 Повний щоденник розробки
Що я збудував
Arcane Bastion — це кристалічний шутер захисту замку з:
- 5 елементних веж (Вогонь / Лід / Електрика / Лоза / Аркан) × 3 рівні апгрейду
- 10 типів ворогів з ефектами стану (замерзання, обпалення, отруєння)
- Ін-art AI — кожний спрайт та фон карти згенеровані штучним інтелектом
- Процедурний звук — кожен звуковий ефект синтезований з осциляторів, жодних аудіофайлів
- Динамічна орієнтація вежі — плавне слідкування з відгуком відбиття
Уся історія складається з 9 скриптових файлів, завантажених за допомогою тегів <script> у порядку залежностей. Старомодно, але працює.
Архітектура
arcane-bastion/
├── js/
│ ├── sprites.js ← асинхронний завантажувач зображень (18 активів)
│ ├── map.js ← 20×14 плиткова сітка + фони для AI
│ ├── tower.js ← 5 типів, цілепокладання, плавне обертання
│ ├── enemy.js ← 10 типів, навігація за шляхом
│ ├── projectile.js ← вогнепальні ракети з наведенням, ланцюгова блискавка
│ ├── audio.js ← синтез за допомогою Web Audio (~400 рядків)
│ ├── ui.js ← HUD, панелі, накладка на біографію
│ ├── game.js ← цикл 60fps, стан хвилі
│ └── demo-mode.js ← запрограмований авто-демо + MediaRecorder
Найважчий баг: політика автоплей Chrome 🔇
Цей баг з’їв чимало годин. Мій аудіо-двигун відпрацював нормально у локальному тестуванні, але після розгортання в Chrome став повністю тишею.
Проблема коріння: створення AudioContext до першого руху користувача переводить його у стан сну — назавжди. Мій Game.init() викликав AudioEngine.init() під час завантаження сторінки.
Виправлення:
// ❌ ПОГАНО: створює AudioContext під час завантаження сторінки
function init() {
ctx = new AudioContext(); // замовкне назавжди!
}
// ✅ ДОБРЕ: ліниве створення при першій взаємодії користувача
function init() {
document.addEventListener('click', () => {
if (!ctx) {
ctx = new AudioContext();
// тепер працює, бо користувач вперше тиснув
}
});
}
І найважливіше — кожна звукова функція повинна викликати ensureContext() перед охороною if (!ctx) return, а не після. Якщо порядок помилковий — контекст ніколи не створиться.
AI Art: не підключається “з коробки”
Я згенерував усі 18 візуальних елементів (5 веж, 10 ворогів, 3 карти) за допомогою генерації зображень за штучним інтелектом. Звучить легко, так?
Реальність:
- Послідовність — кожен запит потребував однакового стилістичного якоря: “темне фентезі, піксель-арт, зверху вниз, сяючі магічні ефекти”
- Прозорість — ранні спрайти мали видимі прямокутні фони. Кожен потребував ручного очищення
- Контраст — спрайти, які добре виглядали на білому тлі, зникали на темних фонах карти. Потрібно було додати сяйво ореолів та підсвітку
- Масштаб — красивий 512×512 спрайт на ігровому масштабі стає розмитим 50px штучкою
AI-арт зберіг тижні ілюстраційної праці, але інтеграційна “остання миля” все одно вимагала значної ручної роботи.
Процедурний звук: математика → звук
Найбільш задовольняюча система для розробки. У кожному звуці гри використовується синтез з формами хвилі OscillatorNode:
// Аттак вежі frost: кристалічний “пінг”
function frostShoot() {
playTone(1200, 0.15, 'sine', 0.12); // високий блиск
playTone(800, 0.2, 'triangle', 0.08); // гармоніка
playNoise(0.08, 0.1); // лідяний тріск
}
Вогонь, лід, блискавка, ліана, аркан — у кожному елементі унікальна аудіо-підпис створена шляхом поєднання типів осциляторів (sine, triangle, sawtooth, square) на різних частотах та тривалостях.
Фоновий музичний супровід — це багатопроцесорний амбієнтний дрон, який еволюціонує з часом. Загалом аудіо-система близько 400 рядків — жодних аудіо-активів не завантажується.
Три зміни, які зробили найбільшу візуальну різницю
- Замінені процедурні фони карт AI на атмосферні
- Сяйво ореолів на спрайтах веж (радіальна градієнтна кола позаду кожної вежі) — миттєва глибина
- Плавне обертання вежы за допомогою
Math.atan2+ лерп-інтерполяція — усе стало живим
Жодна з цих змін не вплинула на геймплей. Усі вони змінили відчуття від гри.
Остаточна статистика
| Показник | Значення |
|---|---|
| Рядків JS | ~3 200 |
| Модулі коду | 9 |
| AI-генеровані активи | 18 |
| Зовнішні залежності | 0 |
| Аудіо-файли | 0 |
| Інструменти збірки | 0 |
Я написав набагато глибший технічний розбір, що охоплює системи сіток, пошук шляхів, реалізацію ланцюгової блискавки, синергію веж та те, як я записував демонстраційне відео з аудіо за допомогою API MediaRecorder у браузері.
📖 Прочитати повний розбір розробки понад 3000 слів →
HI-FI News
через DEV Community https://dev.to
16 березня 2026 р. о 13:39PM
March 16, 2026 at 01:39PM

Залишити відповідь
Щоб відправити коментар вам необхідно авторизуватись.