[英]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
是反余弦( arccos
或cos^-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 = -Cx
和Vy = -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.