近期在尝试着学习写一些3D小游戏,分享一下成绩。
严格上说还算不上残缺的游戏,感兴趣的敌人能够观摩一下。
  • 预览地址:https://luosijie.github.io/ga...
  • git仓库:https://github.com/luosijie/g...
  • 语言:TypeScript
  • 框架:Babylon

筹备

在这里用到的惟一素材:小飞机

是在 Blender 软件了外面简略设计的

Blender 是一个收费开源的建模软件

如果感兴趣,这里举荐B站上的一个 入门教程

上面是我的一些步骤

  1. 应用简略的几何元素构建出飞机模型
  2. 制作2个小动画:螺旋桨旋转机身摇摆
  3. 导出 .glb 格局模型

模型导入到 Babylon 的代码如下

次要用到2个参数 meshesanimationGroups

{    animationGroups: (2) [AnimationGroup, AnimationGroup]    geometries: (9) [Geometry, Geometry, Geometry, Geometry, Geometry]    lights: []    meshes: (10) [Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh]    particleSystems: []    skeletons: []    transformNodes: (5) [TransformNode, TransformNode, TransformNode]    __proto__: Object

代码

在这个我的项目次要实现一下几个环节

  1. 根本场景的搭建
  2. 飞机追随鼠标的静止
  3. 粒子的生成和静止
  4. 飞机与粒子的碰撞

飞机模型的加载

    // 加载飞机模型    private async loadPlane(): Promise<any> {        // 新建一个通明元素 包裹模型        const container = MeshBuilder.CreateBox('plane-container', { width: 1, depth: 2, height:1 }, this.scene)        container.isVisible = false;        // 调整到与模型重合的地位        container.bakeTransformIntoVertices(Matrix.Translation(0, 1.2, 0.8))        container.rotation.y = -Math.PI / 2        container.position.x = 0.6        // 加载飞机模型        const glb = await SceneLoader.ImportMeshAsync(null, './public/', 'plane.glb', this.scene)        const root = glb.meshes[0]        console.log('glb', glb)        // 绑定父子关系        root.parent = container        return {            mesh: container,            fly: () => {                glb.animationGroups[0].play(true)                glb.animationGroups[1].play(true)            },            stop: () => {                glb.animationGroups[0].stop(),                glb.animationGroups[1].stop()            }        }    }

飞机模型的静止追随

  1. 鼠标挪动时获取 鼠标坐标飞机 坐标
  2. 飞机坐标 须要 3维坐标屏幕坐标 的转化
  3. 飞机坐标鼠标坐标 挪动
...    // 获取鼠标坐标存储    this.scene.onPointerObservable.add(info => {        const { event } = info        // 存储鼠标坐标数据        if (event.type === 'pointermove') {            this.pointerPos = {                x: event.x,                y: event.y            }        }    }).../** Loop中更新plane坐标 */private updatePlane(): void {    // 设置平滑系数-一直尝试失去到数值    const smoothing = 2000    // 获取plane屏幕坐标    const originPos = this.WorldToScreen(this.plane.mesh.position)    if (this.pointerPos.x && this.pointerPos.y) {        // 计算鼠标地位 和 plane 地位得间隔        const deltaX = (this.pointerPos.x - originPos.x) / smoothing        const deltaY = (this.pointerPos.y - originPos.y) / smoothing        // plane 朝鼠标的方向挪动        this.plane.mesh.position.x += deltaX        this.plane.mesh.position.y -= deltaY    }}

生成粒子

/**  * 生成粒子数据 * 每个间隔时间生成粒子:并插入到 particles 中 */private initParticles(): void {    // 限度 scene 最多的粒子为90    const LIMIT = 90    this.particles = []    setInterval(() => {        if (this.particles.length > LIMIT || this.state !== State.GAME) return        // 创立粒子        const particle = this.createParticle()        // 随机搁置粒子        particle.position.x = 20 + Math.random() * 20        particle.position.y = -10 + Math.random() * 20        particle.position.z = 0        // 粒子插入 particles 中:不便前面更新操作        this.particles.push(particle)    }, 300)}

更新粒子静止 并检测 是否与飞机碰撞

/** Loop中更新plane坐标 */private updatePlane(): void {    // 设置平滑系数-一直尝试失去到数值    const smoothing = 2000    // 获取plane屏幕坐标    const originPos = this.WorldToScreen(this.plane.mesh.position)    if (this.pointerPos.x && this.pointerPos.y) {        // 计算鼠标地位 和 plane 地位得间隔        const deltaX = (this.pointerPos.x - originPos.x) / smoothing        const deltaY = (this.pointerPos.y - originPos.y) / smoothing        // plane 朝鼠标的方向挪动        this.plane.mesh.position.x += deltaX        this.plane.mesh.position.y -= deltaY    }}

其余

我的项目的次要流程就是这些了

还有其余的一些,比方:

  • 场景的搭建
  • 相机的解决
  • 灯光的解决
  • 游戏状态的解决

欢送到GitHub查看残缺代码

谢谢浏览

喜爱的话,点赞 star 反对