Threejs系列--9游戏开发--沙漠赛车游戏【基础事件处理器】

  • 序言
  • 目录结构
  • 代码一览
    • Time.js代码
    • EventEmitter.js代码
    • Sizes.js代码
    • Application.js代码
  • 代码解读
  • 运行结果

序言

通过上一章,你可以将图形渲染出来,但是没有任何动画效果。本章将进行动画事件的基本处理,让图像可以在页面内运动。

目录结构

资源目录里面的结构不变,点击传送门快速查看。

|__src|__assets|__js|    |__base     基础类文件夹|     |__Camera.js 相机类|   |__geometries   定制的物体类文件夹|  |__materials    材质类文件夹| |__passes   合成器通道文件夹|   |__utils    工具类文件夹|     |__Sizes.js  画布大小控制类|       |__EventEmitter.js 基础事件处理器 【新增--处理事件队列】|        |__Time.js  动画刷新 【新增--处理动画的刷新与停止】|  |__world    精灵类文件夹| |__Application.js   初始化游戏的文件 【test方法中新增刷新事件】|__index.js     入口|__index.css      小项目,样式一丢丢

代码一览

新增了两个文件,以及Application中test对其进行了测试。

Time.js代码

import EventEmitter from "./EventEmitter";export default class Time extends EventEmitter {constructor(){super();this.tick = this.tick.bind(this);this.tick()}/*** 屏幕刷新*/tick(){window.requestAnimationFrame(this.tick);this.trigger("tick");}/*** 停止刷新*/stop(){}
}

EventEmitter.js代码

