旋转代码是:
pygame.transform.rotate(surface, angle)
但我不想使用这些代码。我想写一个自己旋转表面的代码。我怎么能这样做?
答案 0 :(得分:0)
有许多不同的方法可以解决这个问题,但我把它解释为它应该按度旋转图像,逆时针旋转并根据需要调整图像大小。我还添加了crop
函数来消除过多的噪音。虽然,我的实现仍然存在问题,主要是aliased。要解决此问题,您可以查看this回答。
要旋转图像,首先需要将其转换为矩阵。这可以在pygame.surfarray.array3d
的帮助下完成,但它要求您安装numpy。然后我们需要一个rotation matrix和一个新矩阵,我们将所有像素从图像复制到。将位置矢量与旋转矩阵相乘时,您将获得一个新的位置矢量。所以我们所做的只是迭代图像的x-y坐标,将旋转矩阵应用于每个坐标,然后在新矩阵中的新坐标处添加像素。
import numpy as np
from math import sin, cos, radians
import pygame
pygame.init()
SIZE = WIDTH, HEIGHT = 720, 480
FPS = 30
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()
def crop(array, background=(0, 0, 0)):
rows, cols, _ = array.shape
left, right, top, bottom = 0, cols, 0, rows
for row in range(rows):
if not np.all(array[row] == background):
top = row
break
for row in range(rows - 1, top, -1):
if not np.all(array[row] == background):
bottom = row
break
np.transpose(array, axes=(1, 0, 2))
for col in range(cols):
if not np.all(array[col] == background):
left = col
break
for col in range(cols - 1, left, -1):
if not np.all(array[col] == background):
right = col
break
np.transpose(array, axes=(1, 0, 2))
return array[top:bottom+1, left:right+1]
def rotate(surface, angle):
rect = surface.get_rect()
width, height = surface.get_size()
image_array = pygame.surfarray.array3d(surface)
angle = radians(angle)
# Rotation matrix: https://en.wikipedia.org/wiki/Rotation_matrix
rotation = np.array(
((cos(angle), -sin(angle)),
(sin(angle), cos(angle))
), dtype=np.float16
)
# Rotates the corners of the image because the distance between 2 opposite corners will always be the furthest
# distance. This helps us calculate the new width and height of our new rotated image.
y_list, x_list = zip(*(
(position @ rotation) for position in (rect.topleft, rect.topright, rect.bottomleft, rect.bottomright)
))
min_x, min_y = min(x_list), min(y_list)
new_width = int(abs(min_x - max(x_list))) + 1
new_height = int(abs(min_y - max(y_list))) + 1
# Since we're rotating the image at the topleft corner and not in the center it'll be moved. By adding the offset
# we just move it back in place.
offset = -int(min_y), -int(min_x)
rotated_image_array = np.zeros(shape=(new_height, new_width, 3), dtype=np.uint8)
for row in range(height): # Not the newly calculated height, but the original image's height.
for col in range(width):
y, x = (row, col) @ rotation + offset
rotated_image_array[int(y), int(x)] = image_array[row, col]
rotated_image_array = crop(rotated_image_array)
return pygame.surfarray.make_surface(rotated_image_array)
def main():
running = True
original_image = pygame.Surface((200, 200))
original_image.fill(pygame.Color('red'))
image = original_image
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.key == pygame.K_1:
print('Reset image.')
image = original_image
elif event.key == pygame.K_2:
print('Starting rotating.')
time = pygame.time.get_ticks()
image = rotate(image, 20)
time = pygame.time.get_ticks() - time
print('Finished rotating in {:.4E} s.'.format(time / 1000))
screen.fill((255, 255, 255))
screen.blit(image, image.get_rect(center=(WIDTH // 2, HEIGHT // 2)))
pygame.display.update()
if __name__ == '__main__':
main()
答案 1 :(得分:-2)
import pygame
SIZE = 1000, 900
pygame.init()
screen = pygame.display.set_mode(SIZE)
a=0
done = False
screen.fill((0, 0, 0))
other1 = pygame.image.load("image.jpg")
screen.blit(other1, (0, 0))
while not done:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
a=a+90
other2 = pygame.transform.rotate(other1, a)
screen.blit(other2, (0, 0))
if event.key == pygame.K_RIGHT:
a=a-90
other2 = pygame.transform.rotate(other1, a)
screen.blit(other2, (0, 0))
screen.fill((0,0,0))
pygame.display.flip()