【问题标题】:Draw in a surface and rotate with pygame绘制表面并使用 pygame 旋转
【发布时间】:2018-10-30 17:55:22
【问题描述】:

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

我有以下代码:

import pygame
import math
import numpy as 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 指令中将 rotate_surface 替换为 screen,箭头会在屏幕上绘制,但永远不会旋转。

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

谢谢,

【问题讨论】:

  • 在这件事上给我打电话,但我认为你应该在你把事情放到表面之后做pygame.transformA Surface transform is an operation that moves or resizes the pixels. 表示必须先转换像素。返回值为All these functions take a Surface to operate on and return a new Surface with the results.。这意味着您在该表面上粘贴的任何内容都是转换后的。所以把它移到pygame.draw.line 之后看看它是否有效?
  • 感谢 Torxed 的建议。我已经尝试过了,但它不起作用。当鼠标在屏幕上移动时,只有黑色矩形出现旋转。

标签: python pygame


【解决方案1】:

问题是您在表面区域之外绘制箭头线。每个表面的左上角坐标为 (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()

我还尝试改进了一些东西(查看 cmets)。

【讨论】:

  • 当然!坐标系:) 谢谢skrx,非常感谢。我现在明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
  • 2013-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多