Threejs系列--9游戏开发--沙漠赛车游戏【基础场景渲染】
序言
开篇先来碎碎念,最近项目紧张,终于有时间写一篇了。本章将开始编程,为了方便初学者,先构建基础框架,预留代码位。后期开发过程中将逐步增加代码量以及项目中的某些依赖。
准备工作
emmmm,项目开始直接换react了,其实换不换对于这个项目来说几乎毫无影响,各位可根据个人情况而定。
不想换的小伙伴可以一直参考系列7,完全不会影响开发体验。
// 创建项目
> npx create-react-app react-racing-game
// 打开配置 要配置模型等资源的解析
> npm run eject
// 下载threejs
> npm i three
目录结构
资源目录里面的结构不变,点击传送门快速查看。
|__src
|__assets
|__js
| |__base 基础类文件夹
| |__Camera.js 相机类
| |__geometries 定制的物体类文件夹
| |__materials 材质类文件夹
| |__passes 合成器通道文件夹
| |__utils 工具类文件夹
| |__Sizes.js 画布大小控制类
| |__world 精灵类文件夹
| |__Application.js 初始化游戏的文件
|__index.js 入口
|__index.css 小项目,样式一丢丢
代码一览
如果你运行以下代码,浏览器能看到绿到你发慌的矩形块。
代码中预留了扩展位,后期开发中会逐步迭代完善。
如果你看到了这里,你亦可以自行填空完善。让我们的想法互相碰撞,emmm,天崩地裂^^
index.js代码
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './js/Application';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
index.css代码
* {margin: 0; padding: 0;}
html,body,#root{height: 100%;}
body {overflow: hidden;}
Camera.js代码
import * as THREE from "three";
/**
* 相机类
*/
export default class Camera {
constructor(_options) {
this.sizes = _options.sizes;
this.renderer = _options.renderer;
//创建三维对象容器
this.container = new THREE.Object3D();
this.container.matrixAutoUpdate = false; //是否算每一帧的位移、旋转(四元变换)和缩放矩阵,并重新计算matrixWorld属性
//装载相机实例
this.setInstance();
}
setInstance() {
//获取透视相机
this.instance = new THREE.PerspectiveCamera(40, this.sizes.viewport.width / this.sizes.viewport.height, 1, 80);
this.container.add(this.instance); //添加对象到这个对象的子级,可以添加任意数量的对象。
}
}
Sizes.js代码
/**
* 游戏窗口
*/
export default class Sizes {
constructor() {
this.viewport = {};
this.$sizeViewport = document.createElement("div");
this.$sizeViewport.style.width = "100vw";
this.$sizeViewport.style.height = "100vh";
this.$sizeViewport.style.position = "absolute";
this.$sizeViewport.style.top = 0;
this.$sizeViewport.style.left = 0;
this.$sizeViewport.style.pointerEvents = "none";
//监听resize
//触发resize
this.resize();
}
resize() {
document.body.appendChild(this.$sizeViewport);
this.viewport.width = this.$sizeViewport.offsetWidth;
this.viewport.height = this.$sizeViewport.offsetHeight;
document.body.removeChild(this.$sizeViewport);
//对resize的定制
}
}
Application.js代码
import React from 'react';
import ReactDOM from 'react-dom';
import * as THREE from "three";
import Camera from './base/Camera';
import Sizes from './utils/Sizes';
export default class Application extends React.Component {
componentDidMount(){
//当前画布对象
this.$canvas = ReactDOM.findDOMNode(this);
// //针对场景大小控制的类
this.sizes = new Sizes();
//导入资源
this.resources = new Resources()
//基础配置
this.setConfig();
//设置调试工具
this.setDebug();
//设置场景构造器
this.setRenderer();
//设置相机
this.setCamera();
//使用通道设置高级处理效果
this.setPasses();
//设置精灵
this.setWorld();
//测试场景
this.test()
}
setConfig(){}
setDebug(){}
setCamera(){
//获取相机
this.camera = new Camera({
sizes: this.sizes,
renderer: this.renderer,
});
//相机实例添加到场景中
this.scene.add(this.camera.container);
}
setRenderer(){
//获取场景
this.scene = new THREE.Scene();
//获取构造器
this.renderer = new THREE.WebGLRenderer({
canvas: this.$canvas, //一个供渲染器绘制其输出的canvas。如果没有传这个参数,会创建一个新canvas
alpha: true, // canvas是否包含透明度
});
//构造器设置
this.renderer.setClearColor(0x000000, 1); //设置颜色及其透明度
this.renderer.setPixelRatio(2); //设置设备像素比。通常用于避免HiDPI设备上绘图模糊
this.renderer.setSize(
this.sizes.viewport.width,
this.sizes.viewport.height
); //将输出canvas的大小调整为(width, height)并考虑设备像素比,。
this.renderer.physicallyCorrectLights = true; //是否使用物理上正确的光照模式
this.renderer.gammaFactor = 2.2; //默认2
this.renderer.gammaOutPut = true; //如果设置, 所有纹理和颜色需要乘以gamma输出
this.renderer.autoClear = false; //定义渲染器是否在渲染每一帧之前自动清除其输出
}
setPasses(){}
setWorld(){}
test(){
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
this.scene.add( cube );
this.camera.instance.position.z = 5;
this.renderer.render(this.scene, this.camera.instance)
}
render(){
return (
<canvas id="webgl"></canvas>
);
}
}
运行结果
铛铛 ~~~ 铛铛 ~~~ 瞧下面
为什么换react
额,单纯想换 ##!