Как создать 3d игру прямо в браузере

от автора

Привет всем. Сегодня я вам расскажу как легко вы можете создать 3d игру прямо в вашем браузере и сделать вы сможете это очень быстро, примерно за минут 30.

Three.js

Это библиотека которая позволяет создавать 3д графику, она довольно проста и мощна. Мы будем использовать только её и больше никаких других фреймворков. Чтобы её подключить вам нужно скачать файл из этого рипозитория в папке build/three.js. Я качаю файл three.min.js (точно такая же, но весит меньше) и просто подключаю.

<html>   <head></head>    <body style="margin:0px;">     <script src="three.min.js"></script>      <script>     //тут пишем код     </script>    </body> </html>

Обратите внимание что отступы у body стоят нулевые, это нужно чтобы экран не съезжал вправо.

scene, camera и renderer

Создание графики в данной библиотеке основано на трёх столпах. Первое Scene это весь наш мир, вся информация, которая содержится о нём. Второе Camera это объект, который обозначает с какого ракурса мы будем смотреть на этот мир. Третье Render, объект который обрабатывает камеру и сцену и выдаёт результат на экран. Давайте создадим эти три объекта для начала.

var scene = new THREE.Scene();  //камера содержит 4 аргумента: угол обзора в градусах, отношение сторон экрана, и растояние обработки минимальное и масимальное var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); camera.lookAt(new THREE.Vector3(0, 0, 0)); //указываем куда будет смотреть камера scene.add(camera);  var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); //указываем размеры рендера, которые соответсвую нашей камере document.body.appendChild(renderer.domElement); //добавляем DOM элемент рендара в html код

Также нам нужна функция анимации, которая будет покадрово обновлять сцену.

