Две предыдущие части (первая и вторая) были своего рода мануалами о том, как загружать модели и передвигать их. В этот раз я расскажу о том, как добавить больше интерактивности. В частности, статистику в реальном времени и столкновения.
Шаг 9. Столкновения
Это, возможно, самая трудная часть. Дело в том, что существует прям много способов понять, что два объекта сталкиваются. Каждый имеет свои плюсы и минусы, и ваша задача - выбрать тот, который больше подходит. Если вам интересно, то зацените раздел Ресурсы в конце, там я оставлю список материалов для изучения на эту тему.
Вот эти способы:
Raycasting. Этот метод первым приходит на ум, когда вы произносите вслух слово "Столкновения". Когда вы кастуете заклинание, то вам уже известна траектория, по которой полетит файрбол. Так что вы можете провести воображаемый луч в этом направлении и проверить, а не столкнется он с чем-нибудь. Обычно он используется для пуль, а файрбол так быстро не летит, так что метод нам тут не подойдет.
Spatial grid. В этом подходе все игровое поле делится на ячейки определенного размера и производится проверка, какие другие объекты находятся в той же самой ячейке, что и файрбол (ну или в одной из ближайших).
Boid-like. Этот метод похож на raycasting. По сути, в нем и используется raycasting, только много раз и в нескольких направлениях.
AABB method. Каждый объект в сцене имеет некоторый bounding box, коробку, в которую он вписан. Существуют методы определения их столкновений (напр. Three.js BoxHelper).
Ammo.js С помощью физического движка вы можете симулировать физический мир, передвигать в нем объекты, которые представляют объекты вашей сцены и выяснять и движка, а какие из них сейчас сталкиваются. Это, возможно, самый точный метод, но он же и самый сложный.
Naive. Наконец, можно же просто опросить все остальные объекты, а как далеко они находятся от файрбола. Это самый медленный, но и самый простой способ.
У нас получилась, я бы сказал, 2.5D-игра, ни один объект не меняет Y координаты. Поэтому самый простой выбор будет последний, Naive.
Итак, содадим компонент Collidable который будет выполнять всю работу:
Для этого он будет хранить ссылки на все collidable-объекты в глобальном хранилище.
Естественно, нужно будет обернуть в него файрболы, врагов и игрока и написать колбеки:
Шаг 10. Статистика
В общем, весь код, который относится к WebGL, должен быть расположен внутри компонента Canvas. Но что если мы поместим немного HTML вне его? Точно. Все будет выглядеть так, как мы к этому привыкли. В этом шаге все обычно: выбрать данные из стора, отобразить их в диве, немного css.
Попробуйте сыграть! Пишите комменты, если вам все ок.
Conclusion
Естественно, я не причисляю себя к великим разработчикам игр. В мире огромное количество отличных примеров того, как надо работать с WebGL, я постоянно вижу их в Твиттере. Круто, что люди делятся своим опытом. Btw, here are some links to stay in touch: twitter, linkedin, github.
Ресурсы
https://stemkoski.github.io/Three.js/Collision-Detection.html — опреление столкновений на основе raycasting
https://www.youtube.com/watch?v=sx4IIQL0x7c — крутое видео о spatial grids
https://www.youtube.com/watch?v=bqtqltqcQhw — крутое видео о боидах
https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_collision_detection/Bounding_volume_collision_detection_with_THREE.js — статья с объяснением того, как определять столкновения на основе bounding box
https://mozdevs.github.io/gamedev-js-3d-aabb/physics.html — physics based (ammo.js) collision detection
https://medium.com/@bluemagnificent/intro-to-javascript-3d-physics-using-ammo-js-and-three-js-dd48df81f591 — интро three.js и ammo.js