使用精灵在Pygame中旋转图像 [英] Rotate an image in pygame using sprites

查看:162
本文介绍了使用精灵在Pygame中旋转图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用pygame制作游戏,我想旋转图像. pygame.transform.rotate不断增加图像尺寸,所以我认为精灵可以帮助我旋转图像.但是问题更加复杂,我想单击表面上的某个位置,并且希望图像朝那个方向旋转,因此对象可以进行无数次旋转.有人可以给我解释一下该怎么做吗?

I am making a game in pygame and I wanted to rotate an image. pygame.transform.rotate kept increasing the images dimensions so I thought that maybe sprites could help me to rotate an image. But the problem is more complex, I want to click somewhere on the surface and I want the image to turn into that direction, so there are infinite number of rotations the object could make. Can somebody please give me a explanation on how to do this?

推荐答案

图片更改尺寸

pygame中的表面无法旋转;它们都有水平宽度和垂直高度.当您加载图像时,pygame创建一个Surface,该Surface的水平宽度和垂直高度等于您的图像.当您将图片旋转45度时,pygame必须创建一个适合原始图片的新Surface.新的Surface的水平宽度和垂直高度必须是假设的图像,才能适合该图像.

Image changing dimensions

Surfaces in pygame can't be rotated; they all have a horizontal width and a vertical height. When you load your image pygame creates a Surface which has a horizontal width and a vertical height equal to your image. When you rotate your image 45 degrees pygame have to create a new Surface where your original image fits. The new Surface's horizontal width and vertical height has to be the images hypothenuse to be able to fit the image.

应该是这样.如果您遇到的问题与碰撞检测有关,我建议您尝试其他形式的碰撞检测,例如圆形,或者继续使用矩形,但是将其尺寸减小到最小.

This is supposed to be. If the problem you're having is about collision detection I'd recommend you to try other forms of collision detection like circular, or keep using rectangular but minimize it's size.

您可能应该使用矢量来使图像转到您单击的位置.我通常创建自己的向量类,但是 pygame有其自己的向量类,除非您出于学习目的创建自己的类,否则应使用该类.如果您不知道如何加,减,标量乘法归一化计算您可能要在其上读取的向量之间的角度,否则可能是有点复杂.无论如何,这只是基本向量类的一小部分:

You probably should use vectors to make the image turn to where you click. I usually create my own vector class, but pygame has its own Vector classes which should be used unless you want to create your own for learning purposes. If you don't know how add, subtract, scalar multiply, normalize and calculate angle between vectors you might want to read up on it, otherwise it might be a bit complicated. Anyway this is a small portion of a basic vector class:

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 原始图像.旋转图像时,pygame会创建一个旋转的新图像.这样做会使您的图像失去一些信息,从而失去一些质量.这就是为什么您始终应该旋转原始图像而不是旋转的副本的原因.

Then I would do is create a class for your image with attributes position and original image. When you're rotating the image, pygame creates a new image that's rotated. By doing this your image lose some information and therefore some quality. That's why you always should rotate the original image and not a rotated copy.

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()

这篇关于使用精灵在Pygame中旋转图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