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)
  }
}

创建出来的人物长这样。

相关推荐
nyaomaru6 小时前
将一个真实的 TypeScript OSS 库从 tsup 迁移到 tsdown
前端·typescript
wflynn1 天前
GitHub 今日推荐|ts-rust:把微软 TypeScript-Go 编译器逐行移植成 Rust 实现
rust·typescript·开源·github·compiler·tsc
Duang007_1 天前
生产可观测性:从“系统慢“到“根因“的完整链路(Go / TypeScript)
后端·python·golang·typescript·prometheus
IllegalCreed2 天前
用 TypeScript 从零重写《仙剑奇侠传》:能通关的浏览器版,和一个给它做内容的可视化编辑器
typescript
_zxd2 天前
TypeScript 类型树
前端·typescript
Flynt2 天前
SvelteKit 3 升级实录:sv migrate 改完 6 个源文件,还给我留了张任务清单
typescript·前端框架·svelte
光影少年4 天前
Taro 是如何解析入口配置 app.config.ts 和页面配置的?
微信小程序·小程序·typescript·reactjs·百度小程序·taro
沧沧凉凉5 天前
一段需求、零素材,Claude Code 派了 33 个代理给我做了个 3D 动作游戏
游戏·ai编程·three.js
AI情绪识别开源5 天前
HFpEF 心房-心室耦联效率无创监测方向(AVCEI)
typescript·laravel·perl
凤城老人5 天前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron