用Three.js写3D跑酷微信小游戏[2]-创建舞台和游戏主角

游戏元素

舞台是游戏开发中的一个术语,意思是用来显示游戏元素的平台,所有的游戏元素只有添加到舞台,才能够显示到用户的界面。以这个音乐跑酷小游戏为例,我们需要实现的有哪些元素呢?归纳起来,主要元素有:

  • 菜单按钮
  • 主角
  • NPC
  • 赛道
  • 计时分数
  • 音乐动画帧

创建舞台场景

我们先不管这些游戏元素该怎么实现的,目前我们的任务是,先实现一个舞台。Three.js 实现一个舞台非常简单:

1
const scene = new THREE.Scene();

但这仅仅只是一个舞台场景而已,在 3D 世界中,我们还需要一台摄影机(相当于用户的眼睛),摄影机的摆放位置(坐标),决定了屏幕呈现元素的角度:

创建摄影机

创建一台摄影机:

1
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 4000);

PerspectiveCamera是透视摄影机类,继承于THREE.Camera类,用这种模式的摄影机,在 3D 世界中,图像会是近大远小的情况。该类分别接受 4 个参数fov(field of view,视野大小), aspect(视窗宽高比), near(距离摄影机最近的位置,最小值为 0.1),far(距离摄影机最远的位置)。

near 和 far 决定了成像的空间范围,far 一般不宜过大,否则会造成性能渲染问题。

还有其他模式的摄影机:

  • CubeCamera
  • OrthographicCamera
  • StereoCamera

这里不作介绍了,感兴趣可以查看:https://threejs.org/docs/index.html#api/zh/cameras/Camera

创建渲染器

有了舞台场景,摄影机了,但是还缺少一个东西:WebGL 渲染器。创建WebGL渲染器

1
2
3
4
5
6
7
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
alpha: true,
antialias: true,
});
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(RATIO);

这里设置了 3 个参数,作用分别是:

  • canvas指定渲染到哪个 canvas,如果没有指定,则会创建一个新的 canvas。这里因为微信小游戏默认创建了主屏 canvas,并暴露到全局环境中,所以设置值为canvas即可。
  • alpha是声明 canvas 是否需要透明度,这个游戏需要有透明度,所以为true
  • antialias则是表示是否需要执行抗锯齿。

为了兼容 Retina 屏幕,我们需要设置 dpr 值为devicePixelRatio

最后调用render方法,把舞台和摄影机都加入渲染器:

1
renderer.render(scene, camera);

创建主角

舞台,摄影机,WebGL 渲染器都具备了,但是如果没有主角的话,我们看到的将是漆黑一片,所以我们还需要创建一个主角,在这个小游戏中,我们的主角非常简单,就是一个 3D 几何体:

1
const boxGeometry = new THREE.BoxGeometry(8, 8, 8);

BoxGeometry是立方几何体模型,分别接受宽(width)、高(height),深(depth)3 个参数。

同时还需要创建材质:boxMaterial,相当于模型的皮:

1
2
3
4
5
const boxMaterial = new THREE.MeshBasicMaterial({
color: 0xe67e22,
transparent: true,
opacity: 0.75,
});

最后创建立方几何体网格:Mesh,并确定位置:

1
const box = new THREE.Mesh(boxGeometry, boxMaterial);

然后把 box 元素添加到舞台scene

1
scene.add(box);

主角虽然创建了,但是我们并没有设置camera的位置,因此摄影机和主角都处在 3D 坐标系的原点(0, 0, 0),所以还需要我们完成最后一步,把camera移动到合适的位置。

移动 camera 到合适的位置(坐标)

移动 camera 之前,我们需要认识什么是 3D 坐标系(图转),3D 坐标系遵循右手坐标系:

3D 世界的中心坐标为(0, 0, 0),即xyz值分别都为0

移动 camera 的位置:

1
2
// 移动到x坐标为0,y坐标为30,z坐标为60的位置
camera.position.set(0, 30, 60);

这时候,我们就可以看到舞台上有个橘黄色的立方体:

可能你已经注意到了,舞台上出现了红、绿、蓝的线条,没错,他们分别代表xyz轴,这些线条就是辅助坐标系,对于调试元素的位置坐标非常有用,它是 Three.js 提供的AxesHelper。创建辅助坐标系:

1
2
// 10000代表辅助线的长度
const axesHelper = new THREE.AxesHelper(10000);

总结

最后我们需要把一些数值参数提取到constant.ts常量文件,后续方便我们调整游戏的参数,调整之后的代码结构是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
./src
├── Game
│ ├── Player // 游戏主角
│ │ └── index.ts
│ ├── camera // 摄影机
│ │ └── index.ts
│ ├── constant.ts // 常量
│ ├── helper
│ │ └── axes.ts // 辅助坐标系
│ ├── index.ts
│ ├── renderer // WebGL渲染器
│ │ └── index.ts
│ └── scene // 舞台场景
│ └── index.ts
├── index.ts // 入口
└── lib
└── weapp-adapter.js // 模拟BOM,DOM

代码::https://github.com/inarol/rungame/tree/section1

[本文谢绝转载,谢谢]

粤ICP备2022084378号