簡體   English   中英

如何旋轉三角形pygame

[英]how to rotate a triangle pygame

我在 pygame 中有這個三角形

triangle = pygame.draw.polygon(window, (210,180,140), [[x, y], [x -10, y -10], [x + 10, y - 10]], 5)

我需要向鼠標旋轉,非常像這個 gif 中的中心箭頭: http : //i.stack.imgur.com/yxsV1.gif Pygame 沒有用於旋轉多邊形的內置函數,因此我需要手動將三個點移動到一個圓圈中,最低點 [x,y] 指向鼠標的坐標。 我擁有的變量是:

三角形的中心和我希望它旋轉的圓之間的距離(即半徑)

從中心到鼠標坐標的距離

三角形 [x,y] 的最低點與另外兩條邊的坐標

有了這些信息,如何使用三角函數旋轉三角形的所有三個邊,使底點始終面向鼠標位置?

編輯:這是我到目前為止所得到的,但它只能沿着對角線來回移動三角形而不是旋轉。

    def draw(self):
        curx,cury = cur
        #cur is a global var that is mouse coords
        angle = math.atan2(self.x - curx, self.y - cury)
        distance = math.sqrt(200 - (200 * math.cos(angle)))
        x = self.x + distance
        y = self.y + distance
        triangle = pygame.draw.polygon(window, (210,180,140), [[x, y], [x - 10,y - 10], [x + 10,y - 10]], 5)

編輯:今天早上再次考慮這個問題,因為多邊形是三角形,所以還有另一種方法可以做到這一點。 此外,數學可能更容易理解,並且每個點需要的計算更少。

設 Cx 和 Cy 為內接三角形的圓的中心。 我們可以使用參數方程來描述圓的方程:

 F(t) = { x = Cx + r * cos(t)
        { y = Cy + r * sin(t)

其中r是圓的半徑, t表示沿圓的角度。

使用這個方程,我們可以使用接觸圓的點來描述三角形,在這種情況下,我們將使用t = { 0, 3 * pi / 4, 5 * pi / 4 }作為我們的點。

我們還需要計算旋轉三角形所需的角度,以便t = (0)處的點位於從(Cx, Cy)到鼠標位置的直線上。 兩個(歸一化)向量之間的角度可以通過以下方式計算:

t = acos(v1 . v2) = acos(<x1, y1> . <x2, y2>) = acos(x1 * x2 + y1 * y2)

哪里. 表示點積, acos是反余弦( arccoscos^-1 )。

從這兩個方程我們可以很容易地創建一個 python 函數,給定三角形/圓的中心、圓的半徑和鼠標的位置,返回一個表示三角形 xy 坐標的元組列表。 (例如,中心和鼠標位置是(x, y)形式的元組)

def get_points(center, radius, mouse_position):
    # calculate the normalized vector pointing from center to mouse_position
    length = math.hypot(mouse_position[0] - center[0], mouse_position[1] - center[1])
    # (note we only need the x component since y falls 
    # out of the dot product, so we won't bother to calculate y)
    angle_vector_x = (mouse_position[0] - center[0]) / length

    # calculate the angle between that vector and the x axis vector (aka <1,0> or i)
    angle = math.acos(angle_vector_x)

    # list of un-rotated point locations
    triangle = [0, (3 * math.pi / 4), (5 * math.pi / 4)]

    result = list()
    for t in triangle:
        # apply the circle formula
        x = center[0] + radius * math.cos(t + angle)
        y = center[1] + radius * math.sin(t + angle)
        result.append((x, y))

    return result

像這樣調用這個函數:

from pprint import pprint
center = (0,0)
radius = 10
mouse_position = (50, 50)
points = get_points(center, radius, mouse_position)
pprint(points)

產生:

[(7.071067811865475, 7.0710678118654755),
 (-10.0, 1.2246467991473533e-15),
 (-1.8369701987210296e-15, -10.0)]

這是三角形的三個點 (x, y)。

我將保留下面的原始方法,因為這是現代計算機圖形系統(OpenGL、DirectX 等)的處理方式。


圍繞任意多邊形的質心旋轉是三個不同矩陣操作的序列,平移對象使質心位於原點 (0,0),應用旋轉,然后平移回原始位置。

計算任意 n 邊形的質心可能超出了此處答案的范圍(Google 會提供許多選項),但可以使用方格紙完全手工完成。 稱該點為C

為了簡化操作,並使用簡單的矩陣乘法來應用所有變換,我們使用所謂的齊次坐標,其形式如下:

    [ x ]
p = | y |
    [ 1 ]

對於二維坐標。

    [ Cx ]
C = | Cy |
    [ 1  ]

平移矩陣的一般形式為:

    [ 1  0  Vx ]
T = | 0  1  Vy |
    [ 0  0  1  ]

其中<Vx, Vy>表示平移向量。 由於平移的目標是將質心C移動到原點,因此Vx = -CxVy = -Cy 逆向平移T'就是Vx = Cx, Vy = Cy

接下來需要旋轉矩陣。 r為所需的順時針旋轉角度, R為旋轉矩陣的一般形式。 然后,

    [  cos(r)  sin(r)  0 ]
R = | -sin(r)  cos(r)  0 |
    [  0       0       1 ]

因此,最終的變換矩陣為:

       [ 1  0  -Cx ]   [  cos(r)  sin(r)  0 ]   [ 1  0  Cx ]
TRT' = | 0  1  -Cy | * | -sin(r)  cos(r)  0 | * | 0  1  Cy |
       [ 0  0   1  ]   [    0       0     1 ]   [ 0  0  1  ]

簡化為:

[ cos(r)  sin(r)  cos(r)*Cx-Cx+Cy*sin(r) ]
|-sin(r)  cos(r)  cos(r)*Cy-Cy-Cx*sin(r) |
[  0       0                1            ]

將此應用於點p = (x,y)我們得到以下等式:

p' = { x' =  Cx*cos(r)-Cx+Cy*sin(r)+x*cos(r)+y*sin(r)
     { y' = -Cx*sin(r)+Cy*cos(r)-Cy-x*sin(r)+y*cos(r)

在 Python 中:

def RotatePoint(c, p, r):
    x = c[0]*math.cos(r)-c[0]+c[1]*math.sin(r)+p[0]*math.cos(r)+p[1]*math.sin(r)
    y = -c[0]*math.sin(r)+c[1]*math.cos(r)-c[1]-p[0]*math.sin(r)+p[1]*math.cos(r)
    return (x, y)

輸入所有內容后,我意識到您的對象可能已經以原點為中心,在這種情況下,上面的函數簡化為x=p[0]*math.cos(r)+p[1]*math.sin(r) y=p[0]*math.sin(r)+p[1]*math.cos(r)


我在這里對 Wolfram Alpha 充滿信心,而不是用手將所有東西相乘。 如果有人注意到任何問題,請隨時進行編輯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM