简体   繁体   中英

Pygame Rotate Rectangles within Surface

I'm having trouble keeping track of two rectangles that I blit onto a surface after I then rotate that surface. There are three rectangles draw on to the surface, representing the player. As the left and right keys are pressed, the rectangles all rotate around the centre point correctly. When the space bar is pressed, the "lights" are supposed to toggle on and off, however they are always redrawn at the bottom of the surface. Can you advise what I'm doing wrong?

import pygame
from pygame.locals import *


class Player(pygame.sprite.Sprite):
    height = 48
    width = 48
    colour = (30,144,255)

    def __init__(self):
        super(Player, self).__init__()
        self.surf = pygame.Surface((self.width, self.height))
        self.surf.fill((0, 0, 0))
        self.rect = self.surf.get_rect(center = (screen_width / 2, screen_height / 2))
        self.rotation = 0
        self.PlayerBody = pygame.draw.rect(self.surf, self.colour, Rect(15, 15, 20, 35))
        self.PlayerLightLeft = pygame.draw.rect(self.surf, (125, 0, 0), Rect(19, 45, 4, 4))
        self.PlayerLightRight = pygame.draw.rect(self.surf, (125, 0, 0), Rect(27, 45, 4, 4))
        self.lights = False
        self.lightsOnColour = (255, 0, 0)
        self.lightsOffColour = (125, 0, 0)
        self.lightsColour = self.lightsOffColour

    def update(self, pressedKey):
        if pressedKey == pygame.K_RIGHT:
            self.surf = pygame.transform.rotate(self.surf, -90)
        if pressedKey == pygame.K_LEFT:
            self.surf = pygame.transform.rotate(self.surf, 90)
        if pressedKey == pygame.K_SPACE:
            if self.lights:
                self.lightsColour = self.lightsOffColour
                self.lights = False
            else:
                self.lightsColour = self.lightsOnColour
                self.lights = True
        # always draws rectangles at the bottom of the surface
            self.PlayerLightLeft = pygame.draw.rect(self.surf, self.lightsColour, self.PlayerLightLeft)
            self.PlayerLightRight = pygame.draw.rect(self.surf, self.lightsColour, self.PlayerLightRight)


# initialize pygame
pygame.init()

screen_width = 800
screen_height = 600

screen = pygame.display.set_mode((screen_width, screen_height))
background = pygame.Surface(screen.get_size())
background.fill((255, 255, 255))

Player = Player()

running = True

while running:
    pressedKey = pygame.K_0
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                running = False
            pressedKey = event.key
        elif event.type == QUIT:
            running = False
    screen.blit(background, (0, 0))
    Player.update(pressedKey)
    screen.blit(Player.surf, Player.rect)

    pygame.display.flip()

# end of game, quit
pygame.quit()

Don't rotate the player surface when a key is presse, but add an attribute angle to the class Player , which stores the current angle of the surface.
Change the angle when the K_RIGHT or K_LEFT key is pressed.

class Player(pygame.sprite.Sprite):
    height = 48
    width = 48
    colour = (30,144,255)

    def __init__(self):
        super(Player, self).__init__()

        # [...]

        self.angle = 0

    def update(self, pressedKey):
        if pressedKey == pygame.K_RIGHT:
            self.angle = (self.angle - 90) % 360
        if pressedKey == pygame.K_LEFT:
            self.angle = (self.angle + 90) % 360
        # [...] 

this causes that the original surface is never changed and changing the "lights" will always work.

Create a rotated surface, which is rotated by Player.angle and blit the rotated surface:

rotSurf = pygame.transform.rotate(Player.surf, Player.angle)
screen.blit(rotSurf, Player.rect)

Brilliant @Rabbid76! Thank you!

Updated code below in case anyone has a similar problem.

import pygame
from pygame.locals import *


class Player(pygame.sprite.Sprite):
    height = 48
    width = 48
    colour = (30,144,255)

    def __init__(self):
        super(Player, self).__init__()
        self.surf = pygame.Surface((self.width, self.height))
        self.surf.fill((0, 0, 0))
        self.rect = self.surf.get_rect(center = (screen_width / 2, screen_height / 2))
        self.angle = 0
        self.PlayerBody = pygame.draw.rect(self.surf, self.colour, Rect(15, 15, 20, 35))
        self.PlayerLightLeft = pygame.draw.rect(self.surf, (125, 0, 0), Rect(19, 45, 4, 4))
        self.PlayerLightRight = pygame.draw.rect(self.surf, (125, 0, 0), Rect(27, 45, 4, 4))
        self.lights = False
        self.lightsOnColour = (255, 0, 0)
        self.lightsOffColour = (125, 0, 0)
        self.lightsColour = self.lightsOffColour

    def update(self, pressedKey):
        if pressedKey == pygame.K_RIGHT:
            self.angle = (self.angle - 90) % 360
        if pressedKey == pygame.K_LEFT:
            self.angle = (self.angle + 90) % 360
        if pressedKey == pygame.K_SPACE:
            if self.lights:
                self.lightsColour = self.lightsOffColour
                self.lights = False
            else:
                self.lightsColour = self.lightsOnColour
                self.lights = True
            self.PlayerLightLeft = pygame.draw.rect(self.surf, self.lightsColour, self.PlayerLightLeft)
            self.PlayerLightRight = pygame.draw.rect(self.surf, self.lightsColour, self.PlayerLightRight)


# initialize pygame
pygame.init()

screen_width = 800
screen_height = 600

screen = pygame.display.set_mode((screen_width, screen_height))
background = pygame.Surface(screen.get_size())
background.fill((255, 255, 255))

Player = Player()

running = True

while running:
    pressedKey = pygame.K_0
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                running = False
            pressedKey = event.key
        elif event.type == QUIT:
            running = False
    screen.blit(background, (0, 0))
    Player.update(pressedKey)
    rotSurf = pygame.transform.rotate(Player.surf, Player.angle)
    screen.blit(rotSurf, Player.rect)

    pygame.display.flip()

# end of game, quit
pygame.quit()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM