1

私は pygame でゲームを作っていて、画像を回転させたいと思っていました。pygame.transform.rotate画像のサイズを増やし続けたので、スプライトが画像の回転に役立つのではないかと考えました。しかし、問題はもっと複雑です。表面のどこかをクリックしたいのですが、画像をその方向に向けたいので、オブジェクトが作成できる回転数は無限にあります。誰かがこれを行う方法について説明してもらえますか?

4

1 に答える 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())

次に、属性positionoriginal 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 に答える