最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 3D堆叠游戏——第一步 基础 初始化游戏

    正文概述 掘金(孙_华鹏)   2020-12-30   538

    应用技术栈

    webpack

    threejs

    typescript

    文件目录

    │  bash.exe.stackdump
    │  package-lock.json
    │  package.json
    │  README.md
    │  tsconfig.json
    │  webpack.config.js
    │  webpack.plugins.js
    │
    └─src
        ├─html
        │      index.html  // html
        │
        └─screen
                index.ts  // ts入口文件
    

    下面是主要的功能以及场景元素的选择

    3D堆叠游戏——第一步 基础 初始化游戏

    来自灵魂画师绘制的构图

    3D堆叠游戏——第一步 基础 初始化游戏

    首先创建场景以及其他必要元素

    一堆代码

    const THREE = require("three");
    import { OrbitControls } from "../../node_modules/three/examples/jsm/controls/OrbitControls";
    
    class CreateScene {
      // 屏幕宽度
      width: number = window.innerWidth;
      // 屏幕高度
      height: number = window.innerHeight;
      // 3d容器
      container: any = document.body;
      frustumSize = 2000;
      scene // 场景
      renderer  // 渲染器
      camera // 相机
      controls // 控制器 
      constructor() {
        this.createScene()
        this.createCamera()
        this.createRenderer()
        this.createControls()
        this.render()
        this.axesHelper(100)
        this.createBackground()
        // 监听屏幕尺寸变化
        window.addEventListener("resize", this.onWindowResized.bind(this), false);
      }
      // 创建场景
      createScene(): void {
        this.scene = new THREE.Scene();
      }
      // 创建渲染器
      createRenderer(): void {
        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setSize(this.width, this.height);
        document.body.appendChild(this.renderer.domElement);
      }
      // 创建相机
      createCamera(): void {
        this.camera = new THREE.OrthographicCamera(this.width / - 2, this.width / 2, this.height / 2, this.height / - 2, 1, this.frustumSize);
        this.camera.zoom = 3
        console.log(this.camera)
        this.camera.position.set(200, 250, 200)
        this.scene.add(this.camera);
        this.camera.updateProjectionMatrix()
      }
      // 创建控制器
      createControls(): void {
        this.controls = new OrbitControls(
          this.camera,
          this.renderer.domElement
        );
        this.controls.screenSpacePanning = true
        this.controls.target = new THREE.Vector3(0, 100, 0)
    
      }
      // 渲染动画
      animate(): void {
        requestAnimationFrame(this.render.bind(this));
      }
      // 渲染
      render(): void {
        this.animate()
        this.renderer.render(this.scene, this.camera);
        this.controls.update();
    
      }
      // 创建坐标轴辅助线
      axesHelper(len: number): void {
        const axesHelper = new THREE.AxesHelper(len);
        this.scene.add(axesHelper);
      }
      // 监听屏幕改变
      onWindowResized() {
        this.camera.left = this.width / - 2;
        this.camera.right = this.width / 2;
        this.camera.top = this.height / 2;
        this.camera.bottom = this.height / - 2;
        this.camera.updateProjectionMatrix();
        this.width = window.innerWidth
        this.height = window.innerHeight
        this.renderer.setSize(this.width, this.height);
      }
      // 创建天空背景
      createBackground(): any {
        const canvas = document.createElement('canvas');
        canvas.width = 1;
        canvas.height = 32;
    
        const context = canvas.getContext('2d');
        const gradient = context.createLinearGradient(0, 0, 0, 32);
        gradient.addColorStop(0.0, '#014a84');
        gradient.addColorStop(0.5, '#0561a0');
        gradient.addColorStop(1.0, '#437ab6');
        context.fillStyle = gradient;
        context.fillRect(0, 0, 1, 32);
    
        const sky = new THREE.Mesh(
          new THREE.SphereBufferGeometry(1000),
          new THREE.MeshBasicMaterial({ map: new THREE.CanvasTexture(canvas), side: THREE.BackSide })
        );
        this.scene.add(sky);
      }
    
    }
    export { CreateScene, THREE }
    

    然后在screen/index.ts 入口文件直接引用并实例化

    import {CreateScene,THREE} from '../createScene/index'
    const _this = new CreateScene()
    

    创建后的场景如下

    3D堆叠游戏——第一步 基础 初始化游戏

    创建主角

    initFloor() {
        const w: number = 30
        const h: number = 50
        const l: number = 30
        const floorParams = {
          w: w,
          h: h,
          l: l,
          x: w / 2,
          y: h / 2,
          z: l / 2
        }
        this.floorCube = createCube(floorParams)
        this.floorGroup.add(this.floorCube)
      }
    

    createCube 是封装的一个方法,主要功能创建方块,包括底板和主角

    // 创建方块时候需要的参数
    interface cubeParams {
      w: number // 宽度  对应X轴
      h: number // 高度  对应Y轴
      l: number // 长度  对应Z轴
      x: number // x轴位置
      y: number // y轴位置
      z: number // z轴位置
    }
    // 创建方块
    export function createCube(p: cubeParams): any {
      const geometry = new THREE.BoxGeometry(p.w, p.h, p.l);
      const material = new THREE.MeshNormalMaterial();
      const cube = new THREE.Mesh(geometry, material);
      cube.position.set(p.x, p.y, p.z)
      return cube
    }
    

    创建完成后

    3D堆叠游戏——第一步 基础 初始化游戏

    接下来需要创建主角(可移动方块)

    需要获取的信息为底板的高度,底板的顶点信息 底板的位置信息,过往主角都将视为底板内容,

    所以底板不直接添加到scene场景内,而是创建一个group

    可以通过封装好的getBox方法获取size

    封装好的getBox方法

    const THREE = require("three");
    function getBox(mesh: any) {
      let b = new THREE.Box3();
      b.expandByObject(mesh);
      return b
    
    }
    // 获取尺寸
    // 模型,vector3
    export function getSize(mesh: any, v3:any) {
      getBox(mesh).getSize(v3);
    }
    // 获取世界坐标
    export function getPosition(mesh:any, v3: any) {
      mesh.getWorldPosition(v3)
    }
    

    创建主角并设置位置信息

    3D堆叠游戏——第一步 基础 初始化游戏

    createlead() {
        const size = new THREE.Vector3()
        const mesh = this.floorGroup
        // 获取尺寸
        getSize(mesh, size)
        const position = new THREE.Vector3()
        // 获取底板的位置 默认应该都是0
        getPosition(mesh, position)
        const gy = position.y // 底板的Y值
        const y = size.y + gy + this.leadY / 2 // 主角的Y值
        // 设定第奇数个主角从z轴的负方向来,第偶数个主角从X轴方向来 
        // 需要一个主角计数器,同样可以用来计算分数
        // 起始点距离底板30
        // 主角初始位置
        const flag = this.leadCount % 2 === 0 // 是否是偶数主角
        // x 起始点
        let sx = (flag ? -this.startPoint : 0) + this.size / 2
        // z 起始点
        let sz = (flag ? 0 : -this.startPoint) + this.size / 2
        // 创建一个主角
        const leadParam = {
          w: this.size,
          h: this.leadY,
          l: this.size,
          x: sx,
          y: y,
          z: sz
        }
        const leadCube = createCube(leadParam)
        this.scene.add(leadCube)
        // 创建角色后计数器自增1
        this.leadCount++
      }
    

    多调用几次便可以从两侧创建主角

    3D堆叠游戏——第一步 基础 初始化游戏

    下面是initGame代码 又是一堆代码 汗!!!

    const THREE = require("three");
    import { createCube } from '../utils/tools'
    import { getSize, getPosition } from '../utils/getBox'
    class CreateGame {
      scene: any
      floorCube: any // 初始底板
      floorGroup: any // 底板组
      size: number = 30 // 主角宽度和长度
      leadY: number = 5 // 主角高度
      leadCount: number = 0 // 计数器
      startPoint: number = 60 // 主角起始位置 x或z
      leadInterval: any = null // 循环
      constructor(element: any) {
        this.scene = element.scene
        this.floorGroup = new THREE.Group()
        this.scene.add(this.floorGroup)
        this.initFloor()
      }
      initFloor() {
        const w: number = this.size
        const h: number = 50
        const l: number = this.size
        const floorParams = {
          w: w,
          h: h,
          l: l,
          x: w / 2,
          y: h / 2,
          z: l / 2
        }
        this.floorCube = createCube(floorParams)
        this.floorGroup.add(this.floorCube)
        this.floorGroup.updateMatrix()
      }
      createlead() {
        const size = new THREE.Vector3()
        const mesh = this.floorGroup
        // 获取尺寸
        getSize(mesh, size)
        const position = new THREE.Vector3()
        // 获取底板的位置 默认应该都是0
        getPosition(mesh, position)
        const gy = position.y // 底板的Y值
        const y = size.y + gy + this.leadY / 2 // 主角的Y值
        // 设定第奇数个主角从z轴的负方向来,第偶数个主角从X轴方向来 
        // 需要一个主角计数器,同样可以用来计算分数
        // 起始点距离底板30
        // 主角初始位置
        const flag:boolean = this.leadCount % 2 === 0 // 是否是偶数主角
        // x 起始点
        let sx:number = (flag ? -this.startPoint : 0) + this.size / 2
        // z 起始点
        let sz:number = (flag ? 0 : -this.startPoint) + this.size / 2
        // 创建一个主角
        const leadParam = {
          w: this.size,
          h: this.leadY,
          l: this.size,
          x: sx,
          y: y,
          z: sz
        }
        const leadCube = createCube(leadParam)
        this.floorGroup.add(leadCube)
        // 创建角色后计数器自增1
        this.leadCount++
      }
    }
    
    export { CreateGame }
    

    游戏共分为4个步骤来写文章

    第一步 基础 初始化游戏

    第二步 控制 控制主角移动以及停止

    第三步 切割 将主角切割为底板内部方块,底板外部方块 外部方块进行自由落体

    第四步 记分器、加载中等其他功能


    起源地下载网 » 3D堆叠游戏——第一步 基础 初始化游戏

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元