Threejs系列--22游戏开发--沙漠赛车游戏【布置游戏开始场景】

Threejs系列--22游戏开发--沙漠赛车游戏【布置游戏开始场景】,第1张

Threejs系列--22游戏开发--沙漠赛车游戏【布置游戏开始场景】 序言目录结构代码一览index.js代码Objects.js代码Materials.js代码materials/FloorShadow.js代码materials/Matcap.js代码 代码解读运行结果

序言

本章将进行游戏开始场景的处理,场景中模型较多,需要统一管理

目录结构

资源目录里面的结构不变,点击传送门快速查看。

|__src
	|__assets
	|__js
	|	|__base		基础类文件夹
	|		|__Camera.js 相机类	
	|		|__Resources.js 构建模型的资源类 
	|	|__geometries	定制的物体类文件夹
	|		|__AreaFenceBufferGeometry.js 栏栅模型
	|		|__AreaFloorBorderBufferGeometry.js 进度条几何体  
	|	|__materials	材质类文件夹
	|		|__Floor.js 地面材质	
	|		|__AreaFence.js	【新增--开始按钮的栏栅材质】
	|		|__AreaFloorBorder.js 进度条着色器 
	|		|__FloorShadow.js 
	|		|__Matcap.js 
	|	|__passes	合成器通道文件夹
	|		|__Blur.js	  模糊着色器
	|		|__Glows.js		发光着色器
	|	|__utils	工具类文件夹
	|		|__Sizes.js  画布大小控制类
	|		|__EventEmitter.js 基础事件处理器
	|		|__Time.js  动画刷新 
	|		|__Loader.js 加载器 
	|	|__world	精灵类文件夹
	|		|__sections
	|			|__IntroSection.js 开始场景模型 【新增】
	|		|__Area.js	区域基础类  
	|		|__Areas.js	区域管理类  
	|		|__index.js	精灵类
	|		|__Floor.js 地面类
	|		|__Materials.js 材质类 【新增】
	|		|__Objects.js 模型管理类 【新增】
	|		|__Sounds.js 音乐加载类	
	|	|__Application.js	初始化游戏的文件 
	|__index.js		入口
	|__index.css  	小项目,样式一丢丢
代码一览 index.js代码
...
import Objects from "./Objects.js";
import Materials from "./Materials.js";
import IntroSection from "./sections/IntroSection.js";

export default class {
    ...

    start() {
    	//准备场景与游戏主场景的过渡动画
    	this.setReveal();
        //场景中材质处理
        this.setMaterials();
        //场景中模型管理
        this.setObjects();
        //开始场景中各个模型加载
        this.setSections();
    }

    setStartingScreen() {
        ...
        
        this.startingScreen.area.on('interact', () => {
            ...
        
            this.start(); //点击开始按钮后,开始布置游戏场景
			
			//主场景展示动画
			window.setTimeout(() => {
                this.reveal.go();
            }, 600);
        })
    }
    
	setReveal(){
        this.reveal = {};

        this.reveal.matcapsProgress = 0;
        this.reveal.previousMatcapsProgress = null;

        this.reveal.go = () => {
            gsap.fromTo(
              this.reveal,
              { matcapsProgress: 0 },
              { matcapsProgress: 1, duration: 3 }
            );
        }

        this.time.on("tick", () => {
            if (this.reveal.matcapsProgress !== this.reveal.previousMatcapsProgress) {
              for (const _materialKey in this.materials.shades.items) {
                const material = this.materials.shades.items[_materialKey];
                material.uniforms.uRevealProgress.value = this.reveal.matcapsProgress;
              }
            }
        });
    }

    setMaterials(){
        this.materials = new Materials({
            time: this.time,
            resources: this.resources
        });
    }

    setObjects(){
        this.objects = new Objects({
            materials: this.materials,
        });

        this.container.add(this.objects.container);
    }

    setSections(){
        this.sections = {};

        const options = {
            resources: this.resources,
            objects: this.objects,
        };
		
		//加载开始场景
        this.sections.intro = new IntroSection({
            ...options,
        });
        this.container.add(this.sections.intro.container);
    }
}

