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


主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, greenwillow, v-green, vue-pro, healer-readable, mk-cute, jzman, geek-black, awesome-green

贡献主题:https://github.com/xitu/juejin-markdown-themes

theme: juejin

highlight:

应用技术栈

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入口文件

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

来自灵魂画师绘制的构图

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

一堆代码

``` typescript 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 入口文件直接引用并实例化

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

创建后的场景如下

第二步 创建底座以及第一个可以移动的主角

创建主角

typescript 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 是封装的一个方法,主要功能创建方块,包括底板和主角

typescript // 创建方块时候需要的参数 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 }

创建完成后

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

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

所以底板不直接添加到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) } ```

创建主角并设置位置信息

typescript 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++ }

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

下面是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个步骤来写文章

第一步 基础 初始化游戏

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙华鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值