diff --git a/README.md b/README.md index 1327a61a61fae749d77ed65f6165b1e09d1d3f55..5fb344d1470ab390117ceed9dd2abffe32cbfa75 100644 --- a/README.md +++ b/README.md @@ -2,44 +2,47 @@ 2022数据结构绝不犯困小组大作业——池塘夜降彩色雨 - - -#### 池塘夜降彩色雨 - 班级:数据结构01班 姓名:林孟颖 张丁夕 陈卓勋 (按笔画顺序排序) 完成日期:2022年6月 - - #### 一、需求分析 确定池塘夜雨景色的在每一时刻的描述,并渲染到屏幕上。 -1、雨滴的特征包括位置(三维坐标,右手系,纵向为Y,Y正方向为向上,坐标轴取值0-100,当XZ方向超过边界时,通过模运算回卷到另一个方向),颜色随机,透明程度(50% - 90%),体积(关乎落入水面后涟漪的大小)。 +1、雨滴的特征包括位置(三维坐标,右手系,纵向为Y,Y正方向为向上,坐标轴取值0-100,当XZ方向超过边界时,通过模运算回卷到另一个边界),颜色,体积(关乎落入水面后涟漪的大小);涟漪的特征包括颜色、位置、当前大小、扩展的最大大小。 -2、涟漪的特征包括颜色、位置、大小。 +2、状态不断更新。雨滴下落,风向由XZ平面的向量表示,与竖直下落的向量合成后得到每一个雨滴的下落方向。雨滴落到塘面变为涟漪,雨滴落到荷叶上变为水珠。涟漪不断拓展,到达最大大小后清除。 -3、雨滴到涟漪的转换参数是风向。风向由XY平面的向量表示,与竖直下落的向量合成后得到每一个雨滴的下落方向。 +3、用户通过图形化界面,拖动拉杆,动态修改单位时间内雨滴的生成量、状态更新速率、风向、风速、视角等。 -4、雨滴到涟漪的转换瞬间伴随声音生成。 - -5、用户动态修改单位时间内雨滴的生成量(1000-5000)、体积区间(10-30,以比例1映射到水圈最大范围)、状态更新速率(100-500ms) +4、随机产生电闪雷鸣效果。 #### 二、概要设计 -使用队列表示所有雨滴对象和涟漪对象。每个对象在一定时间间隔后触发状态更新。当雨滴Z坐标小于等于0后,将其从雨滴队列删去,同时将一个涟漪对象插入队列。 +###### 1、平台选择 + +选择网页作为动画平台,基于JavaScript语言、THREE.js库实现动画,结合html和CSS实现交互。 + +##### 2、动画总体思路 + +建立三维场景,利用THREE.js中的算法将三维场景转化为2D图像并输出在网页上。 -为此,定义三个数据类型,分别是雨滴、涟漪和队列。(实际操作中,雨滴方法、涟漪方法和队列并未用上) +在首次进入网页时初始化所有背景。而后反复执行生成雨滴、雨滴下落、生成涟漪或水珠、电闪雷鸣等过程,并渲染在屏幕上。 + +###### 3、数据结构 + +建立雨滴对象和涟漪对象。在一定时间间隔后触发状态更新。当雨滴Y坐标小于等于0后,将其从雨滴组中删去,同时将一个涟漪对象放入雨滴组。 + +为此,定义两个数据类型,分别是雨滴、涟漪。 ``` 雨滴{ - 数据 + 属性 坐标 颜色 - 透明程度 体积 方法 位置更新 @@ -49,58 +52,222 @@ ``` 涟漪{ - 数据 - 当前XY平面位置 - 涟漪当前大小 - 涟漪最大大小 - 透明度(根据最大大小和当前大小计算。最大时透明度为0%,最小时透明度为50%) + 属性 + 坐标 + 颜色 + 当前大小 + 最大大小 方法 大小更新 是否到达最大大小 } -``` ``` -队列{ - 数据 - 队头 - 队尾 - 方法 - 入队 - 功能:将新元素插入到队尾 - 执行条件:队列未满 - 出队 - 功能:将队头元素删除 - 执行条件:队列未空 -} -``` +###### 4、其他动画细节 -#### 三、详细设计 +荷叶生成、雨滴与荷叶的碰撞:将塘面分块,随机确定荷叶有无,在有荷叶的地方加上手绘荷叶贴图,随机调换指向。 -构建三维场景,用摄像机模型计算当前的环境在平面上的投影。 +电闪雷鸣的表征方法:电闪——用天上乌云的局部亮度迅速变化反映;雷鸣——播放音频;电闪雷鸣间隔在一定时间范围内随机确定。 + +#### 三、详细设计 ##### 1、环境场景 -绘制卡通风格的树、岸、和水面,在平面上生成图像,并放置在坐标平面上。绘制荷叶,将水面分为网格,随机生成荷叶。可以调节参数,生成不同数量的荷叶。 +手绘卡通风格的树、岸和水面,在平面上绘制图像,并放置在坐标平面上。 + +```javascript +scene.add(createPlane(World.MAX_X,World.MAX_Y,'./picture/ddark_tree.jpg',1,1,World.MAX_X/2,World.MAX_Y/2,0,0,0,1)); +``` + +![image-20220704193903991](.\docPic\image-20220704193903991.png) + +绘制荷叶,将水面分为网格,随机生成荷叶。可以调节参数,生成不同数量的荷叶。 + +```js +for(let i =0; i { + if(amesh.isRain) + { + amesh.drop(WindAcceleration); + if(amesh.hitGround()) + { + if(amesh.fromSky && haveLotus[calcIndex(amesh.position.x)][calcIndex(amesh.position.z)]) + { + // more small balls + for(let i = 0; i { + if(amesh.isWave) + { + amesh.expand(wavePara.scaleInc); + if(amesh.reachMaxSize(wavePara.scaleMax)) + waveGroup.children.splice(index,1); + } + }) +``` + +###### 4、闪电和乌云 +通过云层的闪光模拟闪电。使用点光源照射半透明云层。 +![image-20220704194305156](.\docPic\image-20220704194305156.png) + +在当前时间仍然在闪电时间以内的时候,随机修改点光源亮度。每次闪电结束,随机确定下一次闪电开始的时间,并定时播放雷声。 + +``` +//在从上一次闪电结束,间隔lighteningGap开始的一段长为lighteningDuration的时间内会有闪电 + if(deltaTime < longestBound && deltaTime > lighteningPara.lighteningGap) + { + lightening.power = Math.random()*(lighteningPara.lmMax - lighteningPara.lmMin); + } + if(deltaTime > longestBound) { + lighteningPara.lighteningGap = lighteningPara.lighteningGapMin + (lighteningPara.lighteningGapMax - lighteningPara.lighteningGapMin) *Math.random(); + lightening.power = lighteningPara.lmMin; + lighteningPara.lastlighteningTime = nowTime; + setTimeout(() => { + sound.play(); + }, lighteningPara.lighteningGap); + } +``` + +旋转多片乌云模拟风起云涌效果。从THREE.js库中的Mesh对象继承而来,并设置自动随机旋转) + +```javascript +// 乌云对象 +class cloudMesh extends THREE.Mesh { + constructor() { + ... + this.rotate(); // 生成便开始不断自动旋转 + } + // 随机旋转,模拟风起云涌之势 + rotate() { + setInterval(() => { + var divide = 100; + this.rotateZ(Math.PI/divide * (0.8-Math.random())); + }, 100); + } +} +``` + +![image-20220704194223384](.\docPic\image-20220704194223384.png) + +#### 四、调试分析 + +使用控制台输出、肉眼观察动画效果等方式进行调试。 #### 五、运行方法 -###### 1、在项目内开启服务器 +###### 1、开启服务器 -项目根目录下有Go语言编写的服务器代码。x86-64 Linux下运行./webServer,x86-64 Windows下运行./webServer.exe。其它架构也可以安装Go-lang语言开发环境,编译webServer.go。 +项目根目录下有Go语言编写的webServer代码。x86-64 Linux下运行./webServer,x86-64 Windows下运行./webServer.exe。其它架构也可以安装Go-lang语言开发环境,编译webServer.go。或者使用其它方式开启本地服务器。 ###### 2、本地访问index.html @@ -110,16 +277,80 @@ http://localhost:8080/ ``` +注意:新版浏览器禁止了自动音频播放,若需要听雷声效果,请设置浏览器允许音频自动播放(可以将http://localhost:8080/ 纳入白名单) +另外若浏览器未自动打开index.html(显示目录结构)则需手动点击index.html。 #### 六、测试结果 +小雨 + +![image-20220704194739589](.\docPic\image-20220704194739589.png) + +大雨 + +![image-20220704194905276](.\docPic\image-20220704194905276.png) + +起风(需运行查看动画) + +![image-20220704194954955](.\docPic\image-20220704194954955.png) + +扩大视野 + +![image-20220704195230967](.\docPic\image-20220704195230967.png) + +缩小视野 + +![image-20220704195158644](.\docPic\image-20220704195158644.png) + +雨滴大小、荷叶密度、四散的水珠数量等各种参数都可以修改,此处不再一一列举 + +```javascript +const World = { + MAX_X : 100, // 世界的尺寸 + MAX_Y : 100, + MAX_Z : 100, + WaterBlockNum : 10, // 荷塘水面分块的个数 + LotusRatio : 0.3, // 荷叶占比 + LotusHeight : 0.0001, // 荷叶悬空高度 + WaveHeight : 0.00005, // 波纹悬空高度 + smallBallNum : 4, // 每一个雨滴撞击到荷叶产生的小水珠个数 + deaccRatio : 0.1, // 反弹速度与原速度的比例 + boundAngle : Math.PI/6, // 水珠反射角 + cloudToBackRatio : 0.01, // 云与世界边界最短距离与世界尺寸的比例 + cloudNum : 200, // 云的数量 + lightColor : 0x556666, // 闪电的颜色 + lookAtMe : null, // 相机注视高度 与用户交互 + fieldOfView : null, // 视野大小 与用户交互 +} + +const lighteningPara = { + //在从上一次闪电结束,间隔lighteningGap开始的一段长为lighteningDuration的时间内会有闪电 + // 闪电时间会随每次闪电结束随机调整 + lighteningGapMax : 10000, // 两次闪电的最大时间间隔 单位ms + lighteningGapMin : 5000, // 两次闪电的最小时间间隔 单位ms + lighteningGap : 7500, // 闪电的实际间隔 单位ms + lighteningDuration : 300, // 一次闪电的时间 单位ms + lastlighteningTime : 0, // 上一次闪电时刻 单位ms + lmMax : 200, // 闪电最大亮度 + lmMin : 20, // 闪电最小亮度 +} +``` + +#### 七、附录(源代码链接和源文件说明) + +./js/main.js 为彩色雨源码 + +./js/THREE.js 为开源库,提供3D场景基本操作 +./pic 和.picture中为整个项目编写期间手绘的素材 -#### 七、附录(源代码链接) +./sound 中为雨声和雷声 +css文件中为页面排版,html文件中为页面基本元素 +Gitee开源链接:[池塘夜降彩色雨: 2022数据结构绝不犯困小组大作业——池塘夜降彩色雨 (gitee.com)](https://gitee.com/zhang-dingxi/rainbow_in_the_pond) #### 八、致谢 -感谢JavaScript开源库 Three.js的开发者们。 +感谢小组成员们的通力合作!感谢JavaScript开源库 THREE.js的开发者和开源社区的工作者们! diff --git a/docPic/image-20220704193903991.png b/docPic/image-20220704193903991.png new file mode 100644 index 0000000000000000000000000000000000000000..cc370d2c173968e5cf50572e91f2e766d3748799 Binary files /dev/null and b/docPic/image-20220704193903991.png differ diff --git a/docPic/image-20220704194034592.png b/docPic/image-20220704194034592.png new file mode 100644 index 0000000000000000000000000000000000000000..8e0e02032c5068df9d09760fefd5a542c0c27164 Binary files /dev/null and b/docPic/image-20220704194034592.png differ diff --git a/docPic/image-20220704194124896.png b/docPic/image-20220704194124896.png new file mode 100644 index 0000000000000000000000000000000000000000..b3a31665ccba204723d8e7398beb155609689842 Binary files /dev/null and b/docPic/image-20220704194124896.png differ diff --git a/docPic/image-20220704194223384.png b/docPic/image-20220704194223384.png new file mode 100644 index 0000000000000000000000000000000000000000..28fc8321dfbb7e00b8c095e933d884ea0063b8be Binary files /dev/null and b/docPic/image-20220704194223384.png differ diff --git a/docPic/image-20220704194305156.png b/docPic/image-20220704194305156.png new file mode 100644 index 0000000000000000000000000000000000000000..649c33207bef3409eb642846f82f3f6376f73aed Binary files /dev/null and b/docPic/image-20220704194305156.png differ diff --git a/docPic/image-20220704194739589.png b/docPic/image-20220704194739589.png new file mode 100644 index 0000000000000000000000000000000000000000..ca06961cf53f35b3e2116e81a17fa2cada12f543 Binary files /dev/null and b/docPic/image-20220704194739589.png differ diff --git a/docPic/image-20220704194905276.png b/docPic/image-20220704194905276.png new file mode 100644 index 0000000000000000000000000000000000000000..e90958cec7cef2a03b34a1415af8eac307ad7f4e Binary files /dev/null and b/docPic/image-20220704194905276.png differ diff --git a/docPic/image-20220704194954955.png b/docPic/image-20220704194954955.png new file mode 100644 index 0000000000000000000000000000000000000000..3a7984224ea62bb524a140e995f8f89e74eafaeb Binary files /dev/null and b/docPic/image-20220704194954955.png differ diff --git a/docPic/image-20220704195158644.png b/docPic/image-20220704195158644.png new file mode 100644 index 0000000000000000000000000000000000000000..b1b3fff916780f6d3aa696e62fa91b9c7cef3003 Binary files /dev/null and b/docPic/image-20220704195158644.png differ diff --git a/docPic/image-20220704195230967.png b/docPic/image-20220704195230967.png new file mode 100644 index 0000000000000000000000000000000000000000..9c4cd3d3d9d993686ece74566c11f358fe4e2058 Binary files /dev/null and b/docPic/image-20220704195230967.png differ diff --git a/index.html b/index.html index 18e9623cad40c77fd946007b1a38ce0a6b20b5c4..ba754e09427dcf240ea5f9497700d7870ae3d9a6 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ Rainbow in the pond - + @@ -37,7 +37,7 @@ - + \ No newline at end of file diff --git a/js/rainAndWave.js b/js/main.js similarity index 80% rename from js/rainAndWave.js rename to js/main.js index 6102f359206f5e01161088e639f62145a33b5162..faaac8bc26627e7231c6a46057feccf8326c9e62 100644 --- a/js/rainAndWave.js +++ b/js/main.js @@ -5,60 +5,58 @@ "use strict" const World = { - MAX_X : 100, //世界的尺寸 + MAX_X : 100, // 世界的尺寸 MAX_Y : 100, MAX_Z : 100, - WaterBlockNum : 10, //荷塘水面分块的个数 - LotusRatio : 0.3, //荷叶占比 - LotusHeight : 0.0001, //荷叶悬空高度 - WaveHeight : 0.00005, //波纹悬空高度 - smallBallNum : 4, //每一个雨滴撞击到荷叶产生的小水珠个数 - deaccRatio : 0.1, //反弹速度与原速度的比例 - boundAngle : Math.PI/6, //水珠反射角 - lotusScaleInc : 0.33, - cloudToBackRatio : 0.01, - cloudNum : 200, - lightColor : 0x556666, - lookAtMe : null, - fieldOfView : null, + WaterBlockNum : 10, // 荷塘水面分块的个数 + LotusRatio : 0.3, // 荷叶占比 + LotusHeight : 0.0001, // 荷叶悬空高度 + WaveHeight : 0.00005, // 波纹悬空高度 + smallBallNum : 4, // 每一个雨滴撞击到荷叶产生的小水珠个数 + deaccRatio : 0.1, // 反弹速度与原速度的比例 + boundAngle : Math.PI/6, // 水珠反射角 + cloudToBackRatio : 0.01, // 云与世界边界最短距离与世界尺寸的比例 + cloudNum : 200, // 云的数量 + lightColor : 0x556666, // 闪电的颜色 + lookAtMe : null, // 相机注视高度 与用户交互 + fieldOfView : null, // 视野大小 与用户交互 } const lighteningPara = { //在从上一次闪电结束,间隔lighteningGap开始的一段长为lighteningDuration的时间内会有闪电 // 闪电时间会随每次闪电结束随机调整 - lighteningGapMax : 10000, // ms - lighteningGapMin : 5000, // ms - lighteningGap : 7500, // ms - lighteningDuration : 200, // ms - lastlighteningTime : 0, // 上一次闪电时刻 - lmMax : 200, //最大亮度 - lmMin : 20, //最小亮度 + lighteningGapMax : 10000, // 两次闪电的最大时间间隔 单位ms + lighteningGapMin : 5000, // 两次闪电的最小时间间隔 单位ms + lighteningGap : 7500, // 闪电的实际间隔 单位ms + lighteningDuration : 300, // 一次闪电的时间 单位ms + lastlighteningTime : 0, // 上一次闪电时刻 单位ms + lmMax : 200, // 闪电最大亮度 + lmMin : 20, // 闪电最小亮度 } const windPara = { - windSpeed : null, //改风速。0的时候,竖直下落 - direction : null, //radius 改风向:0~2PI + windSpeed : null, // 风速 与用户交互 + direction : null, // 风向 取值0~2PI 单位弧度 与用户交互 } var WindAcceleration = new THREE.Vector3(-0.01,-0.1,-0.01); //空气坐标系内加速度。单位为 数值每二次方更新间隔 - // 雨滴从y最大落到xz平面(y=0) var rainPara = { - density : null, // 每次更新落下来的雨滴 - maxSize : 0.5 //雨滴最大大小,雨滴大小是随机生成的 + density : null, // 每次更新落下来的雨滴 + maxSize : 0.5 // 雨滴最大大小,雨滴大小是随机生成的 } -var AnimPara = { //动画刷新控制参数,单位毫秒 - refreshTimeGap : null, // ms 刷新时间间隔 - lastRefreshTime : 0 // ms +var AnimPara = { // 动画刷新控制参数 单位ms + refreshTimeGap : null, // 刷新时间间隔 单位ms 与用户交互 + lastRefreshTime : 0 // 上一次刷新时刻 单位ms } -var wavePara = { // 波纹参数 +var wavePara = { // 波纹参数 waveBreadth : 0.15, //波纹内外半径差 initialScale : 0.4, //波纹初始缩放程度 - scaleInc : 0.3, //每次刷新缩放比例增幅 - scaleMax : 3, //最大缩放比例 + scaleInc : 0.3, //每次刷新缩放比例增幅 + scaleMax : 3, //最大缩放比例 } // 页面交互接口 @@ -69,7 +67,7 @@ windPara.windSpeed = document.getElementById("windStr"); World.lookAtMe = document.getElementById("cameraVw"); World.fieldOfView = document.getElementById("cameraFOV"); - +// 从用户界面获取参数,更新全局变量 function change() { var density = Number(rainPara.density.value), windDir = Number(windPara.direction.value), @@ -92,7 +90,7 @@ function change() { World.fieldOfView.style.backgroundSize = `${cameraFOVPercent}%, 100%`; }; -// Refresh function +// 从全局变量更新风向和相机参数 function refresh(){ /* refreshWindAcc */ // direction is an angle ranging from 0 to 2*PI. radius as unit distance @@ -105,10 +103,8 @@ function refresh(){ camera.updateProjectionMatrix(); } - // 类型定义 - //雨滴类。从三维网格对象继承而来。通过参数构造形状、大小、颜色等特征 // 溅起的水珠和雨滴都用雨滴对象表示,使用fromSky属性保证只有从天而降的雨滴才会溅起更多水珠,避免无尽溅起新水珠 class RainMesh extends THREE.Mesh { @@ -143,7 +139,7 @@ class RainMesh extends THREE.Mesh { //雨滴落到了地面 hitGround() { - return this.position.y <0; + return this.position.y < 0; } } @@ -172,28 +168,16 @@ class WaveMesh extends THREE.Mesh { } -// setup stage - - -/** - * 1.generate scene, camera and renderer. - */ - +// 初始化相机和页面canvas元素 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(50,window.innerWidth / window.innerHeight,0.1,1000); const renderer = new THREE.WebGLRenderer(); camera.position.set(World.MAX_X*0.9,World.MAX_Y/2,World.MAX_Z*0.9); camera.lookAt(0,World.MAX_Y/4,0); - renderer.setSize(window.innerWidth,window.innerHeight); document.body.appendChild(renderer.domElement); - -/** - * 2.create the pond side, the xy and yz plane are stones, trees and clouds - * the xz are the gound and pond - */ - +// 绘制法向量为某方向向量的平面 function createPlane(xSize,ySize,texture,repeatX,repeatY,px,py,pz,dx,dy,dz) { let Geo = new THREE.PlaneGeometry(xSize,ySize); let Pic = new THREE.TextureLoader().load(texture); @@ -202,53 +186,39 @@ function createPlane(xSize,ySize,texture,repeatX,repeatY,px,py,pz,dx,dy,dz) { Pic.repeat.set(repeatX,repeatY); let mesh = new THREE.Mesh(Geo,new THREE.MeshBasicMaterial({side:THREE.DoubleSide,map:Pic})); mesh.position.set(px,py,pz); - // var direct; mesh.rotateX((new THREE.Vector2(dz,dy).angle())) ; - // console.log(-(new THREE.Vector2(dy,dz).angle())); mesh.rotateY((new THREE.Vector2(dz,dx).angle())) ; mesh.rotateZ(-(new THREE.Vector2(dx,dy).angle())) ; return mesh; - } +// 生成前后左右的树和石头 生成水面 scene.add(createPlane(World.MAX_X,World.MAX_Y,'./picture/ddark_tree.jpg',1,1,World.MAX_X/2,World.MAX_Y/2,0,0,0,1)); scene.add(createPlane(World.MAX_X,World.MAX_Y,'./picture/ddark_tree.jpg',1,1,0,World.MAX_Y/2,World.MAX_Z/2,1,0,0)); scene.add(createPlane(World.MAX_X,World.MAX_Y,'./picture/ddark_tree.jpg',1,1,World.MAX_X/2,World.MAX_Y/2,World.MAX_Z,0,0,1)); scene.add(createPlane(World.MAX_X,World.MAX_Y,'./picture/ddark_tree.jpg',1,1,World.MAX_X,World.MAX_Y/2,World.MAX_Z/2,1,0,0)); scene.add(createPlane(World.MAX_X,World.MAX_Y,'./picture/processed/water_wave.jpg',World.WaterBlockNum,World.WaterBlockNum,World.MAX_X/2,0,World.MAX_Z/2,0,1,0)); -//water - - +// 计算一维坐标下荷叶的序号 function calcIndex(x) { return Math.floor(x/World.MAX_X *World.WaterBlockNum); } +// 建立荷叶贴图平面 var leaveGeo = new THREE.PlaneGeometry(World.MAX_X/World.WaterBlockNum,World.MAX_Y/World.WaterBlockNum); var leavePic = new THREE.TextureLoader().load('./picture/processed/water_leave.png'); -// var leavePic = new THREE.TextureLoader().load('./picture/leave1-2.png'); - var haveLotus = new Array(World.WaterBlockNum); -/** - * 3.initialize the lotus array randomly, - * (generate frogs if we still have time) - */ - - -// generate leaves +// 对池塘分块,随机生成荷叶 for(let i =0; i { var divide = 100; - // this.rotateX(Math.PI/divide); this.rotateZ(Math.PI/divide * (0.8-Math.random())); }, 100); } } - - +// 在场景中增加乌云 for(let i =0 ; i< World.cloudNum;i++){ scene.add(new cloudMesh()); } @@ -294,7 +260,7 @@ var lightening = new THREE.PointLight(World.lightColor,1,1000); lightening.position.set(World.MAX_X/2,World.MAX_Y/2,World.MAX_Z/2); scene.add(lightening); -//环境光 +//环境光,让乌云不是全黑的 var ambLight = new THREE.AmbientLight(World.lightColor,2.5) scene.add(ambLight); @@ -309,17 +275,13 @@ audioLoader.load( './sound/thunder.mp3', function( buffer ) { sound.setVolume( 0.5 ); }); -// prepare for the rain and wave - +// 建立两个Group,保存水珠和涟漪对象 let rainGroup = new THREE.Group; let waveGroup = new THREE.Group; scene.add(rainGroup); scene.add(waveGroup); - -// loop stage - function draw() { renderer.render(scene,camera); allFallsDown(); @@ -327,16 +289,16 @@ function draw() { requestAnimationFrame(draw); } +// 世界状态更新 function allFallsDown() { - // control refresh frequency + // 控制更新速率 未达到更新时间就直接返回 if(new Date().getTime() - AnimPara.lastRefreshTime < Number(AnimPara.refreshTimeGap.value)) return; AnimPara.lastRefreshTime = new Date().getTime(); - //4.generate new rain - - for(let i = 0; i { if(amesh.isRain) { @@ -374,25 +336,21 @@ function allFallsDown() { rainGroup.children.splice(index,1); } } - }) - //6. rain hit the lotus or pond and become splash or wave - - //7. refresh wave expansion + // 更新涟漪 waveGroup.children.forEach( (amesh,index) => { if(amesh.isWave) { amesh.expand(wavePara.scaleInc); - //8. wave disappear if(amesh.reachMaxSize(wavePara.scaleMax)) waveGroup.children.splice(index,1); } }) - //9. randomly create a lightening - + + // 随机产生雷电,在一段时间内随机改变亮度,模拟闪电 let nowTime; let longestBound; let deltaTime; @@ -401,33 +359,30 @@ function allFallsDown() { longestBound = lighteningPara.lighteningGap + lighteningPara.lighteningDuration; //在从上一次闪电结束,间隔lighteningGap开始的一段长为lighteningDuration的时间内会有闪电 - if(deltaTime < longestBound && deltaTime > lighteningPara.lighteningGap) { lightening.power = Math.random()*(lighteningPara.lmMax - lighteningPara.lmMin); } if(deltaTime > longestBound) { lighteningPara.lighteningGap = lighteningPara.lighteningGapMin + (lighteningPara.lighteningGapMax - lighteningPara.lighteningGapMin) *Math.random(); - - lightening.power = lighteningPara.lmMin; lighteningPara.lastlighteningTime = nowTime; setTimeout(() => { sound.play(); }, lighteningPara.lighteningGap); } - - } +// 开始绘制和运转 draw(); +// 让画面充满屏幕 function setCanvaSize(){ var canvas = document.getElementsByTagName('canvas')[0]; canvas.setAttribute('width', document.body.clientWidth); canvas.setAttribute('height', document.body.clientHeight); - //console.log(window.innerHeight, window.innerWidth); } + //侧边栏 var btn = document.getElementById("btn"); var control = document.getElementById("control"); @@ -437,4 +392,5 @@ btn.addEventListener('click', function(e) { // 动态添加类名和删除类名 control.classList.toggle("slide"); }) + setCanvaSize(); \ No newline at end of file diff --git a/useful_notes.md b/useful_notes.md deleted file mode 100644 index 9d479443e8ed8ba403b7cd02d64d8458307db2d0..0000000000000000000000000000000000000000 --- a/useful_notes.md +++ /dev/null @@ -1,15 +0,0 @@ -About the Frustum and field of view -https://docs.unity3d.com/Manual/UnderstandingFrustum.html - -https://threejs.org/docs/index.html?q=renderer#api/en/renderers/WebGLRenderer - -the renderer has an element: canvas, to output the image, it should be added to the html to be displayed. - -a html only need one canvas, thus only one renderer. - -and the raindrop must be abandoned after hitting the groud, and nothing should point to the raindrop after that to enable garbage collector to get the memory back(I think so). - -also, we only need one camera for all the scene. - -we call it the process of learning -https://blog.csdn.net/yinge0508/article/details/123132259?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-4-123132259-blog-108352748.pc_relevant_paycolumn_v3&spm=1001.2101.3001.4242.3&utm_relevant_index=7 \ No newline at end of file