简体   繁体   English

如何旋转三角形pygame

[英]how to rotate a triangle pygame

I have this triangle in pygame我在 pygame 中有这个三角形

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

that i need to rotate towards the mouse, very much like the center arrow in this gif: http://i.stack.imgur.com/yxsV1.gif .我需要向鼠标旋转,非常像这个 gif 中的中心箭头: http : //i.stack.imgur.com/yxsV1.gif Pygame doesn't have a built in function for rotating polygons, so I'll need to manually move the three points in a circle, with the lowermost point [x,y] pointing towards the coords of the mouse. Pygame 没有用于旋转多边形的内置函数,因此我需要手动将三个点移动到一个圆圈中,最低点 [x,y] 指向鼠标的坐标。 The variables I have are:我拥有的变量是:

the distance between the center of the triangle and the circle i want it to rotate along (ie the radius)三角形的中心和我希望它旋转的圆之间的距离(即半径)

the distance from the center to the mouse coordinates从中心到鼠标坐标的距离

the coordinates of the lowermost point of the triangle [x,y] and the other two sides三角形 [x,y] 的最低点与另外两条边的坐标

with this information, how can I use trigonometry to rotate all three sides of the triangle so that the bottom point allways faces the mouse position?有了这些信息,如何使用三角函数旋转三角形的所有三个边,使底点始终面向鼠标位置?

EDIT: this is what I've got so far, but it only manages to move the triangle back and forth along a diagonal instead of rotating.编辑:这是我到目前为止所得到的,但它只能沿着对角线来回移动三角形而不是旋转。

    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)

Edit: Thinking about this again this morning there's another way to do this since the polygon is a triangle.编辑:今天早上再次考虑这个问题,因为多边形是三角形,所以还有另一种方法可以做到这一点。 Also the math is potentially easier to understand, and it requires less calculation for each point.此外,数学可能更容易理解,并且每个点需要的计算更少。

Let Cx and Cy be the center of the circle inscribing the triangle.设 Cx 和 Cy 为内接三角形的圆的中心。 We can describe the equation of a circle using the parametric equation:我们可以使用参数方程来描述圆的方程:

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

Where r is the radius of the circle, and t represents the angle along the circle.其中r是圆的半径, t表示沿圆的角度。

Using this equation we can describe the triangle using the points that touch the circle, in this case we'll use t = { 0, 3 * pi / 4, 5 * pi / 4 } as our points.使用这个方程,我们可以使用接触圆的点来描述三角形,在这种情况下,我们将使用t = { 0, 3 * pi / 4, 5 * pi / 4 }作为我们的点。

We also need to calculate the angle that we need to rotate the triangle so that the point that was at t = (0) is on a line from (Cx, Cy) to the mouse location.我们还需要计算旋转三角形所需的角度,以便t = (0)处的点位于从(Cx, Cy)到鼠标位置的直线上。 The angle between two (normalized) vectors can be calculated by:两个(归一化)向量之间的角度可以通过以下方式计算:

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

where .哪里. represents the dot product, and acos is the inverse cosine ( arccos or cos^-1 ).表示点积, acos是反余弦( arccoscos^-1 )。

From these two equations we can easily create a python function which, given the center of the triangle/circle, the radius of the circle, and the location of the mouse, returns a list of tuples representing the xy coordinates of the triangle.从这两个方程我们可以很容易地创建一个 python 函数,给定三角形/圆的中心、圆的半径和鼠标的位置,返回一个表示三角形 xy 坐标的元组列表。 (For the example the center and mouse position are tuples of the form (x, y) ) (例如,中心和鼠标位置是(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

Calling this function like this:像这样调用这个函数:

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

produces:产生:

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

which is the three points (x, y) of the triangle.这是三角形的三个点 (x, y)。

I'm going to leave the original method below, since it's the way that modern computer graphics systems (OpenGL, DirectX, etc.) do it.我将保留下面的原始方法,因为这是现代计算机图形系统(OpenGL、DirectX 等)的处理方式。


Rotation about the centroid of a arbitrary polygon is a sequence of three distinct matrix operations, Translating the object so that the centroid is at the origin (0,0), applying a rotation, and translating back to the original position.围绕任意多边形的质心旋转是三个不同矩阵操作的序列,平移对象使质心位于原点 (0,0),应用旋转,然后平移回原始位置。

Calculating the centroid for an arbitrary n-gon is probably outside the scope of an answer here, (Google will reveal many options), but it could be done completely by hand using graph paper.计算任意 n 边形的质心可能超出了此处答案的范围(Google 会提供许多选项),但可以使用方格纸完全手工完成。 Call that point C .称该点为C

To simplify operations, and to enable all transformations to be applied using simple matrix multiplications, we use so called Homogeneous coordinates , which are of the form:为了简化操作,并使用简单的矩阵乘法来应用所有变换,我们使用所谓的齐次坐标,其形式如下:

    [ x ]
p = | y |
    [ 1 ]

for 2d coordinates.对于二维坐标。

Let

    [ Cx ]
C = | Cy |
    [ 1  ]

The general form of the translation matrix is:平移矩阵的一般形式为:

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

Where <Vx, Vy> represents the translation vector.其中<Vx, Vy>表示平移向量。 Since the goal of the translation is to move the centroid C to the origin, Vx = -Cx and Vy = -Cy .由于平移的目标是将质心C移动到原点,因此Vx = -CxVy = -Cy The inverse translation T' is simply Vx = Cx, Vy = Cy逆向平移T'就是Vx = Cx, Vy = Cy

Next the rotation matrix is needed.接下来需要旋转矩阵。 Let r be the desired clockwise rotation angle, and R be the general form of the rotation matrix.r为所需的顺时针旋转角度, R为旋转矩阵的一般形式。 Then,然后,

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

The final transformation matrix is therefore:因此,最终的变换矩阵为:

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

Which simplifies to:简化为:

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

Applying this to a point p = (x,y) we obtain the following equation:将此应用于点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)

In Python:在 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)

After typing all that I realize that your object may already be centered on the origin, in which case the function above simplifies to x=p[0]*math.cos(r)+p[1]*math.sin(r) and y=p[0]*math.sin(r)+p[1]*math.cos(r)输入所有内容后,我意识到您的对象可能已经以原点为中心,在这种情况下,上面的函数简化为x=p[0]*math.cos(r)+p[1]*math.sin(r) y=p[0]*math.sin(r)+p[1]*math.cos(r)


I put some faith in Wolfram Alpha here, rather than multiplying everything out by hand.我在这里对 Wolfram Alpha 充满信心,而不是用手将所有东西相乘。 If anyone notices any issues, feel free to make the edit.如果有人注意到任何问题,请随时进行编辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM