나만보는개발공부블로그

Three.js를 이용해 간단한 FPS 게임 만들어보기-1 본문

Three.js

Three.js를 이용해 간단한 FPS 게임 만들어보기-1

alexrider94 2021. 9. 24. 16:39

[Three.js를 배우고자 하게 된 동기]

웹브라우저에서 3d 애니메이션이나 그래픽스를 웹페이지에 표현하여서 더욱 멋진 웹사이트를 만들어낼수 있고 다양한 게임들을 웹페이지에서 바로 즐겨볼 수 있는 Javscript 3d library가 있어서 한번 배워보고자 간단하게 FPS형식의 총쏘는 단계까지의 실습과정을 블로그에 담아볼려고합니다.

 

먼저 Three.js 공식 홈페이지에 들어가게 되면 three.js를 이용한 다양한 웹프로젝트들을 확인할 수 있는데 정말 혁신적인 웹페이지들을 많이 볼 수 있엇고 나도 three.js를 활용해 웹페이지를 개발하고자 하면 더욱 멋진 웹개발자가 될 수 있을까하는 마음이 생길겁니다 ^^

 

급하게 배우고자 하는 마음으로 코드의 정리는 제대로 되지 않았지만 어떤식으로 흘러가는지 단계별로 게임을 만들어볼 까 합니다.

 

https://threejs.org/

 

Three.js – JavaScript 3D Library

 

threejs.org

 

[실습을 위한 개발 실행환경 세팅하기]

저는 vscode 환경에서 webpack-dev를 이용해 개발을 진행하였습니다.

 

터미널을 열어주고 원하는 저장소에 파일을 하나 생성해줍시다.

mkdir threejs-fps

npm init을 통해 package.json을 하나 생성해주고 src파일을 하나 만들어줍니다.

그리고 필요한 패키지를 다운받습니다.

 

필요한 패키지는 다음과 같습니다.

webpack

webpack-cli

wepback-dev-server

webpack-merge

html-loader

html-webpack-plugin

file-loader

@babel/core

babel-loader

three

 

아래와 같이 패키지들을 설치해줍시다.

npm install --save webpack webpack-cli webpack-dev-server webpack-merge file-loader three html-webpack-plugin @babel/core babel-loader html-loader

 

webpack 설정을 위한 프로젝트 최상단에 bundler라는 폴더를 생성해줍시다.

그리고 bundler폴더안에 webpack.common.js와 webpack.dev.js를 파일을 만들어줍시다.

필요 패키지에 대한 설명은 webpack은 개인적으로 공부해보면서 알아보는것이 좋고 일단 webpack을 통해서 모듈들을 처리하고 webpack-cli는 말그대로 webpack-cli 환경을 위한 것이고 webpack-dev-server은 개발 서버를 생성해주기 위한 것이고 webpack-merge는 여러 webpack 파일을 통합하기 위한 것입니다. 그래서 webpack.dev.js에서 설정을 통해서 나만의 개발환경이 서버로 생성되는것입니다. 

three.js에서 3d 그래픽을 사용할려면 보통은 gltf형식의 3d 이미지를 가져와서 사용하게 되는데 webpack에서 이걸 모듈로 처리해서 쉽게 표현할 수 있게 해줄 수 있는걸로 알고 있습니다. file-loader가 방금의 역할을 하게 되고 babel-loader는 webpack과 바벨을 연동시켜주고 바벨은 js의 여러 버전의 문법에서 사용할 수 있게 컴파일해주는것입니다.

그리고 가장 중요한 three 라이브러리를 통해서 3d환경의 웹개발을 할 수 있게 됩니다.

 

이제 라이브러리들에 대한 설명은 완벽하진 못해도 설명이 끝낫고 각자 부족한점들을 인터넷 구글링을 통해서 알아보도록 합시다.

 

먼저 webpack-dev-server 환경을 만들기 위해서 webpack.common.js 내용부터 생성해봅시다.

 

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
  entry: { index: path.resolve(__dirname, '../src/index.js') },
  output: {
    filename: 'bundle.[contenthash].js',
    path: path.resolve(__dirname, '../dist'),
  },
  devtool: 'source-map',
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../src/index.html'),
      minify: true,
    }),
  ],
  module: {
    rules: [
      // HTML
      {
        test: /\.(html)$/,
        use: ['html-loader'],
      },
      // JS
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: ['babel-loader'],
      },
      // Models
      {
        test: /\.(glb|gltf)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              outputPath: 'assets/',
            },
          },
        ],
      },
    ],
  },
};

위의 파일 설정을 webpack.common.js 입니다.

entry point는 우리가 webpack실행시의 진입 시작점이고 프로젝트 최상단위 src파일내의 index.js를 시작점으로 index.js가 가장 먼저 실행되도록 합니다.

output은 번들러가 끝난후의 파일생성단계인데 일단은 개발과정만 진행하기때문에 넘어갑시다. 그리고 plugin과, module들을 위와 같이 설정해줍니다.

보면은 3d model을 위해 glb, gltf를 처리하기 위해 file-loader을 사용한것을 볼 수 있습니다.

 

그다음에는 webpack.dev.js 파일을 다음과 같이 작성합니다.

const { merge } = require('webpack-merge');
const commonConfiguration = require('./webpack.common.js');

module.exports = merge(commonConfiguration, {
  mode: 'development',
  devServer: {
    port: 8080,
    open: true,
    hot: true,
    https: false,
  },
});

마지막으로 package.json에서  scripts 안에 dev를 추가해줍시다.

  "dev": "webpack serve --config ./bundler/webpack.dev.js"

그러면 일단은 실행환경은 끝낫습니다.

 

이제 한번 three.js로 검은화면단을 만들어봅시다.

 

src파일내부안에 index.html과 index.js를 생성해줍시다.

 

index.html은 canvas 태그를 통해서 index.js안에서 돔 엘리먼트를 건들여서 three.js를 입힐것입니다.

일단 index.html을 다음과 같이 작성합시다.

 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Threejs-FPS</title>
</head>

<body>
  <canvas class='app'></canvas>
</body>

</html>

 

그리고 index.js를 작성합시다.

 

import * as THREE from 'three';

class Game {
  $canvas = document.querySelector('.app');
  _scene = new THREE.Scene();
  _size = {
    width: window.innerWidth,
    height: window.innerHeight,
  };
  constructor() {
    this.setUpThreeComponents();
  }

  setUpThreeComponents = () => {
    this._camera = new THREE.PerspectiveCamera(75, this._size.width / this._size.height, 0.1, 1000);

    //set up camera
    this._scene.add(this._camera);

    //set up light
    const light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(0, 0, 500);
    this._scene.add(light);

    //set up renderer
    this._renderer = new THREE.WebGLRenderer({
      canvas: this.$canvas,
      antialias: true,
    });

    this._renderer.setSize(this._size.width, this._size.height);
    this._renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  };
}

new Game();

위의 코드를 간단하게 설명하자면 game이라는 클래스를 만들어주고 three.js를 import해서 three 함수들을 사용하고 있습니다. queryselector을 통해 canvas class name값을 가져와 저장시켜주고 constructor()를 통해서 기본 three 화면단을 생성해주고 있습니다.

 

일단은 파일을 그대로 저장하고 실행해보면 다음과 같이 완성될것입니다..

 

 

검은화면이 생성된거면 일단은 개발환경은 완료입니다.

다음 단계에 한번 어떤식으로 three.js가 동작하는지 그리고 scene이나 camera 이런것들이 뭔지 알아봅시다.