function animate() {   requestAnimationFrame(animate);//вызываем функцию при каждом обновлении кадра    renderer.render(scene, camera);//обновляем рендер } animate();//вызываем первый раз функцию

Автообновление размеров экрана

Размеры окна браузера могут меняться нам нужно поставить событие на изменение размеров и обновлять размеры камеры и рендера.

function setSize() {     renderer.setSize(window.innerWidth, window.innerHeight);// устанавливаем размеры рендера     camera.apect = window.innerWidth/window.innerHeight;//устанаваливает отношение сторон камеры     camera.updateProjectionMatrix();//обновляем камеру } window.addEventListener("resize", setSize);//создаем событие на изменение размеров окна браущера

Освещение

Чтобы было что-товидно нам нужен свет. Я создам два типа света, первый свет Ambient, которая распределён равномерно по всей сцене и как бы имитирует солнце. И второй Point (точечный) имитирует свет лампочки.

var light = new THREE.AmbientLight(0xffffff, 0.2);//создаем равномерный свет белого цвета с мощностью 0.2 scene.add(light);//добавляем в сцену равномерный свет var light = new THREE.SpotLight(0xffffff);//создаем точечный свет белогоцвета light.position.set(0, 5, 0);//задаем координаты точечного света scene.add(light);//добавляем в сцену точечный свет

Создаём первый объект

Объекты в three.js добавляется путём задание геометрии объекта и материала. Для начала создадим пол коричневого цвета, это будет просто обычный параллелограмм. Поэтому геометрию возьмём BOX и просто растянем его под размеры параллелограмма, а материал возьмём Phong чтобы хорошо было видно отражение точечного света.

//создаём пол с геометрией куба и Phong материалом коричневого цвета, side указываем с обоих сторон материал var floor = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0xad7600, side: THREE.DoubleSide})); floor.scale.set(5, 0.1, 10); //устанавливаем нужные размеры floor.position.y = -0.5; //указываем координату чтобы он был под ногами scene.add(floor); // добавляем в сцену

Смотрим что получилось:

Как мы видим у нас под ногами пол коричневого цвета.

Управление

Теперь нам нужно осуществить управление. Сделаем его с помощью кнопок WASD. W и S будем ходить вперёд назад. A и D будем поворачивать камеру по вертикальной оси. Сначала будем отслеживать нажатие кнопок WASD и записывать в переменную какая кнопка нажата в данный момент

var keys = { w: false, a: false, s: false, d: false }; //переменная указывает какие кнопки нажаты сейчас function keyDown(e) {   //если нажали какую-то кнопку запишем в переменную это   if (e.code == "KeyW") {     keys.w = true;   } else if (e.code == "KeyA") {     keys.a = true;   } else if (e.code == "KeyS") {     keys.s = true;   } else if (e.code == "KeyD") {     keys.d = true;   } } function keyUp(e) {   //если отпустили кукую-то кнопку запишем в переменную это   if (e.code == "KeyW") {     keys.w = false;   } else if (e.code == "KeyA") {     keys.a = false;   } else if (e.code == "KeyS") {     keys.s = false;   } else if (e.code == "KeyD") {     keys.d = false;   } } window.addEventListener("keydown", keyDown);//событие нажатие кнопки window.addEventListener("keyup", keyUp);//событие отпускание кнопки

Теперь зная какая кнопка нажата в данный момент, мы можем в нашу функцию анимации добавлять координаты и поворот камеры. Вот как мы изменяем функцию animate

function animate() {   var speed = 0.05;//скорость пердвежение   if (keys.w && !keys.s) {//если нажата w и не нажата s     //идем вперет в зависиости от поворота камеры     position[0] += speed*Math.sin(rotate);     position[1] += speed*Math.cos(rotate);   }   if (!keys.w && keys.s) {//если нажата s и не нажата w     //идем назад в зависимости от поворота камеры     position[0] -= speed*Math.sin(rotate);     position[1] -= speed*Math.cos(rotate);   }   if (keys.a && !keys.d) {//если нажата a и не нажата d     rotate += speed; //поворачиваем влево   }   if (!keys.a && keys.d) {//если нажата d и не нажата a     rotate -= speed; //поворачиваем вправо   }   // добавляем ограничения по координатам чтобы мы не могли уйти бесконечно далеко   if (position[0] > 2.3) { position[0] = 2.3 }   if (position[0] < -2.3) { position[0] = -2.3 }   if (position[1] > 4.8) { position[1] = 4.8 }   if (position[1] < -4.8) { position[1] = -4.8 }   //устанаваливаем координаты камеры   camera.position.x = position[0];   camera.position.z = position[1];   //устанавливаем точку куда должна смотреть камера   camera.lookAt(position[0]+5*Math.sin(rotate), 0, position[1]+5*Math.cos(rotate))   //эти две строчки уже и так были в той функции   requestAnimationFrame(animate);   renderer.render(scene, camera); }

Теперь мы можем передивигаться.

Заканчиваем

Теперь же просто для завершённости проекта добавим еще стены и потолок точно по такому же принципу как с полом и покрасим стены в зелёный и потолок в сиреневвый.

var wall1 = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0x00870e, side: THREE.DoubleSide})); wall1.scale.set(5, 1, 0.1); wall1.position.z = 5; scene.add(wall1);  var wall2 = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0x00870e, side: THREE.DoubleSide})); wall2.scale.set(5, 1, 0.1); wall2.position.z = -5; scene.add(wall2);  var wall3 = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0x00870e, side: THREE.DoubleSide})); wall3.scale.set(0.1, 1, 10); wall3.position.x = 2.5; scene.add(wall3);  var wall4 = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0x00870e, side: THREE.DoubleSide})); wall4.scale.set(0.1, 1, 10); wall4.position.x = -2.5; scene.add(wall4);  var ceil = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0xff00aa, side: THREE.DoubleSide})); ceil.scale.set(5, 0.1, 10); ceil.position.y = 0.5; scene.add(ceil);

Вот что у нас получилось:

Конечный код

Вот полностью код, который мы написали:

