2. 使用正弦和餘弦來朝着某個角度移動

2. Sine on the Dotted Line: using sine and cosine to move at an angle

This post is about moving at a given angle, or: what use are sine and cosine anyway?

這篇帖子討論如何根據給定的角度進行運動,即:sin和cos函數如何使用?

Imagine you have a game where you control a spaceship in 2D, flying it around the screen. Positions on the screen in a 2D system use X and Y coordinates, so any movement on the screen is simply an alteration of the X and/or Y coordinates.

想象你在2D遊戲中控制一艘飛船在屏幕四周飛行。在2D系統中物體的位置使用x和y座標來表示,因此物體運動可以簡單地看作是其x/y座標的改變。

Let’s say that the spaceship has a fixed speed of 5 units per frame. If it’s pointing exactly to the right, that’s really easy to implement. You just move 5 units to the right, which means adding 5 to its X coordinate. InGreenfoot, this is:

我們假設飛船的速度固定爲每幀5個單位。如果讓它完全向右運動,那是很容易實現的。你只需要朝右移動5個單位,即給它的x座標值增加5。在Greenfoot中的代碼如下:

setLocation(getX() + 5, getY());

Similarly, if the spaceship is pointing upwards, the code is simple:

類似地,如果飛船向上運動,則代碼很簡單:
setLocation(getX(), getY() - 5);

(Remember that while in maths, positive values on the Y-axis are upwards, in computing they are generally downwards. Seethis note.) But what if the spaceship is pointing at a diagonal angle somewhere between right and upwards, let’s say 20 degrees from horizontal. How many units do you move then?

This problem is a common application of sine and cosine (which fall under the umbrella oftrigonometry). First, let’s draw a little diagram of our problem:

(請記住,在數學中Y軸的正方向是向上的,而在計算機中一般是朝下。)倘若飛船朝着右邊和上邊之間的某個角度斜線運動的話,比如距離水平方向20度運動,那麼需要移動多少單元呢?

這個問題涉及到sin和cos函數(三角學的內容)的基本使用。首先讓我們根據問題繪製一幅示意圖:

(NB: one thing computing does much better than mathematics is use meaningful variable names, and we will do the same.) So we have a starting position for the spaceship labelled (oldX, oldY) in the bottom left, and a position we want to move to, which will be (oldX + moveX, oldY + moveY). We know the angle (20 degrees in this example) and the distance in a straight line (5, our movement speed). What we need to know are the amounts to move: moveX and moveY.

(注意:計算機信息處理技術比數學好的一點在於能夠使用有意義的變量名稱,我們將利用這一點。)我們將飛船在左下方的初始位置標記爲(oldX, oldY) ,將移動的目標位置標記爲(oldX + moveX, oldY + moveY)。我們知道移動的角度(本例中是20度)和直線距離(5,即移動速度)。我們需要知道移動的座標分量:moveX and moveY。

Calculating the X and Y distances when moving at an angle is where sine and cosine come in useful. Sine and cosine are functions that take an angle, and give back a ratio between two sides of the corresponding right-angle triangle.No matter which two points you are interested in on an X-Y grid system, you can always form a right-angled triangle by drawing connecting lines parallel to the X and Y axes. This is key for much of the use of trigonometry in games and simulations.

sin和cos函數可用於計算斜向運動時的x和y距離分量。sin和cos函數根據給定的角度值返回相關直角三角形的兩條直角邊的比值。對於直角座標系中的任意兩個點,總是可以通過繪製平行於x軸和y軸的連線來形成一個直角三角形。這是遊戲及模擬開發中應用三角學的關鍵。

Back in maths class, you might have tried to memorise which sides sine and cosine refer to, using an acronym for the letter jumble SOHCAHTOA. Nowadays you can google it, or just go straight to wikipedia (score one for computing!). Here is the relevant sidebox from the current wikipedia article:

倘若回到數學課堂上,你或許得試着回憶一下sin和cos函數所涉及的是哪條邊。如今你可以用谷歌搜索一下,或者直接去維基百科查看。

A few notes. The hypotenuse is always the side that is opposite the right-angle: in all our diagrams, this is the slanted diagonal line between the two points we’re interested in. Of the other two sides, the adjacent is the one that is adjacent to the angle you’re interested in (labelled with the greek letter alpha,α, above), and the opposite is the one opposite the angle you’re interested in. So let’s match these two diagrams:

這裏有一些說明。斜邊始終是與直角相對的:在所有的示意圖中,它是連接兩個點的傾斜的對角線。鄰邊是與傾斜角(用希臘字母阿爾法α表示)相鄰的邊,對邊是於傾斜角相對的邊。讓我們將上面的兩幅圖匹配一下:

We can see that the hypotenuse is 5, and alpha is 20 degrees. We want to know the length of the adjacent side (the horizontal line, labelled moveX) and the opposite side (the vertical line, labelled moveY). We can adapt the equation from wikipedia to our setting:

圖中可以看到斜邊值是5,傾斜角的值是20度。我們想知道鄰邊(水平線,用moveX表示)和對邊(垂線,用moveY表示)的長度。可以使用如下公式計算:

\sin(20^\circ) = \displaystyle\frac{\textrm{moveY}}{5}

The cosine equation is similar, but rather than opposite divided by hypotenuse, it’s adjacent divided by hypotenuse, which in our setting is:

cos函數公式是相似的,只是不再用對邊除以斜邊,而是用鄰邊除以斜邊,公式如下:

\cos(20^\circ) = \displaystyle\frac{\textrm{moveX}}{5}

The tiniest bit of re-arrangement in each equation gives:

變形後的公式如下:

5 \times \cos(20^\circ) = \textrm{moveX}   ,    5 \times \sin (20^\circ) = \textrm{moveY}

You can bang that into your calculator right now (being wary ofdegrees vs radians), to get moveX=4.70 (to 2dp) and moveY=1.71 (to 2dp). You can always sanity check those figures using good old pythagoras: it should be the case that4.70^2 + 1.71^2 = 5^2 (or near enough, given that we’ve rounded).

現在可以直接進行計算了(主意角度與弧度的區別),結果爲moveX=4.70 (to 2dp),moveY=1.71 (to 2dp)。你可以通過勾股定理來檢查這些數據:4.70^2 + 1.71^2 = 5^2(考慮到四捨五入,結果近似即可)

That’s the calculation for our specific example, but we need to put it in our code. For this, we use Java’s standard maths libraries. Our code for moving at an angle is:

以上是對我們例子的計算,然而需要將它寫到代碼中去。我們需要用到java中的標準數學庫。以下是斜向運動的代碼:

double radians = Math.toRadians(getRotation());
double moveSpeed = 5;

double moveX = (int)(Math.cos(radians) * moveSpeed);
double moveY = (int)(Math.sin(radians) * moveSpeed);

setLocation(getX() + (int)moveX, getY() + (int)moveY);

For our rocket ship, that’s all you need to move at an angle. This function is so useful that in Greenfoot it’s now provided for you: you can callmove(5);, which will perform the above calculations for you, and move 5 units at the current rotation. But don’t feel cheated: understanding this use of sine and cosine is necessary for us to build more interesting games in future posts.

對於我們的飛船,以上代碼足以實現斜向運動。Greenfoot將以上代碼寫成了一個非常實用的函數:你可以調用move(5),它便會爲你執行以上的計算,即根據當前角度值的方向移動5個單位的距離。然而不要感覺受到欺騙:理解sin和cos的用法對於以後創建更加有趣的遊戲是非常必要的。

I’ve made a quick scenario to demonstrate it in action, combining the above code with the usual Greenfoot code for turning based on keyboard control. You canhave a play (use the left and right arrow keys to turn), and download the project to look at the code in Greenfoot .

我將製作一個簡單的遊戲劇本來進行演示,它將以上代碼和Greenfoot的基本代碼結合起來,並通過鍵盤來控制飛船的轉向。你可以試玩一下(使用左右方向鍵實現轉向),也可以將工程下載下來併到Greenfoot中查看源代碼。

發佈了0 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章