ThreeJS实现推箱子小游戏【一】

前言

最近一直在学ThreeJS,看到别人做出那么多炫酷的效果,觉得太厉害了,于是决定从一些简单的效果开始做。所以打算借这个小游戏来认真的来学习一下ThreeJS

正文

"推箱子" 游戏最早是由日本游戏开发者Hiroyuki Imabayashi于1982年开发和发布的。这款游戏的日本名为 "Sokoban"(倉庫番),意为 "仓库管理员"。"推箱子" 游戏的目标是在游戏区域内将箱子移动到指定的位置,通常通过推箱子来完成。游戏逻辑并不复杂,正好可以用来练练手。

初始化场景

游戏场景主要分为四个部分:场景底部面板、仓库边界、箱子、推箱子的人。

首先肯定是初始化场景,需要完成场景、相机、灯光、控制器的创建。场景、渲染器都是常规创建就行,相机的话因为我们游戏场景的范围是 10*10,所以相机需要稍微调整一下。

ts 复制代码
const fov = 60
    const aspect = this.sizes.width / this.sizes.height
    this.camera = new PerspectiveCamera(fov, aspect, 0.1)
    this.camera.position.copy(
      new Vector3(
        this.gridSize.x / 2 - 2,
        this.gridSize.x / 2 + 4.5,
        this.gridSize.y + 1.7
      )
    )

gridSize表示游戏场景的范围,暂时设置为 10*10 的网格,后面随着游戏关数不同,复杂度的变化,整体游戏范围肯定会越来越大。 灯光我们需要创建两个灯光,一个平行光,一个环境光,光的颜色都设置为白色就行,平行光需要添加一些阴影的参数。

ts 复制代码
const ambLight = new AmbientLight(0xffffff, 0.6)
const dirLight = new DirectionalLight(0xffffff, 0.7)

dirLight.position.set(20, 20, 20)
dirLight.target.position.set(this.gridSize.x / 2, 0, this.gridSize.y / 2)
dirLight.shadow.mapSize.set(1024, 1024)
dirLight.shadow.radius = 7
dirLight.shadow.blurSamples = 20
dirLight.shadow.camera.top = 30
dirLight.shadow.camera.bottom = -30
dirLight.shadow.camera.left = -30
dirLight.shadow.camera.right = 30

dirLight.castShadow = true

this.scene.add(ambLight, dirLight)

threeJs的场景初始完之后,接着需要创建游戏场景的底部平面。

游戏场景平面我们用PlaneGeometry来创建,接着将平面沿着x轴旋转90度,调整为水平方向,并且给平面添加网格辅助AxesHelper,方便我们在游戏移动的过程中找准位置。

ts 复制代码
  private createScenePlane() {
    const { x, y } = this.gridSize
    const planeGeometry = new PlaneGeometry(x * 50, y * 50)
    planeGeometry.rotateX(-Math.PI * 0.5)
    const planMaterial = new MeshStandardMaterial({ color: theme.groundColor })
    const plane = new Mesh(planeGeometry, planMaterial)
    plane.position.x = x / 2 - 0.5
    plane.position.z = y / 2 - 0.5
    plane.position.y = -0.5
    plane.receiveShadow = true
    this.scene.add(plane)
  }
  
  private createGridHelper() {
    const gridHelper = new GridHelper(
      this.gridSize.x,
      this.gridSize.y,
      0xffffff,
      0xffffff
    )
    gridHelper.position.set(
      this.gridSize.x / 2 - 0.5,
      -0.49,
      this.gridSize.y / 2 - 0.5
    )
    gridHelper.material.transparent = true
    gridHelper.material.opacity = 0.3
    this.scene.add(gridHelper)
  }

接着我们创建一个可以推动箱子的人物,我们用RoundedBoxGeometry 来创建身体,再创建两个SphereGeometry当做眼睛,最后再用RoundedBoxGeometry创建一个嘴巴,就简单的完成了一个任务。

ts 复制代码
export default class PlayerGraphic extends Graphic {
  constructor() {
    const NODE_GEOMETRY = new RoundedBoxGeometry(0.8, 0.8, 0.8, 5, 0.1)
    const NODE_MATERIAL = new MeshStandardMaterial({
      color: theme.player
    })
    const headMesh = new Mesh(NODE_GEOMETRY, NODE_MATERIAL)
    headMesh.name = PLAYER

    const leftEye = new Mesh(
      new SphereGeometry(0.16, 10, 10),
      new MeshStandardMaterial({
        color: 0xffffff
      })
    )
    leftEye.scale.z = 0.1
    leftEye.position.x = 0.2
    leftEye.position.y = 0.16
    leftEye.position.z = 0.46

    const leftEyeHole = new Mesh(
      new SphereGeometry(0.1, 100, 100),
      new MeshStandardMaterial({ color: 0x333333 })
    )

    leftEyeHole.position.z += 0.08
    leftEye.add(leftEyeHole)

    const rightEye = leftEye.clone()
    rightEye.position.x = -0.2

    const mouthMesh = new Mesh(
      new RoundedBoxGeometry(0.4, 0.15, 0.2, 5, 0.05),
      new MeshStandardMaterial({
        color: '#5f27cd'
      })
    )
    mouthMesh.position.x = 0.0
    mouthMesh.position.z = 0.4
    mouthMesh.position.y = -0.2

    headMesh.add(leftEye, rightEye, mouthMesh)
    headMesh.lookAt(headMesh.position.clone().add(new Vector3(0, 0, 1)))

    super(headMesh)
  }
}

创建出来的人物长这样。

相关推荐
fthux6 小时前
孩子的名字有救了
微信小程序·typescript·ai编程
常常不爱学习17 小时前
Vue3 + TypeScript学习
开发语言·css·学习·typescript·html
AAA不会前端开发2 天前
TypeScript核心类型系统完全指南
前端·typescript
sen_shan2 天前
Vue3+Vite+TypeScript+Element Plus开发-27.表格页码自定义
前端·javascript·typescript
冴羽2 天前
这是一个很酷的金属球,点击它会产生涟漪……
前端·javascript·three.js
烛阴2 天前
为什么 `Promise.then` 总比 `setTimeout(..., 0)` 快?微任务的秘密
前端·javascript·typescript
胖虎2653 天前
Three.js 工业 3D 可视化:生产线状态监控系统实现方案
three.js
披萨心肠5 天前
Typescript数组与元组类型
typescript·编程语言
一点七加一5 天前
Harmony鸿蒙开发0基础入门到精通Day11--TypeScript篇
前端·javascript·typescript
BLOOM5 天前
一款注解驱动的axios工具
javascript·typescript