<html>   <head></head>    <body style="margin:0px;">     <script src="three.min.js"></script>      <script>       var scene = new THREE.Scene();        var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);       camera.lookAt(new THREE.Vector3(0, 0, 0));       scene.add(camera);        var renderer = new THREE.WebGLRenderer();       renderer.setSize(window.innerWidth, window.innerHeight);       document.body.appendChild(renderer.domElement);        function setSize() {           renderer.setSize(window.innerWidth, window.innerHeight);           camera.apect = window.innerWidth/window.innerHeight;           camera.updateProjectionMatrix();       }       window.addEventListener("resize", setSize);        var floor = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0xad7600, side: THREE.DoubleSide}));       floor.scale.set(5, 0.1, 10);       floor.position.y = -0.5;       scene.add(floor);        var wall1 = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0x00870e, side: THREE.DoubleSide}));       wall1.scale.set(5, 1, 0.1);       wall1.position.z = 5;       scene.add(wall1);        var wall2 = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0x00870e, side: THREE.DoubleSide}));       wall2.scale.set(5, 1, 0.1);       wall2.position.z = -5;       scene.add(wall2);        var wall3 = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0x00870e, side: THREE.DoubleSide}));       wall3.scale.set(0.1, 1, 10);       wall3.position.x = 2.5;       scene.add(wall3);        var wall4 = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0x00870e, side: THREE.DoubleSide}));       wall4.scale.set(0.1, 1, 10);       wall4.position.x = -2.5;       scene.add(wall4);        var ceil = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshPhongMaterial({color: 0xff00aa, side: THREE.DoubleSide}));       ceil.scale.set(5, 0.1, 10);       ceil.position.y = 0.5;       scene.add(ceil);        var light = new THREE.AmbientLight(0xffffff, 0.2);       scene.add(light);       var light = new THREE.SpotLight(0xffffff);       light.position.set(0, 5, 0);       scene.add(light);        var keys = { w: false, a: false, s: false, d: false };       function keyDown(e) {         if (e.code == "KeyW") {           keys.w = true;         } else if (e.code == "KeyA") {           keys.a = true;         } else if (e.code == "KeyS") {           keys.s = true;         } else if (e.code == "KeyD") {           keys.d = true;         }       }       function keyUp(e) {         if (e.code == "KeyW") {           keys.w = false;         } else if (e.code == "KeyA") {           keys.a = false;         } else if (e.code == "KeyS") {           keys.s = false;         } else if (e.code == "KeyD") {           keys.d = false;         }       }       window.addEventListener("keydown", keyDown);       window.addEventListener("keyup", keyUp);        function animate() {         var speed = 0.05;         if (keys.w && !keys.s) {           position[0] += speed*Math.sin(rotate);           position[1] += speed*Math.cos(rotate);         }         if (!keys.w && keys.s) {           position[0] -= speed*Math.sin(rotate);           position[1] -= speed*Math.cos(rotate);         }         if (keys.a && !keys.d) {           rotate += speed;         }         if (!keys.a && keys.d) {           rotate -= speed;         }         if (position[0] > 2.3) { position[0] = 2.3 }         if (position[0] < -2.3) { position[0] = -2.3 }         if (position[1] > 4.8) { position[1] = 4.8 }         if (position[1] < -4.8) { position[1] = -4.8 }         camera.position.x = position[0];         camera.position.z = position[1];         camera.lookAt(position[0]+5*Math.sin(rotate), 0, position[1]+5*Math.cos(rotate));         requestAnimationFrame(animate);         renderer.render(scene, camera);       }       animate();     </script>    </body> </html> 

Заключение

Теперь вы знаете как легко создать 3д графику в браузере, даже если вы не хотели создавать игру. 3д графика может пригодиться в проектирование и еще много где. Также в данной библиотеке можно добавлять текстуры, 3д модели и прочее, можно еще сделать управление с помощью мыши и клавиатуры как в шутерах, например. Если вы хотите узнать как это сделать, я могу создать отдельные статьи про это если в голосовании будет много желающих, я сделаю такие статьи. В данной статье я показал лишь основы, чтобы вы знали с чего начать. Спасибо за внимание

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Хотите ли вы еще узнать что-топро 3д графику

66.67% Я хочу знать как установить текстуры на объекты16
66.67% Я хочу знать как загрузить 3д модели16
70.83% Я хочу знать как сделать управление с помощью мыши и клавиатуры17

Проголосовали 24 пользователя. Воздержались 22 пользователя.

ссылка на оригинал статьи https://habr.com/ru/articles/570666/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *