Нарисуй на поверхности и вращайся с пигмеем - PullRequest
0 голосов
/ 30 октября 2018

Я пытаюсь имитировать в Python некоторое поведение, доступное в JS, с помощью команды context.rotate (angle).

У меня есть следующий код ниже: импорт пигмей импорт математики импорт 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()

Я рисую стрелку и хочу повернуть ее в зависимости от того, где находится мышь на экране. Конечно, я могу каждый раз перерисовывать свои строки, выполняя вычисления синуса, косинуса, но это больно. Я думал, что поверхности могут помочь мне здесь, и на самом деле, это работает с прямоугольником, который отлично вращается. Но рисование моих линий на поверхности не работает.

Итак, я полагаю, что неправильно понимаю, для чего нужны поверхности, или, может быть, я что-то неправильно кодирую, и есть лучший способ сделать это. Обратите внимание, что если я заменим rotated_surface на screen в моих инструкциях draw.line, стрелка будет нарисована на экране, но никогда не будет вращаться.

Есть мысли (помимо использования изображения / спрайта;))?

Спасибо

1 Ответ

0 голосов
/ 30 октября 2018

Проблема в том, что вы рисуете линии стрелок за пределами области поверхности. Верхние левые координаты каждой поверхности (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()

Я также попытался улучшить еще несколько вещей (см. Комментарии).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...