Objects.js代码
import * as THREE from "three";

export default class Objects {
    constructor(_options) {
        this.materials = _options.materials;

        this.container = new THREE.Object3D();
        this.container.matrixAutoUpdate = false;

        this.items = [];
        this.floorShadows = [];
        
        //设置模型的处理方式
        this.setParsers();
    }

    setParsers() {
        this.parsers = {};
    
        this.parsers.items = [
          {
            regex: /^shade([a-z]+)_?[0-9]{0,3}?/i,
            apply: (_mesh, _options) => {
              const match = _mesh.name.match(/^shade([a-z]+)_?[0-9]{0,3}?/i);
              const materialName = `${match[1]
                .substring(0, 1)
                .toLowerCase()}${match[1].substring(1)}`; 
              let material = this.materials.shades.items[materialName];
    
              if (typeof material === "undefined") {
                material = new THREE.MeshNormalMaterial();
              }
    
              const mesh = _options.duplicated ? _mesh.clone() : _mesh;
              mesh.material = material;
    
              if (mesh.children.length) {
                for (const _child of mesh.children) {
                  if (_child instanceof THREE.Mesh) {
                    _child.material = material;
                  }
                }
              }
    
              return mesh;
            },
          },
          {
            regex: /^floor_?[0-9]{0,3}?/i,
            apply: (_mesh, _options) => {
              const geometry = new THREE.PlaneBufferGeometry(
                _mesh.scale.x,
                _mesh.scale.y,
                10,
                10
              );
              const material = this.materials.items.floorShadow.clone();
    
              material.uniforms.tShadow.value = _options.floorShadowTexture;
              material.uniforms.uShadowColor.value = new THREE.Color(
                this.materials.items.floorShadow.shadowColor
              );
              material.uniforms.uAlpha.value = 0;
    
              const mesh = new THREE.Mesh(geometry, material);
              mesh.matrixAutoUpdate = false;
              mesh.updateMatrix();
    
              this.floorShadows.push(mesh);
    
              return mesh;
            },
          },
        ];
    
        this.parsers.default = {};
        this.parsers.default.apply = (_mesh) => {
          const mesh = _mesh.clone();
          mesh.material = this.materials.shades.items.white;
    
          return mesh;
        };
    }
	
	//合并模型
    getConvertedMesh(_children, _options = {}) {
        const container = new THREE.Object3D();
        const center = new THREE.Vector3();
    
        const baseChildren = [..._children];
    
        for (const _child of baseChildren) {
          if (_child.name.match(/^center_?[0-9]{0,3}?/i)) {
            center.set(_child.position.x, _child.position.y, _child.position.z);
          }
    
          if (_child instanceof THREE.Mesh) {
            let parser = this.parsers.items.find((_item) =>
              _child.name.match(_item.regex)
            );
            if (typeof parser === "undefined") {
              parser = this.parsers.default;
            }
    
            const mesh = parser.apply(_child, _options);
    
            container.add(mesh);
          }
        }
    
        if (center.length() > 0) {
          for (const _child of container.children) {
            _child.position.sub(center);
          }
    
          container.position.add(center);
        }
    
        if (_options.mass && _options.mass === 0) {
          container.matrixAutoUpdate = false;
          container.updateMatrix();
        }
    
        return container;
    }
	
	//添加模型
    add(_options) {
        const object = {};
    
        object.merged = false;
        object.shouldMerge = _options.mass === 0;
    
        const offset = new THREE.Vector3();
        if (_options.offset) {
          offset.copy(_options.offset);
        }
    
        const rotation = new THREE.Euler();
        if (_options.rotation) {
          rotation.copy(_options.rotation);
        }
    
        const sleep = typeof _options.sleep === "undefined" ? true : _options.sleep;
    
        object.container = this.getConvertedMesh(_options.base.children, _options);
        object.container.position.copy(offset);
        object.container.rotation.copy(rotation);
        this.container.add(object.container);
    
        if (_options.mass === 0) {
          object.container.matrixAutoUpdate = false;
          object.container.updateMatrix();
    
          for (const _child of object.container.children) {
            _child.matrixAutoUpdate = false;
            _child.updateMatrix();
          }
        }
    
        this.items.push(object);
    
        return object;
    }
}
Materials.js代码
import * as THREE from "three";
import FloorShadowMaterial from "../materials/FloorShadow.js";
import MatcapMaterial from "../materials/Matcap.js";

export default class Materials {
  constructor(_options) {
    this.resources = _options.resources;

    this.items = {};

    this.setShades();
    this.setFloorShadow();
  }
  
  setShades() {
    this.shades = {};
    this.shades.items = {};
    this.shades.indirectColor = "#d04500";

    this.shades.uniforms = {
      uRevealProgress: 0,
      uIndirectDistanceAmplitude: 1.75,
      uIndirectDistanceStrength: 0.5,
      uIndirectDistancePower: 2.0,
      uIndirectAngleStrength: 1.5,
      uIndirectAngleOffset: 0.6,
      uIndirectAnglePower: 1.0,
      uIndirectColor: null,
    };

    // White
    this.shades.items.white = new MatcapMaterial();
    this.shades.items.white.name = "shadeWhite";
    this.shades.items.white.uniforms.matcap.value =
      this.resources.items.matcapWhiteTexture;
    this.items.white = this.shades.items.white;

    // Orange
    this.shades.items.orange = new MatcapMaterial();
    this.shades.items.orange.name = "shadeOrange";
    this.shades.items.orange.uniforms.matcap.value =
      this.resources.items.matcapOrangeTexture;
    this.items.orange = this.shades.items.orange;

    // Green
    this.shades.items.green = new MatcapMaterial();
    this.shades.items.green.name = "shadeGreen";
    this.shades.items.green.uniforms.matcap.value =
      this.resources.items.matcapGreenTexture;
    this.items.green = this.shades.items.green;

    // Brown
    this.shades.items.brown = new MatcapMaterial();
    this.shades.items.brown.name = "shadeBrown";
    this.shades.items.brown.uniforms.matcap.value =
      this.resources.items.matcapBrownTexture;
    this.items.brown = this.shades.items.brown;

    // Gray
    this.shades.items.gray = new MatcapMaterial();
    this.shades.items.gray.name = "shadeGray";
    this.shades.items.gray.uniforms.matcap.value =
      this.resources.items.matcapGrayTexture;
    this.items.gray = this.shades.items.gray;

    // Beige
    this.shades.items.beige = new MatcapMaterial();
    this.shades.items.beige.name = "shadeBeige";
    this.shades.items.beige.uniforms.matcap.value =
      this.resources.items.matcapBeigeTexture;
    this.items.beige = this.shades.items.beige;

    // Red
    this.shades.items.red = new MatcapMaterial();
    this.shades.items.red.name = "shadeRed";
    this.shades.items.red.uniforms.matcap.value =
      this.resources.items.matcapRedTexture;
    this.items.red = this.shades.items.red;

    // Black
    this.shades.items.black = new MatcapMaterial();
    this.shades.items.black.name = "shadeBlack";
    this.shades.items.black.uniforms.matcap.value =
      this.resources.items.matcapBlackTexture;
    this.items.black = this.shades.items.black;

    // Green emerald
    this.shades.items.emeraldGreen = new MatcapMaterial();
    this.shades.items.emeraldGreen.name = "shadeEmeraldGreen";
    this.shades.items.emeraldGreen.uniforms.matcap.value =
      this.resources.items.matcapEmeraldGreenTexture;
    this.items.emeraldGreen = this.shades.items.emeraldGreen;

    // Purple
    this.shades.items.purple = new MatcapMaterial();
    this.shades.items.purple.name = "shadePurple";
    this.shades.items.purple.uniforms.matcap.value =
      this.resources.items.matcapPurpleTexture;
    this.items.purple = this.shades.items.purple;

    // Blue
    this.shades.items.blue = new MatcapMaterial();
    this.shades.items.blue.name = "shadeBlue";
    this.shades.items.blue.uniforms.matcap.value =
      this.resources.items.matcapBlueTexture;
    this.items.blue = this.shades.items.blue;

    // Yellow
    this.shades.items.yellow = new MatcapMaterial();
    this.shades.items.yellow.name = "shadeYellow";
    this.shades.items.yellow.uniforms.matcap.value =
      this.resources.items.matcapYellowTexture;
    this.items.yellow = this.shades.items.yellow;

    // Metal
    this.shades.items.metal = new MatcapMaterial();
    this.shades.items.metal.name = "shadeMetal";
    this.shades.items.metal.uniforms.matcap.value =
      this.resources.items.matcapMetalTexture;
    this.items.metal = this.shades.items.metal;

	// 颜色处理
    this.shades.updateMaterials = () => {
      this.shades.uniforms.uIndirectColor = new THREE.Color(
        this.shades.indirectColor
      );

      for (const _uniformName in this.shades.uniforms) {
        const _uniformValue = this.shades.uniforms[_uniformName];

        for (const _materialKey in this.shades.items) {
          const material = this.shades.items[_materialKey];
          material.uniforms[_uniformName].value = _uniformValue;
        }
      }
    };

    this.shades.updateMaterials();

  }

