1. 程式人生 > >JS 中 Math 物件的【三角函式】的用法與實戰例子【打靶遊戲】 | Math.tan(), Math.cos(), Math.sin()

JS 中 Math 物件的【三角函式】的用法與實戰例子【打靶遊戲】 | Math.tan(), Math.cos(), Math.sin()

不少人在學習JavaScript的時候,都知道有那麼一個用於數學計算的類 Math,現在來簡單回顧以下,強大的 Math 類中,有哪些屬性和哪些方法:



如果用JS做前端的時候,就會發現跟 Math 類打交道比較少。但是如果用 Node.js  做後臺,或用 JS 寫遊戲的時候,Math 類就會無處不在,尤其是 random()、round()、abs()、ceil()、floor() 等方法很常用。本篇文章就來說說Math 類中的 sin()、cos()、tan() 這三個中學時期的數學重點究竟在JS中怎麼用。

一、理論部分

Math 類的 sin(x)、cos(x)、tan(x) 中的 x 引數是弧度,那麼,弧度是什麼?

最直觀地說,一個 60度 的角,可以用 60°來表示,也可以用 π / 3 (圓周率除以3)來表示;

同理,一個 90度 的角,可以用 90°來表示,也可以用 π / 2 (圓周率除以2)來表示;

還有,一個 180度 的角,可以用 180°來表示,也可以用 π 來表示。

那麼,【60°=π / 3】,90°=π / 2180°=π】,等號的左邊是度數,右邊是弧度

是否回憶起來一個這麼的例子,【 cos(60°) = cos(π/3 ) = 1/2 = 0.5

換句話說,一個角度,可以用度數來表示,也可以用弧度來表示。因為弧度更加符合計算機的計算模式,所以,Math 類的 sin(x)、cos(x)、tan(x) 中的 x 引數型別為弧度。


中學時期,我們知道,30、45、60、90、180 這些角度是特殊角,用弧度來表示相對容易,所以我們當時只背了這麼特殊角度的弧度值,然後理所當然地,慢慢地遺忘了弧度的概念,本文也不闡述弧度的概念,而是直接上一條公式,怎麼轉換度數為弧度值:

------------------------------------------------------------

弧度 = 角度 × π / 180

-----------------------------------------------

怎麼應用到程式碼裡面?

var angle = 60;    //假設角度為60度

var radian = angle * Math.PI / 180;    //計算出弧度

console.log( Math.cos(radian) );    //輸出cos 60度的值


用法就這麼簡單!理論部分到此結束,接下來講一點實戰部分。

二、實戰部分

需求:做一個小遊戲,有一把槍,一個靶子。槍頭的角度可以旋轉,靶子可以左右移動。現在要控制槍頭對準移動的靶子射擊,直到靶子射到爛為止。(下圖為簡單的圖形介面,紅點為錨點)


整一個小遊戲的開發都很簡單。只有在碰撞的實現上有點難度,傳統做法,每次一開槍,射出去的子彈一碰到靶子就視為打中靶子。

現在問題是,傳統做法中的子彈如果速度太快的情況下,碰撞檢測很大可能會失效(原理請自己翻閱遊戲開發相關書籍)。所以,不能用傳統做法來實現碰撞,那怎麼辦?想象一下,子彈的射擊速度非常快,一開槍,一瞬間,就會沿著瞄準的方向射去。我們只需要在開槍的時候,判斷靶子是否與射線碰撞了,如果碰撞則射中,否則射偏。


有了這個思路,就可以擴充套件了,加上槍頭的旋轉,和靶子的移動需求後,實現這個碰撞就需要用到三角函數了!為了便於理解,畫一下原理圖:



根據原理圖,我們可以細化程式碼實現的每一步的原理:

1、先計算出槍頭跟靶子的垂直方向距離(dui_bian)。

2、將槍頭的旋轉的角度轉化為弧度(radian)。

3、根據弧度(radian)和槍頭跟靶子的垂直方向距離(dui_bian)兩個已知量可以計算出武器真正射擊的子彈到目標位置的水平距離(lin_bian)。

4、通過槍頭跟靶子的垂直方向距離(dui_bian)武器真正射擊的子彈到目標位置的水平距離(lin_bian)與偏移值計算,可以得出一個座標(x, y)。

5、判斷座標(x, y)是否在靶子內部,是則視為打中靶子,否則就是打偏了。

有人要問,本文的內容不是關於三角函式的應用嗎?請注意第3步,確實是用到了三角函式的 Math.tan() 方法。

寫一個虛擬碼吧:

var lin_bian = dui_bian / Math.tan( radian );      //計算出武器真正射擊的子彈到目標位置的水平距離(lin_bian)

正文結束!

本文有誤之處,歡迎指點!