Тема: Оброблення зіткнень між об'єктами у 2д грі
Вітаю. Пиляю тут у вільний час навеличкий TDS (Top Down Shooter) на канвасі з мрією приліпити то все колись до веб-сокетів й погратися з друзями
Маю пару питань.
Зараз маю таке. Є мапа, у вигляді масиву (потім можливо перенесу це все у .json формат чи у БД, коли більше тайлів буде, бо зараз більше вчуся, ніж розробляю). Ось якось так:
var map = [
[0, 1, 1, 0],
[1, 0, 0, 0],
[1, 0, 1, 1],
[1, 1, 0, 0]
];
Проходячи по масиву, малюю потрібний тайл:
for (var y = 0; y < map.length; y++) {
for (var x = 0; x < map.length; x++) {
// вибираємо потрібний тайл в залежності від елементу масива
ctx.drawImage(tile, x*32, y*32, 32, 32);
}
}
Я код трошки спрощую, щоб не розтягувати пост.
Так ось є така мапа. Ще є герой, якого малюю тим же способом:
ctx.drawImage(skin, this.x, this.y);
У нього є властивості x i y які відповідають за його координати (у пікселях від початку канваса). Далі вже дивлюся на натиснуті клавіши й якщо треба рухати героя, то змінюю йому значення цих властивостей (наприклад на 2 пікселі) та знову перемальовую все спочатку.
Тобто герой рухається не по клітинках, а вільно. Але тайли на фоні (земля, стінки тощо) мають фіксований розмір (32х32) й розташовані у вигляді таблички. Тобто звичайна тайлова мапа. І тепер власне питання: як зрозуміти, що герой наткнувся на ту ж стінку, наприклад?
Як визначити, що закінчився канвас, я знаю: дивимося координати героя, й перевіряємо чи не менші вони за 0, та чи не більші за висоту/ширину самого канваса. Це просто. Як зрозуміти, що герой врізався у стінку, це я теж якось через одне місце зробив. Я беру чотири краї спрайту героя, і для кожної перевіряю, чи в тому випадку, коли відбудеться переміщення, чи будуть вони розташовані (будь-який з цих країв) на тайлі. Рахую це, так:
var a = map[ Math.floor(this.y/tileSize) ][ Math.floor((this.x-step)/tileSize) ];
Це приклад, лівого верхнього краю, під час перевірки можливості руху ліворуч. Далі дивлюся, якщо ця змінна не містить тайлів через які не можна пройти, то все добре: переходимо до обробки наступного краю/переміщення героя.
Ніби і все нормально працює. Так все дійсно нормально працює, але що робити далі? Якщо в мене буде велика мапа в тій же БД, і треба буде показати гравцеві тільки частину мапи, як її намалювати? Взяти з БД потрібні тайли - ок, але чи буде добре у тому випадку працював алгоритм просто перебору масиву двома циклами, якщо мапа буде рухатися й може статися, що треба малювати починаючи не з початку тайлу, а наприклад з середини? Тобто буде неможливо намалювати так, щоб на екрані було ціле число тайлів у рядку чи стовпчику, при чому "обрізаний" тайл буде на початку. Які ще є методи малювання таких мап, як зручніше зробити?
Також, проблема в тому, що далі будуть з'являтися монстри там, чи якісь предмети, для них писати окремий алгоритм обробки з ними зіткнень, окремо від того, що обчислює зіткнення гравця зі стінами? І як такий алгоритм має виглядати? Так само перебирати кожного монстра та порівнювати його координати з координатами героя? Просто монстри/предмети як і гравець не будуть розташовані чисто по клітинках. Як гадаєте краще зробити?
Можете підказати будь ласка, або кинути ресурс, де нормально пояснюється вирішення такої проблеми.
Дякую
P.S. Чому я не використовую готову бібліотеку, де це вже реалізовано: це чисто хоббі і роблю це в задоволення. Хочу зрозуміти, як це все робиться, бо мені це цікаво