/*** 事件处理器*/
export default class {constructor(){//事件队列this.callbacks = {};this.callbacks.base = {};}/*** 绑定事件* @param {*} _names * @param {*} callback * @returns */on(_names, callback) {if(typeof _names === "undefined" && _names == "") {console.warn("事件名异常");return false;}if(typeof callback !== "function"){console.warn("事件回调异常");return false;}//处理事件名列表const names = this.resolveNames(_names);//将事件添加到回调队列names.forEach(_name => {//处理单个事件名const name = this.resolveName(_name);if(!(this.callbacks[name.namespace] instanceof Object)){this.callbacks[name.namespace] = {};}if(!(this.callbacks[name.namespace][name.value] instanceof Array)){this.callbacks[name.namespace][name.value] = [];}this.callbacks[name.namespace][name.value].push(callback);});return this;}/*** 卸载事件*/off(_names) {if(typeof _names === "undefined" || _names === ""){console.warn("事件名异常");return false;}const names = this.resolveNames(_names);names.forEach(_name => {const name = this.resolveName(_names);if (name.namespace !== "base" && name.value === "") {delete this.callbacks[name.namespace];return;}if (name.namespace === "base") {for (const namespace in this.callbacks) {if (this.callbacks[namespace] instanceof Object &&this.callbacks[namespace][name.value] instanceof Array) {delete this.callbacks[namespace][name.value];if (Object.keys(this.callbacks[namespace]).length === 0)delete this.callbacks[namespace];}}return;}if (this.callbacks[name.namespace] instanceof Object &&this.callbacks[name.namespace][name.value] instanceof Array) {delete this.callbacks[name.namespace][name.value];if (Object.keys(this.callbacks[name.namespace]).length === 0) {delete this.callbacks[name.namespace];}}})return this;}/*** 触发事件* @param {string} _name * @param {array} _args */trigger(_name, _args) {if (typeof _name === "undefined" || _name === "") {console.warn("事件名异常");return;}const args = !(_args instanceof Array) ? [] : _args;let name = this.resolveNames(_name);name = this.resolveName(name[0]);if (name.namespace === "base") {for(const namespace in this.callbacks){if(this.callbacks[namespace] instanceof Object &&this.callbacks[namespace][name.value] instanceof Array){this.callbacks[namespace][name.value].forEach(callback => {callback.apply(this, args);})}}return;}console.log(this.callbacks[name.namespace] )if (this.callbacks[name.namespace] instanceof Object) {if (name.value === "") {console.warn("事件名异常");return;}this.callbacks[name.namespace][name.value].forEach(callback => {callback.apply(this, args);})}}/*** 处理事件名列表* @param {strinng} _names * @returns */resolveNames(_names) {let names = _names;names = names.replace(/[^a-zA-Z0-9 ,/.]/g, "");names = names.replace(/[,/]+/g, " ");names = names.split(" ");return names;}/*** 处理事件名* @param {string} name * @returns */resolveName(name) {const newName = {};const parts = name.split(".");newName.original = name;newName.value = parts[0];newName.namespace = "base";if(parts.length > 1 && parts[1] !== ""){ newName.namespace = parts[1];}return newName;}
}

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//触发resizethis.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';
import Time from './utils/Time';export default class Application extends React.Component {componentDidMount(){//当前画布对象this.$canvas = ReactDOM.findDOMNode(this);//对于画面的交互事件处理this.time = new Time();// //针对场景大小控制的类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。如果没有传这个参数,会创建一个新canvasalpha: 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;  //默认2this.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.time.on("tick", () => {this.camera.instance.position.z  += 0.02; this.renderer.render(this.scene, this.camera.instance)  });}render(){return (<canvas id="webgl"></canvas>);}
}

代码解读

EventEmitter.js是一个事件处理的基础类,可以称为事件管理器。
on() 进行事件绑定
off() 进行事件卸载
trigger() 进行事件触发
所有的事件都添加在属性 callbacks 这个对象上。通过对象内的属性区分是否基础事件,或者其它事件。每个对象内维护一个事件队列。Time.js是一个处理画面刷新的类。
tick() 刷新画面
stop() 停止刷新
Time类继承EventEmitter类,以后页面中需要对事件进行处理,可以使用time对象。例如:在入口的test方法中绑定了页面刷新的事件,接着在页面刷新中不断触发刷新方法,就会看到动画效果了。

运行结果

绿色的矩形块将会有大变小

Threejs系列--10游戏开发--沙漠赛车游戏【基础事件处理器】相关推荐

  1. Threejs系列--11游戏开发--沙漠赛车游戏【初步加载地面】

    Threejs系列--11游戏开发--沙漠赛车游戏[初步加载地面] 序言 目录结构 代码一览 world/index.js代码 world/Floor.js代码 materials/Floor.js代 ...

  2. Threejs系列--22游戏开发--沙漠赛车游戏【布置游戏开始场景】

    Threejs系列--22游戏开发--沙漠赛车游戏[布置游戏开始场景] 序言 目录结构 代码一览 index.js代码 Objects.js代码 Materials.js代码 materials/Fl ...

  3. Threejs系列--9游戏开发--沙漠赛车游戏【基础场景渲染】

    Threejs系列--9游戏开发--沙漠赛车游戏[基础场景渲染] 序言 准备工作 目录结构 代码一览 index.js代码 index.css代码 Camera.js代码 Sizes.js代码 App ...

  4. Threejs系列--16游戏开发--沙漠赛车游戏【loading与start切换效果】

    Threejs系列--16游戏开发--沙漠赛车游戏[loading与start切换效果] 序言 目录结构 新增依赖 代码一览 world/index.js代码 代码解读 运行结果 序言 本章将使页面中 ...

  5. Threejs系列--14游戏开发--沙漠赛车游戏【纹理贴图之loading加载】

    Threejs系列--14游戏开发--沙漠赛车游戏[纹理贴图之loading加载] 序言 目录结构 代码一览 world/index.js代码 Application.js代码 代码解读 运行结果 序 ...

  6. Threejs系列--18游戏开发--沙漠赛车游戏【loading资源加载进度条】

    Threejs系列--18游戏开发--沙漠赛车游戏[loading资源加载进度条] 序言 目录结构 代码一览 AreaFloorBorderBufferGeometry.js代码 AreaFloorB ...

  7. Threejs系列--13游戏开发--沙漠赛车游戏【使用效果合成器添加高级效果】

    Threejs系列--13游戏开发--沙漠赛车游戏[使用效果合成器添加高级效果] 序言 目录结构 代码一览 Blur.js代码 Glows.js代码 Application.js代码 代码解读 运行结 ...

  8. jpct-ae开发3D赛车游戏

    http://magicbird.iteye.com/blog/1578367 jpct-ae开发3D赛车游戏博客分类: jpct ae jpct-ae游戏引擎的资料比较少,本人是在官网中hellow ...

  9. 游戏开发心得——资料篇——游戏行业的详细职位介绍与定义分析

    游戏开发心得--资料篇--游戏行业的详细职位介绍与分析(不定期更新) FOR THE SIGMA FOR THE GTINDER FOR THE ROBOMASTER 简介: 本篇主要介绍一下博主所了 ...

最新文章

  1. webbrowser selstart selLength
  2. D3Vueecharts个人乱记
  3. 服务器性能指标(二)——CPU利用率分析及问题排查
  4. dell服务器r730安装esxi系统,安装Esxi系统重装Esxi系统
  5. 中国国民休闲状况调查(2020)
  6. oracle计算时sum溢出_Oracle内存全面分析
  7. 【java】ASM代理方式 Byte-Buddy代理方式 Javassist代理方式
  8. 【学习总结】Git学习-参考廖雪峰老师教程三-创建版本库
  9. 微型计算机及原理怎么进制的,微型计算机原理及应用课件bcd码运算肥的十进制.ppt...
  10. ztree 标准得json数据格式_Django+zTree构建组织架构树
  11. 从零实现深度学习框架——实现Debug功能与no_grad
  12. mssql sql server 其它系统函数 parsename 点语法字符串分割函数应用简介
  13. jquery的deferred使用详解
  14. spark学习5(hbase集群搭建)
  15. iNOC产品部--完全数计算
  16. 腾讯全球首款JS代码坦克 CodeTank
  17. android极光富媒体推送,极光推送如何在android客户端接收富媒体
  18. 浙大计算机学院考研复试上机试题,浙大计算机学院考研复试上机试题.doc
  19. Word中的手动换行符
  20. AI安全上路小记1-概观线性回归

热门文章

  1. 4.1Reduction模型
  2. SQL SERVER查询生僻字问题
  3. m4v格式如何转换mp4?分享m4v转换mp4的方法
  4. SQL Anywhere(ASA) 数据库“File is shorter than expected -- transaction rolled back”错误修复...
  5. serv-u ftp server是什么?如何利用花生壳搭建ftp服务器?
  6. 如何让vs2019的主题变好看(NightOwl主题为例)???像vscode和webstorm一样自定义主题!!!
  7. MySQL的多表查询-多表关系与相关练习题
  8. 解决idea在运行时出现Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8?
  9. 专题 | Innovus 2020: 创新,永无止境
  10. 求生之路2服务器搭建指南个人存档