  //预留
  setFloorShadow() {
    this.items.floorShadow = new FloorShadowMaterial();
  }
}
materials/FloorShadow.js代码
import * as THREE from "three";

import shaderFragment from "../../assets/shaders/floorShadow/fragment.glsl";
import shaderVertex from "../../assets/shaders/floorShadow/vertex.glsl";

export default function () {
  const uniforms = {
    tShadow: { value: null },
    uShadowColor: { value: null },
    uAlpha: { value: null },
  };

  const material = new THREE.ShaderMaterial({
    wireframe: false,
    transparent: true,
    uniforms,
    vertexShader: shaderVertex,
    fragmentShader: shaderFragment,
  });

  return material;
}

materials/Matcap.js代码
import * as THREE from "three";

import shaderFragment from "../../assets/shaders/matcap/fragment.glsl";
import shaderVertex from "../../assets/shaders/matcap/vertex.glsl";

export default function () {
  const uniforms = {
    ...THREE.UniformsLib.common,
    ...THREE.UniformsLib.bumpmap,
    ...THREE.UniformsLib.normalmap,
    ...THREE.UniformsLib.displacementmap,
    ...THREE.UniformsLib.fog,
    matcap: { value: null },
    uRevealProgress: { value: null },
    uIndirectDistanceAmplitude: { value: null },
    uIndirectDistanceStrength: { value: null },
    uIndirectDistancePower: { value: null },
    uIndirectAngleStrength: { value: null },
    uIndirectAngleOffset: { value: null },
    uIndirectAnglePower: { value: null },
    uIndirectColor: { value: null },
  };

  const extensions = {
    derivatives: false,
    fragDepth: false,
    drawBuffers: false,
    shaderTextureLOD: false,
  };

  const defines = {
    MATCAP: "",
  };

  const material = new THREE.ShaderMaterial({
    wireframe: false,
    transparent: false,
    uniforms,
    extensions,
    defines,
    lights: false,
    vertexShader: shaderVertex,
    fragmentShader: shaderFragment,
  });

  return material;
}

代码解读
index.js 中
	新增了 start()在用户点击开始按钮时触发,
	setMaterials() 对场景内基本材质做了统一处理,
	setObjects() 是对模型的统一管理,
	setSections()开始场景中各个模型加载。
	
Objects.js中对场景中模型进行了统一管理,包含添加 合并 对不同模型进行不同处理。

Materials.js中对场景模型进行了材质处理。
materials/FloorShadow.js与materials/Matcap.js分别是采用自定义的着色器材质。
运行结果

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/940246.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-17
下一篇 2022-05-17

发表评论

登录后才能评论

评论列表(0条)

保存