[英]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.