<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 邊界與摩擦力 在前面的幾章中,我們已經介紹了如何實現用戶交互、利用三角函數實現物體旋轉、給物體加上速度和加速度,利用這些知識,我們已經能夠實現很豐富的動畫效果,不過,似乎動畫還不夠真實,比如:物體可以無限的向左或向右移動、運動沒有阻力,這就是這一章要處理的問題:邊界和摩擦力。 **1、邊界** 在一個游戲中,很少會讓物體可以無限的向左或向右的移動,這就出現了“活動范圍”這一詞,我們在這里稱為“邊界”,邊界也可以認為是我們用墻將物體圍住,限制它的移動位置。 在canvas中,我們一般會設置三種邊界: - 整個canvas元素 - 大于canvas的區域,比如有一張大地圖,物體可以在里面任意移動,移到邊界時地圖也跟著移動變化 - 小于canvas的區域,比如給物體設置了一個小房間,限制它的活動范圍 **1.1 設置邊界** 設置邊界其實也是一種碰撞檢測,只不過物體的碰撞對象變成了邊界。 當我們將整個canvas大小作為邊界時,我們可以很容易檢測: ``` if(ball.x > canvas.width){ console.log('超出了右邊界'); }else if(ball.x < 0){ console.log('超出了左邊界'); }; if(ball.y > canvas.height){ console.log('超出了下邊界'); }else if(ball.y < 0){ console.log('超出了上邊界'); }; ``` 這里為什么是 ball.y < 0 是超出了上邊界,請回想一下canvas的坐標是怎樣的。 那么,如果不是基于整個canvas元素內,怎么做呢?一般以兩個點作為范圍點,看下圖: ![](https://box.kancloud.cn/7d8c431ed1024e6ebd42900de1710f11_359x222.jpg) 如何檢測物體在這個范圍內,代碼如下: ``` if( ball.x < x1 ){ console.log('物體超出了左邊界'); }else if( ball.x > x2){ console.log('物體超出了右邊界'); }; if( ball.y < y1 ){ console.log('物體超出了上邊界'); }else if( ball.y > y2){ console.log('物體超出了下邊界'); }; ``` 當然,上面這段代碼是檢測物體的中心點是否越界,如果要檢測是否完全越界,就需要加或減物體的高寬了:比如檢測物體是否完全越出了左邊界: ![](https://box.kancloud.cn/f59aa45355ce7c43a09c18f426548c8e_365x222.jpg) ``` if( ball.x < (x1 - ball.radius)){ console.log('物體完全越出了左邊界'); }; ``` 大多數情況下,我們不是單純的檢測物體是否越界,而是為了在物體越界后進行某些操作,當然,你也可以在物體越界后不做任何操作,不過這不是我們所推薦的。 當物體越界時,一般我們會進行以下4中選擇操作: - 移除物體 - 重置物體,也就是讓物體所有狀態恢復到原始位置 - 屏幕環繞:讓同一個物體出現在邊界內的另一個位置 - 物體反彈,也就是向反方向運動 **1.2 移除物體** 移除物體多用在多個物體在canvas上移動時,這時,我們一般將它們的引用保存到一個數組中,再通過遍歷整個數組的來移動它們(前面的例子,我都是采取這種方式),這樣,我們就可以使用 Array.splice 方法來移除數組中的某個物體了。 ``` var balls = []; // 存放多個物體的數組 var ball = balls[i]; if(ball.x < x1 || ball.x > x2 || ball.y < y1 || ball.y > y2){ balls.splice(balls.indexof(ball),1); i -= 1; } ``` 上面的檢測越界條件是和檢測在邊界內的條件是不一樣的。 注意:當你使用 Array.splice 方法在循環中移除元素后,需要加上 i -= 1,不然后續循環會出問題。當然,你也可以使用反向遍歷,就不會存在這問題: ``` var i = balls.length; while( i-- ){ if(ball.x < x1 || ball.x > x2 || ball.y < y1 || ball.y > y2){ balls.splice(balls.indexof(ball),1); } } ``` **1.3 重置物體** 重置物體其實就是重新設置物體的位置坐標。 在下面的例子,你會看到一個物體從上向下落下,當它離開canvas后,又有一個物體在同一個位置開始從上向下落下,看起來是不同的物體,其實是同一個,只不過每次它離開canvas后,都將它的 ball.y 設置為原始值,在這里是0。 實例:canvas-demo/animationResetObject.html **1.4 屏幕環繞** 屏幕環繞的意思是當物體從屏幕左邊移出,它就會在屏幕右邊再次出現;當物體從屏幕上方移出,它又會出現在屏幕下方,反之亦然。 屏幕環繞和重置物體類似,都遵循著同一個物體的原則,只不過屏幕環繞是讓其從一邊出再從相反的一邊進而已。 **1.5 反彈** 在讓物體反彈之前,你需要檢測物體何時離開屏幕,當它剛要離開時,要保持它的位置不變而僅改變它的速度向量,也可以說是速度值取反。 在檢測何時反彈時,有一點需要注意,我們不能等到物體完全移出canvas才開始反彈,這顯然和現實不符合,不知道你有沒有玩過足球,當你將足球踢向墻壁時,你會看到球在撞墻后,停在那里并很快反彈回來。 當物體移到如下圖位置,物體就要開始反彈: ![](https://box.kancloud.cn/c8985f501f10399d6da264897832ee1b_365x222.jpg) ``` if( ball.x <= (x1 + ball.radius)){ ball.x = x1 + ball.width; ball.speed.x *= -1; } ``` 在上面的代碼中,我們將 -1 作為反彈系數,不過在現實中,反彈的速度總是會有所減小,這是因為能量損失,所以為了模擬更真實的動畫,你可以將 -1 乘以一個百分比來實現能量損耗的效果。 ``` ball.speed.x *= -0.8; ``` 反彈的步驟如下: - 檢測物體是否越界 - 如果發生越界,立即將物體置回邊界 - 反轉物體的速度向量的方向,也可以說是速度取反。 實例: canvas-demo/oneDirection.html **2、摩擦力(friction)** 摩擦力,又一物理概念,也可稱為阻力,指兩個互相接觸的物體,當它們要發生或已經發生相對運動時,就會在接觸面上產生一種阻礙相對運動的力。 上面是概念式的說法,簡單的講,摩擦力就是阻止你運動的力,它并不會改變你運動的方向,而只會讓你慢慢減速,直至速度為0。 如果想讓動畫更加真實,很多時候我們都需要考慮摩擦力,那如何用代碼實現呢? **(1)精確方法** 上面也說到,摩擦力是阻止你運動的力,這就意味著,可以用速度向量減去摩擦力。更準確地說,只能沿著速度向量的方向減去與摩擦力相等的大小,而不能分別在x、y軸上減小速度向量,也可以這樣理解,摩擦力必須與合速度相減,然后再根據減后的合速度分別求出x、y軸上的最終速度。 ![](https://box.kancloud.cn/e6345a1590dab43dcc5657ce3b20bb49_232x133.jpg) 如下方式: ``` var v = Math.sqrt( vx * vx + vy * vy ); var angle = Math.atan2(vy,vx); if(v > f){ v -= f; }else{ v = 0; }; vx = Math.cos(angle) * v; vy = Math.sin(angle) * v; ``` **(2)約等方法** 約等方法是指將x、y軸上的速度向量乘以一個百分數,一個接近0.9的系數能很好的模擬出摩擦力的效果。 ``` vx *= f; vy *= f; ``` 使用這種方法的好處就是不必去做條件判斷,但它只能無限接近于0,不過由于JavaScript的精度約束,最后的結果也會變為0。 在上面的反彈中,反彈系數也是用這種方法。 **總結** 介紹了如何檢測是否越界 越界后的處理方式:移除物體、重置物體、屏幕環繞、反彈 實現摩擦力的兩種方法:精度方法、約等方法 **附錄** **重要公式:** **(1)檢測是否越界** ``` if( object.x - object.width / 2 > right || object.x + object.width / 2 < left || object.y - object.height / 2 > bottom || object.y + object.height / 2 < top){} ``` **(2)摩擦力(精度方法)** ``` var v = Math.sqrt( vx * vx + vy * vy ); var angle = Math.atan2(vy,vx); if(v > f){ v -= f; }else{ v = 0; }; vx = Math.cos(angle) * v; vy = Math.sin(angle) * v; ``` **(3)摩擦力(約等方法)** ``` vx *= friction; vy *= friction; ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看