<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用 Three.js 實(shí)現(xiàn)跳一跳游戲

          共 5985字,需瀏覽 12分鐘

           ·

          2022-04-29 02:49

          點(diǎn)擊上方?前端Q,關(guān)注公眾號(hào)

          回復(fù)加群,加入前端Q技術(shù)交流群

          游戲地址:fwjzzz.gitee.io/jump[2] git地址:gitee.com/fwjzzz/Jump[3



          前言

          跳一跳是微信小程序[4]的一個(gè)小游戲。長(zhǎng)按屏幕讓小人蓄力跳躍,進(jìn)行游玩。按照小人跳躍盒子的數(shù)量,以及特殊盒子加分項(xiàng)計(jì)算得分。

          游戲規(guī)則

          十分簡(jiǎn)單:長(zhǎng)按鼠標(biāo)蓄力、放手,方塊就會(huì)從一個(gè)盒子跳到另一個(gè)盒子。然而就是這個(gè)小動(dòng)作,讓你一旦開始就魔性地停不下來。

          Three.js

          Three.js?是一款運(yùn)行在瀏覽器中的 3D 引擎,你可以用它創(chuàng)建各種三維場(chǎng)景,包括了攝影機(jī)、光影、材質(zhì)等各種對(duì)象。

          1. 創(chuàng)建一個(gè)場(chǎng)景
          2. 設(shè)置光源
          3. 創(chuàng)建相機(jī),設(shè)置相機(jī)位置和相機(jī)鏡頭的朝向
          4. 創(chuàng)建3D渲染器,使用渲染器把創(chuàng)建的場(chǎng)景渲染出來

          整個(gè)程序的結(jié)構(gòu)

          image.png

          實(shí)現(xiàn)

          html文件引入three.js引擎


          復(fù)制代碼

          頁(yè)面結(jié)構(gòu)

          "mask">
          ??"content">
          ????"score-container">
          ??????"title">本次得分


          ??????"score">0
          ????

          ????"restart">
          ??????重新開始
          ????
          ??


          "info">
          ?"loop"?autoplay?controls?src="https://m801.music.126.net/20220413225245/3060206bc37e3226b7f45fa1
          ?49b0fb2b/jdymusic/obj/wo3DlMOGwrbDjj7DisKw/13866197954/e351/984c/1f8b/f6d3165d6b04dc78ec0d3c273ce02ff2.mp3"
          >???????
          ?
          ??"gaming-score">
          ????得分:"current-score">0
          ??


          復(fù)制代碼

          場(chǎng)景

          let?scene=new?THREE.Scene();
          ??//創(chuàng)建一個(gè)場(chǎng)景
          復(fù)制代碼

          相機(jī)

          常用的相機(jī)有兩種:

          符合人心理習(xí)慣,近大遠(yuǎn)小。

          遠(yuǎn)處和近處一樣大

          let?camera=new?THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,1,1000);
          ??//創(chuàng)建一個(gè)透視相機(jī)?4個(gè)參數(shù)(視覺范圍,寬高比例,近距離,遠(yuǎn)距離)
          ??camera.position.z=10;
          ??camera.position.y=3;
          ??camera.position.x=8;
          ??//相機(jī)的xyz場(chǎng)景方向
          復(fù)制代碼

          幾何體

          使用CubeGeometry創(chuàng)建一個(gè)立方幾何體,使用MeshLambertMaterial材質(zhì)用來配置立方體渲染看上去暗淡不光亮的表面,該材質(zhì)會(huì)對(duì)場(chǎng)景中的光源產(chǎn)生反應(yīng),這個(gè)材質(zhì)可以配置一些其他屬性如:顏色等。

          ?let?geometry=new?THREE.CubeGeometry(4,2,4);
          ??//創(chuàng)建一個(gè)幾何體對(duì)象?(寬,高,深度)
          ??let?material=new?THREE.MeshLambertMaterial({color:0xbebebe});
          ??//創(chuàng)建了一個(gè)可以用于立方體的材質(zhì),對(duì)象包含了顏色、透明度等屬性,
          ??let?cube=new?THREE.Mesh(geometry,material);
          ??//結(jié)合在一起
          ??cube.position.x=16;
          ??scene.add(cube);
          ??//添加到場(chǎng)景中
          復(fù)制代碼

          光源

          場(chǎng)景Scene主要是由幾何體模型和光Light構(gòu)成,在實(shí)際開發(fā)過程中,大多數(shù)三維場(chǎng)景往往需要設(shè)置光源,通過不同的光源對(duì)模型模擬生活中的光照效果,尤其是為了提高Threejs的渲染效果更需要設(shè)置好光源,就像攝影師拍照要打燈一樣。

          ??let?directionalLight=new?THREE.DirectionalLight(0xffffff,1.1);
          ??//平行光??(顏色,強(qiáng)度)
          ??directionalLight.position.set(3,10,5);
          ??//平行光位置
          ??scene.add(directionalLight);
          ??//在場(chǎng)景中加入平行光
          ??let?light=new?THREE.AmbientLight(0xffffff,0.4);
          ??//光的材質(zhì)
          ??scene.add(light);
          ??//把光添加到場(chǎng)景
          復(fù)制代碼

          渲染

          直接通過WebGL渲染器WebGLRenderer[7].setSize()方法設(shè)置渲染尺寸為瀏覽器body區(qū)域?qū)捀叨取?/p>

          ?let?renderer=new?THREE.WebGLRenderer({antialias:true});
          ??//創(chuàng)建一個(gè)渲染器?(讓邊緣動(dòng)畫沒有鋸齒感)
          ??renderer.setSize(window.innerWidth,window.innerHeight);
          ??//?畫布寬高
          ??renderer.setClearColor(0x282828);
          ??//修改畫布顏色
          ??renderer.render(scene,camera);
          ??//渲染場(chǎng)景相機(jī)?(后續(xù)更新也是這里)
          ??document.body.appendChild(renderer.domElement);
          ??//把當(dāng)前渲染的畫布放到body里面
          ??let?x=8;
          ??function?render()?{
          ???//遞歸
          ????x-=0.1;
          ????camera.position.x=x;
          ????renderer.render(scene,camera);
          ?//更新重新渲染
          ????if(x>=-8){
          ?//滿足當(dāng)前條件
          ??????requestAnimationFrame(render)
          ???//循環(huán)渲染
          ????}
          ??}
          復(fù)制代碼

          目前為止實(shí)現(xiàn)了一個(gè)雛形

          添加第二塊

          image.png
          ??????_createCube()?{
          ??let?geometry?=?new?THREE.CubeGeometry(this.config.cubeWidth,?this.config.cubeHeight,?this.config.cubeDeep);
          ??//創(chuàng)建一個(gè)幾何體對(duì)象?(寬,高,深度)
          ??let?material?=?new?THREE.MeshLambertMaterial({
          ???color:?this.config.cubeColor
          ??});
          ??//材質(zhì),對(duì)象包含了顏色、透明度等屬性,
          ??let?cube?=?new?THREE.Mesh(geometry,?material);?//合并在一起
          ??if?(this.cubes.length)?{
          ???//從第二塊開始隨機(jī)左右方向出現(xiàn)
          ???cube.position.x?=?this.cubes[this.cubes.length?-?1].position.x;
          ???cube.position.y?=?this.cubes[this.cubes.length?-?1].position.y;
          ???cube.position.z?=?this.cubes[this.cubes.length?-?1].position.z;
          ???this.cubeStat.nextDir?=?Math.random()?>?0.5???"left"?:?"right";?//要不左邊要不右邊
          ???if?(this.cubeStat.nextDir?==?"left")?{
          ????//左邊改變x軸否則y軸
          ????cube.position.x?=?cube.position.x?-?Math.round(Math.random()?*?4?+?6);
          ???}?else?{
          ????cube.position.z?=?cube.position.z?-?Math.round(Math.random()?*?4?+?6);
          ???}
          ??}
          ??this.cubes.push(cube);?//統(tǒng)一添加塊
          ??if?(this.cubes.length?>?5)?{
          ???//頁(yè)面最多看到5個(gè)塊
          ???this.scene.remove(this.cubes.shift());?//超過就移除
          ??}
          ??this.scene.add(cube);?//添加到場(chǎng)景中
          ??if?(this.cubes.length?>?1)?{
          ???//更新鏡頭位置
          ???this._updateCameraPros();
          ??}
          ?};
          復(fù)制代碼

          定義一個(gè)方塊數(shù)組,判斷從第二塊開始向左右兩邊隨機(jī)出現(xiàn)。this.cubeStat.nextDir = Math.random() > 0.5 ? "left" : "right" 如上圖:(這是由兩張圖組成的)

          跳塊

          微信截圖_20220413013025.png
          _createJumper()?{
          ??let?geometry?=?new?THREE.CubeGeometry(this.config.jumperWidth,?this.config.jumperHeight,?this.config
          ???.jumperDeep);?//?(寬,高,深度)???
          ??let?material?=?new?THREE.MeshLambertMaterial({
          ???color:?this.config.jumperColor
          ??});?//材質(zhì),顏色、透明度
          ??this.jumper?=?new?THREE.Mesh(geometry,?material);?//合并在一起
          ??this.jumper.position.y?=?1;?//顯示跳塊
          ??geometry.translate(0,?1,?0);?//平移
          ??this.scene.add(this.jumper);?//添加到場(chǎng)景中
          ?}
          復(fù)制代碼

          使用Geometry幾何體對(duì)象有一系列的頂點(diǎn)屬性和方法,通過.scale()、.translate()、.rotateX()等方法可以對(duì)幾何體本身進(jìn)行縮放、平移、旋轉(zhuǎn)等幾何變換。注意本質(zhì)上都是改變結(jié)合體頂點(diǎn)位置坐標(biāo)數(shù)據(jù)。

          鼠標(biāo)按下狀態(tài)

          ????????????this.jumperStat?=?{
          ???//鼠標(biāo)按下速度
          ???ready:?false,
          ???xSpeed:?0,
          ???ySpeed:?0
          ??};
          復(fù)制代碼
          ????_handleMouseDown()?{
          ??if?(!this.jumperStat.ready?&&?this.jumper.scale.y?>?0.02)?{
          ???this.jumper.scale.y?-=?0.01;?//壓縮塊
          ???this.jumperStat.xSpeed?+=?0.004;
          ???this.jumperStat.ySpeed?+=?0.008;
          ???this._render();
          ???requestAnimationFrame(()?=>?{
          ????this._handleMouseDown()
          ???})
          ??}
          ?};
          復(fù)制代碼
          image.png

          鼠標(biāo)松開彈起狀態(tài)

          人生不就是這樣嗎?只要你跳對(duì)了位置,就能夠“逆襲”!

          //鼠標(biāo)松開談起狀態(tài)
          ?_handleMouseUp()?{
          ??this.jumperStat.ready?=?true;
          ??if?(this.jumper.position.y?>=?1)?{
          ???if?(this.jumper.scale.y?????this.jumper.scale.y?+=?0.1;?//壓縮狀態(tài)小于1就+
          ???}
          ???if?(this.cubeStat.nextDir?==?"left")?{
          ????//挑起盒子落在哪里
          ????this.jumper.position.x?-=?this.jumperStat.xSpeed;
          ???}?else?{
          ????this.jumper.position.z?-=?this.jumperStat.xSpeed;
          ???}
          ???this.jumper.position.y?+=?this.jumperStat.ySpeed;
          ???this.jumperStat.ySpeed?-=?0.01;?//上升落下狀態(tài)
          ???this._render();
          ???requestAnimationFrame(()?=>?{
          ????//循環(huán)執(zhí)行
          ????this._handleMouseUp();
          ???})
          ??}?else?{
          ???//落下狀態(tài)
          ???this.jumperStat.ready?=?false;
          ???this.jumperStat.xSpeed?=?0;
          ???this.jumperStat.ySpeed?=?0;
          ???this.jumper.position.y?=?1;
          ???this.jumper.scale.y?=?1;
          ???this._checkInCube();?//檢測(cè)落在哪里
          ???if?(this.falledStat.location?==?1)?{
          ????//下落后等于1,+分?jǐn)?shù)
          ????this.score++;
          ????this._createCube();
          ????this._updateCamera();
          ????if?(this.successCallback)?{
          ?????//否則失敗
          ?????this.successCallback(this.score);
          ????}
          ???}?else?{
          ????this._falling()
          ???}
          ??}
          ?};
          復(fù)制代碼
          image.png

          落在哪里

          學(xué)會(huì)控制速度感是非常奇妙的事情。當(dāng)你慢下來了,學(xué)會(huì)控制速度。因?yàn)樵诿恳粋€(gè)過程當(dāng)中,都有你生命中值得停下來瀏覽、欣賞、感受的事物。在我們的認(rèn)知中,總覺得越快,擁有的時(shí)間就越多,效率就越高,生產(chǎn)力就提高。其實(shí)并不是。如果你的頭腦常常處在思維高速運(yùn)轉(zhuǎn)的狀態(tài),一定會(huì)感覺繁忙且毫無頭緒;如果你總是擔(dān)心著未來或者掛念過去,就無法專注在當(dāng)下所做的事,也一定感到時(shí)間不夠用,效率大大降低。

          ????????????????this.falledStat?=?{
          ???location:?-1,?//落在哪里?當(dāng)前塊塊上
          ???distance:?0,?//距離是否倒下
          ??};
          ??this.fallingStat?=?{
          ???//有沒有落到點(diǎn)
          ???end:?false,
          ???speed:?0.2
          ??}
          復(fù)制代碼
          //檢測(cè)落在哪里
          ?//-1???-10從當(dāng)前盒子掉落
          ?//1?下一個(gè)盒子上?10從下一個(gè)盒子上掉落
          ?//0沒有落在盒子上
          ?_checkInCube()?{
          ??let?distanceCur,?distanceNext;
          ??//當(dāng)前盒子距離????下一個(gè)盒子距離
          ??let?should?=?(this.config.jumperWidth?+?this.config.cubeWidth)?/?2;
          ??//
          ??if?(this.cubeStat.nextDir?==?"left")?{
          ???//往左走了
          ???distanceCur?=?Math.abs(this.jumper.position.x?-?this.cubes[this.cubes.length?-?2].position.x);
          ???distanceNext?=?Math.abs(this.jumper.position.x?-?this.cubes[this.cubes.length?-?1].position.x);
          ??}?else?{
          ???//往右走了
          ???distanceCur?=?Math.abs(this.jumper.position.z?-?this.cubes[this.cubes.length?-?2].position.z);
          ???distanceNext?=?Math.abs(this.jumper.position.z?-?this.cubes[this.cubes.length?-?1].position.z);
          ??}
          ??if?(distanceCur????//落在當(dāng)前塊
          ???this.falledStat.distance?=?distanceCur;
          ???this.falledStat.location?=?distanceCur???}?else?if?(distanceNext????//落在下一個(gè)塊上
          ???this.falledStat.distance?=?distanceNext;
          ???this.falledStat.location?=?distanceNext???}?else?{
          ???//落在中間
          ???this.falledStat.location?=?0;
          ??}
          ?};
          ?
          復(fù)制代碼
          微信圖片_20220413155819.png

          落到方塊上,停上一會(huì)兒,放松自己,亦會(huì)有十分的額外獎(jiǎng)勵(lì)。人生路上,匆匆忙忙趕路的時(shí)候,不要忘了適度休息調(diào)整,你會(huì)有意外地收獲,命運(yùn)的魔方會(huì)給你別致的驚喜。人生很短,何須急著走完。

          //下落過程
          ?_falling()?{
          ??if?(this.falledStat.location?==?10)?{
          ???//從下一個(gè)盒子落下
          ???if?(this.cubeStat.nextDir?==?"left")?{
          ????//判斷左方向
          ????if?(this.jumper.position.x?>?this.cubes[this.cubes.length?-?1].position.x)?{
          ?????this._fallingRotate("leftBottom")
          ????}?else?{
          ?????this._fallingRotate("leftTop")
          ????}
          ???}?else?{
          ????//判斷右方向
          ????if?(this.jumper.position.z?>?this.cubes[this.cubes.length?-?1].position.z)?{
          ?????this._fallingRotate("rightBottom")
          ????}?else?{
          ?????this._fallingRotate("rightTop")
          ????}
          ???}
          ??}?else?if?(this.falledStat.location?==?-10)?{
          ???//從當(dāng)前盒子落下
          ???if?(this.cubeStat.nextDir?==?"left")?{
          ????this._fallingRotate("leftTop")
          ???}?else?{
          ????this._fallingRotate("rightTop")
          ???}
          ??}?else?if?(this.falledStat.location?==?0)?{
          ???this._fallingRotate("none")
          ??}
          ?};
          復(fù)制代碼
          image.png
          image.png

          結(jié)尾

          贏也好,輸也罷,人生就是一個(gè)起起伏伏的過程,處在巔峰不驕,跌落低谷不餒。這才是正確的人生姿勢(shì)。當(dāng)然,這里不僅僅說的是游戲。有可能是埋頭玩游戲的,也許你早注意到那個(gè)小方塊的玩家形象,就是生活中的“ 自己 ”。這個(gè)世界就如 “跳一跳” 游戲:規(guī)則和目標(biāo)都明確的智力游戲,玩家可以自由地行動(dòng),站對(duì)位置就可以加分。時(shí)時(shí)輕拂拭,勿使惹塵埃。便可有收獲,享受生活,熱愛人世間的煙火?。。?/p>


          關(guān)于本文


          作者:奶油小泡芙

          https://juejin.cn/post/7086493323136876552


          往期推薦


          vue3中可以幫助你早點(diǎn)下班的9個(gè)開發(fā)技巧!
          86張腦圖,一口氣看完 React
          來分享面經(jīng)了,4年經(jīng)驗(yàn)的前端在上海金三銀四遨游。

          最后


          • 歡迎加我微信,拉你進(jìn)技術(shù)群,長(zhǎng)期交流學(xué)習(xí)...

          • 歡迎關(guān)注「前端Q」,認(rèn)真學(xué)前端,做個(gè)專業(yè)的技術(shù)人...

          點(diǎn)個(gè)在看支持我吧
          瀏覽 47
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  美日韩黄色一级视频 | 一本色道久久综合狠狠躁小说 | 国产标清视频 | 色婷婷精品国产一区二区 | 乱伦 的搜索结果 - 91n |