在表面绘制并使用pygame旋转

时间:2018-10-30 17:55:23

标签: python pygame

我正在尝试在Python中使用context.rotate(angle)命令模仿JS中可用的某些行为。

我在下面有以下代码: 导入pygame     导入数学     将numpy导入为np

pygame.init()

CLOCK = pygame.time.Clock()
RED = pygame.color.THECOLORS['red']
WHITE = pygame.color.THECOLORS['white']
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
screen_width, screen_height = screen.get_size()
surface = pygame.Surface((50, 50), pygame.SRCALPHA)
surface.fill((0, 0, 0))
rotated_surface = surface
rect = surface.get_rect()
ax = int(screen_width / 2)
ay = int(screen_height / 2)
angle = 0
print("Size of the screen ({}, {})".format(screen_width, screen_height))
print("Center of the screen ({}, {})".format(ax, ay))
myfont = pygame.font.SysFont("monospace", 12)

pygame.display.set_caption("Test rotate")

main_loop = True
amplifier = 200


def calculate_angle(mouse_position):
    dx = mouse_position[0] - ax
    dy = mouse_position[1] - ay
    return np.arctan2(dy,dx)

while main_loop:
    for event in pygame.event.get():
        keys = pygame.key.get_pressed()
        if event.type == pygame.QUIT or keys[pygame.K_ESCAPE]:
            main_loop = False

    pos = pygame.mouse.get_pos()
    angle = (calculate_angle(pos) * 180)/math.pi
    screen.fill((255,255,255))
    rotated_surface = pygame.transform.rotate(surface, -angle)
    rect = rotated_surface.get_rect(center = (ax, ay))
    screen.blit(rotated_surface, (rect.x, rect.y))
    pygame.draw.line(rotated_surface, WHITE, (ax,ay), (ax+20, ay), 1)
    pygame.draw.line(rotated_surface, WHITE, (ax+10,ay-10), (ax+20, ay), 1)
    pygame.draw.line(rotated_surface, WHITE, (ax+10,ay+10), (ax+20, ay), 1)
    pygame.display.update()
    CLOCK.tick(30)


pygame.quit()

我正在绘制一个箭头,并希望根据鼠标在屏幕上的位置来旋转它。当然,每次进行正弦,余弦计算时,我当然都可以重画线条,但这很痛苦。我认为曲面可以在这里为我提供帮助,实际上,它可以完美地旋转矩形。但是将线条画在表面上是行不通的。

因此,我想我误会了表面的用途,或者我编码有误,并且有更好的方法可以做到这一点。请注意,如果我在draw.line指令中用屏幕替换了rotated_surface,则箭头确实会在屏幕上绘制,但是永远不会旋转。

有什么想法(除了使用图片/精灵;)?

谢谢

1 个答案:

答案 0 :(得分:2)

问题是您在表面区域之外绘制了箭头线。每个表面的左上角坐标为(0,0),因此它们都有自己的(局部)坐标系。由于您使用屏幕的中心坐标绘制线,因此不会在可见的表面区域绘制箭头。

我会使用局部坐标在while循环之前将线条绘制到原始表面上,然后旋转它并在循环内部获得一个新的矩形。

import math
import pygame


pygame.init()

CLOCK = pygame.time.Clock()
GRAY = pygame.color.THECOLORS['gray50']
WHITE = pygame.color.THECOLORS['white']
screen = pygame.display.set_mode((800, 600))
screen_rect = screen.get_rect()  # A rect with the size of the screen.
surface = pygame.Surface((50, 50), pygame.SRCALPHA)
# surface.fill((0, 50, 150))  # Fill the surface to make it visible.
# Use the local coordinate system of the surface to draw the lines.
pygame.draw.line(surface, WHITE, (0, 0), (25, 0), 1)
pygame.draw.line(surface, WHITE, (0, 0), (25, 25), 1)
pygame.draw.line(surface, WHITE, (0, 0), (0, 25), 1)
# I rotate it so that the arrow is pointing to the right (0° is right).
surface = pygame.transform.rotate(surface, -135)
rect = surface.get_rect()
angle = 0
# If you're using Python 3.6+, you can use f-strings.
print(f"Size of the screen {screen.get_size()}")
print(f"Center of the screen {screen_rect.center}")

def calculate_angle(mouse_position):
    dx = mouse_position[0] - screen_rect.centerx
    dy = mouse_position[1] - screen_rect.centery
    return math.atan2(dy, dx)

main_loop = True
while main_loop:
    for event in pygame.event.get():
        # You shouldn't use `pygame.key.get_pressed` in the event loop.
        if (event.type == pygame.QUIT
            or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
            main_loop = False

    pos = pygame.mouse.get_pos()
    angle = math.degrees(calculate_angle(pos))
    screen.fill(GRAY)
    # Now just rotate the original surface and get a new rect.
    rotated_surface = pygame.transform.rotate(surface, -angle)
    rect = rotated_surface.get_rect(center=(screen_rect.center))
    screen.blit(rotated_surface, rect)
    pygame.display.update()
    CLOCK.tick(30)


pygame.quit()

我还尝试了其他一些改进(请查看评论)。