세 가지를 어떻게 사용하는지.js 3차원 상자 밀기 게임 만들기

오늘 곽 선생은 모두가 내가 보낸 스리를 더 즐겨 보는 것을 발견하였다.js 작은 작품, 오늘 나는 3d 버전의 상자를 밀어내는 게임을 보냈는데, 사실 웹 GL은 많은 프레임워크가 있다.three.js는 게임 엔진으로 적합하지 않지만, 작은 게임을 시도할 수 있습니다.온라인 사례: 클릭
상자 밀기 게임을 만들려면 정상적으로 다음과 같은 4단계가 있어야 한다
  • 일부 수조를 정의하려면 시작 상자 수조, 끝 상자 수조, 지면 수조와 벽면 수조가 있어야 한다. 이 네 개의 수조가 있으면 하나의 관문을 구성할 수 있다.
  • 수조에 따라 지면 벽면 상자와 목표 지점 표지물을 초기화한다.
  • FirstPerson Controls 컨트롤러를 사용하여 카메라의 이동을 제어하고 지면 상자와 벽면에 따라 이동 가능 구역을 계산한다.
  • 카메라가 상자를 맞추고 있을 때 마우스로 상자를 눌러 상자의 이동을 제어하고 성공성 검사를 한다.
  • 다음은 코드 분석 코드입니다.
    1. 배열 정의
    이 네 개의 수조는 각각 벽의 수조, 지면의 수조, 상자의 초기 위치 수조와 목표 수조이다.
    
    wallArr = [[0, 0], [1, 0], [2, 0], [3, 0], [3, 1], [4, 1], [4, 2], [4, 3], [5, 3], [5, 4], [5, 5], [5, 6], [4, 6], [3, 6], [2, 6], [1, 6], [0, 6], [0, 5], [0, 4], [0, 3], [0, 2], [0, 1]]
    scopeArr = [[1, 1], [2, 1], [1, 2], [2, 2], [3, 2], [1, 3], [2, 3], [1, 4], [4, 4], [1, 5], [2, 5], [3, 5], [4, 5]];
    boxArr = [[3, 3], [2, 4], [3, 4]];
    targetArr = [[2, 2], [1, 3], [2, 3]]; 
    2. 상자의 초기 위치 수조에 따라 상자를 초기화
    
    initBox() {
      var textureBox = new THREE.TextureLoader().load("/static/images/base/crate.png");
      if (boxGroup) {
        scene.remove(boxGroup)
      }
      boxGroup = new THREE.Group();
      boxGroup.name = 'box_group'
      boxArr.forEach(d => {
        var boxGeom = new THREE.BoxGeometry(40, 40, 40);
        var boxMate = [];
        boxGeom.faces.forEach(d => boxMate.push(new THREE.MeshBasicMaterial({ map: textureBox })))
        var boxMesh = new THREE.Mesh(boxGeom, boxMate);
        boxMesh.position.set(d[0] * 40 - 20, 20, d[1] * 40 - 20);
        boxMesh.name = 'box';
        boxGroup.add(boxMesh);
      })
      scene.add(boxGroup);
      // 
      this.isWinner(boxArr, targetArr)
    }
    3. 지면 수조에 따라 지면 초기화
    
    initGround() {
      var textureGround = new THREE.TextureLoader().load("/static/images/wall/plaster.jpg", () => {this.loaded_num --});
      var textureGroundNormal = new THREE.TextureLoader().load("/static/images/wall/plaster-normal.jpg", () => {this.loaded_num --});
      var textureGroundSpecular = new THREE.TextureLoader().load("/static/images/wall/plaster-diffuse.jpg", () => {this.loaded_num --});
      textureGround.wrapS = textureGround.wrapT = THREE.RepeatWrapping;
      textureGround.repeat.set(50, 50);
      textureGroundNormal.wrapS = textureGroundNormal.wrapT = THREE.RepeatWrapping;
      textureGroundNormal.repeat.set(50, 50);
      var materialGround = new THREE.MeshPhongMaterial({
        map: textureGround
      })
      materialGround.normalMap = textureGroundNormal;
      materialGround.specularMap = textureGroundSpecular;
      var ground = new THREE.Mesh(new THREE.PlaneGeometry(1000, 1000, 1, 1), materialGround);
      ground.rotation.x = - Math.PI / 2;
      scene.add(ground);
    }
    4. 벽 수조에 따라 지면 초기화
    
    initWall() {
      var normal = new THREE.TextureLoader().load("/static/images/wall/stone.jpg", () => {this.loaded_num --});
      var bump = new THREE.TextureLoader().load("/static/images/wall/stone-bump.jpg", () => {this.loaded_num --});
      wallArr.forEach(d => {
        var wallBox = new THREE.BoxGeometry(40, 40, 40);
        var material = new THREE.MeshPhongMaterial({
          map: normal,
          bumpMap: bump,
          bumpScale: 1
        })
        var wall = new THREE.Mesh(wallBox, material);
        wall.position.x = d[0] * 40 - 20;
        wall.position.y = 20;
        wall.position.z = d[1] * 40 - 20;
        scene.add(wall);
      })
    }
    5. 목표 수조에 따라 목표물 초기화
    
    initTarget() {
      let objLoader = new OBJLoader();
      objLoader.setPath("/static/images/texture/hongqi/");
      objLoader.load('hongqi.obj', (object) => {
        this.loaded_num --;
        let hongqi = object.children[0];
        targetArr.forEach(d => {
          hongqi.position.set(d[0] * 40 - 20, -50, d[1] * 40 - 20)
          hongqi.scale.set(0.12, 0.12, 0.12)
          hongqi.material = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide });
          scene.add(hongqi.clone())
        })
      })
    }
    6. 상자의 클릭 이벤트 감청
    클릭할 때마다 computeMove 방법을 실행하여 이동할 수 있는지 여부를 판단합니다.
    
    initEventListener() {
      raycaster = new THREE.Raycaster();
      document.addEventListener('mousemove', function (event) {
        event.preventDefault();
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
      }, false)
      document.addEventListener('click', () => {
        if (scene.children && scene.getObjectByName('box')) {
          raycaster.setFromCamera(mouse, camera);
          let intersects = raycaster.intersectObjects(scene.getObjectByName('box_group').children);
          if (intersects[0] && intersects[0].object.name == 'box') {
            this.computeMove(intersects[0].object, camera.position);
          }
        }
      })
    }
    7. 감청 게임 성공
    만약 성공한다면, 간단한 팝업 알림.
    
    isWinner(arr1, arr2) {
      let boo = true; //true 
      arr1.forEach(d => {
        let res = arr2.some(dd => {
          return d[0] == dd[0] && d[1] == dd[1]
        })
        if(!res) {
          boo = false;
        }
      })
      if(boo) {
        setTimeout(() => {
          alert(' !')
        },100)
      }
    }
    당시에 이 작은 사례를 만들었을 때는 아직 풋내기였기 때문에three를 거의 사용하지 않았다.js의 보조 방법, 웃음이 난다.
    이상은 세 가지를 어떻게 사용하는지입니다.js는 3차원 트렁크 게임의 상세한 내용을 제작하고three에 대해 더 많이 설명합니다.js 상자 밀기 게임 자료 만들기

    좋은 웹페이지 즐겨찾기