Pygame转换:按下按键即可旋转形状

时间:2019-03-26 13:55:56

标签: python 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的新手,所以希望获得任何详细的帮助。

2 个答案:

答案 0 :(得分:4)

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

然后,您可以将新的Surfacepygame.transform.rotate进行轮换。

这是一个简单的例子:

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

答案 1 :(得分:0)

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

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)