我正在 pygame 中制作游戏,我想旋转图像。pygame.transform.rotate
不断增加图像尺寸,所以我想也许精灵可以帮助我旋转图像。但问题更复杂,我想点击表面上的某个地方,我想让图像转向那个方向,所以对象可以进行无限次的旋转。有人可以给我解释一下如何做到这一点吗?
问问题
739 次
1 回答
2
图像改变尺寸
pygame 中的表面不能旋转;它们都有水平宽度和垂直高度。当您加载图像时,pygame 会创建一个水平宽度和垂直高度等于图像的 Surface。当您将图像旋转 45 度时,pygame 必须创建一个适合原始图像的新 Surface。新 Surface 的水平宽度和垂直高度必须是图像假设才能适合图像。
这应该是。如果您遇到的问题与碰撞检测有关,我建议您尝试其他形式的碰撞检测,例如圆形,或者继续使用矩形,但将其尺寸最小化。
向特定方向旋转
您可能应该使用矢量使图像转向您单击的位置。我通常创建自己的向量类,但pygame 有自己的向量类,除非你想创建自己的用于学习目的,否则应该使用它们。如果您不知道如何加、减、标量乘法、归一化和计算向量之间的角度,您可能需要阅读它,否则可能会有点复杂。无论如何,这是基本向量类的一小部分:
import math
class Vector2D(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector2D(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector2D(self.x - other.x, self.y - other.y)
def __mul__(self, other):
if isinstance(other, Vector2D):
# Vector multiplication
return self.x * other.x + self.y * other.y
else:
# Scalar multiplication
return Vector2D(self.x * other, self.y * other)
__radd__ = __add__
__rsub__ = __sub__
__rmul__ = __mul__
def length(self):
return (self.x ** 2 + self.y ** 2) ** (1/2)
def angle_to(self, other, radians=False):
"""Will return the angle between this vector and the other vector."""
if self.length() == 0 or other.length() == 0:
return 0
if not radians:
return (360 / (2 * math.pi)) * (math.atan2(other.y, other.x) - math.atan2(self.y, self.x))
else:
return math.atan2(other.y, other.x) - math.atan2(self.y, self.x)
def normalize(self):
if self.length() == 0:
return Vector2D(0, 0)
return Vector2D(self.x / self.length(), self.y / self.length())
然后我要做的是为您的图像创建一个具有属性position和original image的类。当您旋转图像时,pygame 会创建一个旋转的新图像。通过这样做,您的图像会丢失一些信息,因此会丢失一些质量。这就是为什么你总是应该旋转原始图像而不是旋转的副本。
class Player(pygame.sprite.Sprite):
def __init__(self, image_path, pos=(0, 0)):
super(Player, self).__init__()
self.original_image = pygame.image.load(image_path).convert() # REMEMBER TO CONVERT!
self.image = self.original_image # This will reference our rotated copy.
self.rect = self.image.get_rect()
self.position = Vector2D(*pos)
def update(self):
"""Updates the player's orientation."""
# Create a vector pointing at the mouse position.
mouse_position = Vector2D(*pygame.mouse.get_pos())
# Create a vector pointing from the image towards the mouse position.
relative_mouse_position = mouse_position - self.position
# Calculate the angle between the y_axis and the vector pointing from the image towards the mouse position.
y_axis = Vector2D(0, -1)
angle = -y_axis.get_angle(relative_mouse_position) # Negating because pygame rotates counter-clockwise.
# Create the rotated copy.
self.image = pygame.transform.rotate(self.original, angle).convert() # Angle is absolute value!
# Make sure your rect represent the actual Surface.
self.rect = self.image.get_rect()
# Since the dimension probably changed you should move its center back to where it was.
self.rect.center = self.position.x, self.position.y
一个简短的例子
import pygame
pygame.init()
BACKGROUND_COLOR = (0, 0, 0)
class Player(pygame.sprite.Sprite):
def __init__(self, position=(0, 0)):
super(Player, self).__init__()
self.original_image = pygame.Surface((32, 32))
pygame.draw.lines(self.original_image, (255, 255, 255), True, [(16, 0), (0, 31), (31, 31)])
self.image = self.original_image # This will reference our rotated copy.
self.rect = self.image.get_rect()
self.position = pygame.math.Vector2(*position)
def update(self):
"""Updates the players orientation."""
# Create a vector pointing at the mouse position.
mouse_position = pygame.math.Vector2(*pygame.mouse.get_pos())
# Create a vector pointing from the image towards the mouse position.
relative_mouse_position = mouse_position - self.position
# Calculate the angle between the y_axis and the vector pointing from the image towards the mouse position.
y_axis = pygame.math.Vector2(0, -1)
angle = -y_axis.angle_to(relative_mouse_position ) # Subtracting because pygame rotates counter-clockwise.
# Create the rotated copy.
self.image = pygame.transform.rotate(self.original_image, angle).convert() # Angle is absolute value!
# Make sure your rect represent the actual Surface.
self.rect = self.image.get_rect()
# Since the dimension probably changed you should move its center back to where it was.
self.rect.center = self.position.x, self.position.y
screen = pygame.display.set_mode((720, 480))
player = Player(position=(300, 250))
while True:
# Handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
# Update
player.update()
# Render
screen.fill(BACKGROUND_COLOR)
screen.blit(player.image, player.rect)
pygame.display.update()
于 2016-07-30T11:54:30.460 回答