Pygame变换:按键时旋转形状



我对 Pygame 相当陌生,似乎找不到一个可靠的答案。我有一个形状,特别是椭圆,我想左右旋转。键绑定将是ad,因为箭头键已经绑定到在x,y轴上左右移动。

我知道它涉及pygame.transform.rotate,但我似乎无法实现这项权利。

def main():
    #Setup basic variables and methods for pygame
    pygame.init()
    windowWidth = 800
    windowHeight = 700
    fps = 45
    clock = pygame.time.Clock()
    gameWindow = pygame.display.set_mode((windowWidth, windowHeight))
    surface = pygame.Surface((50,50))
    BLACK = (0, 0, 0)
    WHITE = (255, 255, 255)
    shipX = windowWidth/2
    shipY = windowWidth/2
    shipSpeed = 4
    while(True):
        pygame.draw.ellipse(gameWindow, WHITE, (shipX, shipY, 20, 30))
        #Monitor the FPS of the game
        clock.tick(fps)
        for event in pygame.event.get():
            # ________________________________________
            if event.type == pygame.QUIT:
                gameExit()
        rotate = 0
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_UP] and shipY > shipSpeed: shipY -= shipSpeed
        if pressed[pygame.K_DOWN] and shipY < windowHeight - shipSpeed - 20: shipY += shipSpeed
        if pressed[pygame.K_LEFT] and shipX > shipSpeed:shipX -= shipSpeed
        if pressed[pygame.K_RIGHT] and shipX < windowWidth - shipSpeed - 20: shipX += shipSpeed
        if pressed[ord('a')]: rotate = pygame.transform.rotate(surface, -20)
        if pressed[ord('d')]: rotate = pygame.transform.rotate(surface, 20)
        gameWindow.fill(BLACK)
        # 'flip' display - always after drawing...
        pygame.display.flip()

预期结果是形状将改变其角度,然后相应地移动。

同样,我对pygame很陌生,所以任何详细的帮助将不胜感激。

您的问题是直接在屏幕上绘制椭圆,但您应该在另一Surface上绘制椭圆。

然后,您可以使用pygame.transform.rotate旋转该新Surface

下面是一个简单的示例:

import pygame
import random
def main():
    pygame.init()
    screen = pygame.display.set_mode((500, 500))
    screen_rect = screen.get_rect()
    clock = pygame.time.Clock()
    surface = pygame.Surface((100, 200))
    surface.set_colorkey((2, 3, 4))
    surface.fill((2, 3, 4))
    rect = surface.get_rect(center=(100, 100))
    pygame.draw.ellipse(surface, pygame.Color('white'), (0, 0, 100, 200))
    angle = 0    
    dt = 0
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_UP]: rect.move_ip(0, -5)
        if pressed[pygame.K_DOWN]: rect.move_ip(0, 5)
        if pressed[pygame.K_LEFT]: rect.move_ip(-5, 0)
        if pressed[pygame.K_RIGHT]: rect.move_ip(5, 0)
        if pressed[pygame.K_a]: angle += 1
        if pressed[pygame.K_d]: angle -= 1
        rotated = pygame.transform.rotate(surface, angle)
        rect = rotated.get_rect(center=rect.center)
        rect.clamp_ip(screen_rect)
        screen.fill(pygame.Color('dodgerblue'))
        screen.blit(rotated, rect.topleft)
        pygame.display.update()
        dt = clock.tick(60)
if __name__ == '__main__':
    main()

请注意,我使用Rect来存储对象的位置,因为这样很容易围绕其中心旋转Surface(通过设置其center属性(,并确保Surface不会超出屏幕(通过使用clamp_ip(。

此外,重要的是始终旋转源Surface,而不是已经旋转的Surface。否则,你会得到失真。


请注意,我们这里有三件事:图像、位置和一些行为逻辑。每当你看到这些东西在一起时,考虑把它们放在一个班级里。Pygame已经为此提供了一个不错的课程,称为Sprite

下面是相同的示例,但基于Sprite

import pygame
import random
class Thingy(pygame.sprite.Sprite):
    def __init__(self, area):
        super().__init__()
        # image is what get's painted on the screen
        self.image = pygame.Surface((100, 200))
        self.image.set_colorkey((2, 3, 4))
        self.image.fill((2, 3, 4))
        pygame.draw.ellipse(self.image, pygame.Color('white'), (0, 0, 100, 200))
        # we keep a reference to the original image
        # since we use that for rotation to prevent distortions
        self.original = self.image.copy()
        # rect is used to determine the position of a sprite on the screen
        # the Rect class also offers a lot of useful functions
        self.rect = self.image.get_rect(center=(100, 100))
        self.angle = 0  
        self.area = area
    def update(self, events, dt):
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_UP]: self.rect.move_ip(0, -5)
        if pressed[pygame.K_DOWN]: self.rect.move_ip(0, 5)
        if pressed[pygame.K_LEFT]: self.rect.move_ip(-5, 0)
        if pressed[pygame.K_RIGHT]: self.rect.move_ip(5, 0)
        if pressed[pygame.K_a]: self.angle += 1
        if pressed[pygame.K_d]: self.angle -= 1
        # let's rotate the image, but ensure that we keep the center position
        # so it doesn't "jump around"
        self.image = pygame.transform.rotate(self.original, self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)
        self.rect.clamp_ip(self.area)
def main():
    pygame.init()
    screen = pygame.display.set_mode((500, 500))
    screen_rect = screen.get_rect()
    clock = pygame.time.Clock()
    sprites = pygame.sprite.Group(Thingy(screen_rect))
    dt = 0
    while True:
        # nice clean main loop
        # all game logic goes into the sprites
        # handle "global" events
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
        # update all sprites
        sprites.update(events, dt)
        # draw everything
        screen.fill(pygame.Color('dodgerblue'))
        sprites.draw(screen)
        pygame.display.update()
        dt = clock.tick(60)
if __name__ == '__main__':
    main()

你应该为你的对象创建一个类:

class myRect(pygame.Surface):
    def __init__(self, parent, xpos, ypos, width, height):
      super(myRect, self).__init__(width, height)
      self.xpos = xpos
      self.ypos = ypos
      self.parent = parent
    def update(self, parent):
      parent.blit(self, (self.xpos, self.ypos))
    def rotate(self, angle):
      #(your rotation code goes here)

最新更新