How do I flip an image horizontally in pygame?

18,211

Solution 1

Add a pig orientation variable. Set it on key down, don't change it back on key up. Have movement rely on the moving_direction variable and the sprite displayed rely on the orientation variable.

Change blitme like so:

def blitme(self):
    if self.orientation == "Right":
        self.screen.blit(self.image, self.rect)
    elif self.orientation == "Left":
        self.screen.blit(pygame.transform.flip(self.image, False, True), self.rect)

Then you can have your key press logic like so:

elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                pig.moving_right = True
                pig.orientation = "Right"
            elif event.key == pygame.K_LEFT:
                pig.moving_left = True
                pig.orientation = "Left"
            elif event.key == pygame.K_UP:
                pig.moving_up = True
            elif event.key == pygame.K_DOWN:
                pig.moving_down = True

In this way you can separate display and movement logic.

Solution 2

pygame.transform.flip takes three arguments:

  1. The surface you want to flip
  2. A boolean to indicate that the surface should be flipped horizontally
  3. A boolean to indicate that the surface should be flipped vertically

To flip the surface only vertically pass True as the third argument:

flipped_surface = pygame.transform.flip(surface, False, True)

Regarding your specific problem, you could do something like this:

PIG_RIGHT = pygame.image.load('pig.png').convert()
PIG_LEFT = pygame.transform.flip(PIG_RIGHT, True, False)

pig = Pig(screen, PIG_RIGHT)  # Assign this image to `self.image`.
clock = pygame.time.Clock()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                pig.moving_right = True
                pig.image = PIG_RIGHT
            elif event.key == pygame.K_LEFT:
                pig.moving_left = True
                pig.image = PIG_LEFT

    screen.fill(blue_sky)

    pig.blitme()
    pig.update()

    pygame.display.flip()
    clock.tick(30)

You could also store the two suraces in your Pig class and switch the self.image in relation to the state of the self.moving_right, self.moving_left or self.direction attributes.

Share:
18,211
Katrina
Author by

Katrina

Updated on July 25, 2022

Comments

  • Katrina
    Katrina almost 2 years

    This is in pygame. How do I flip an image (lets say an image of a pig looking to the right) to look to the left when I press the left arrow key, and stay like that even if I don't press any keys or if I press the up and down arrow keys. Then how do I switch it back again to look to the right when I press the right arrow key and make it stay like that even if I don't press any key or if I press the up and down arrow keys.

    I know I have to use pygame.transform.flip(). But, I don't know how to put it in my code.

    This is the main game:

    import sys
    
    import pygame
    
    from pig import Pig
    
    pygame.init()
    
    screen_width = 800
    screen_height = 600
    
    screen = pygame.display.set_mode((screen_width, screen_height))
    pygame.display.set_caption("Flying Pig")
    
    blue_sky = 135, 206, 250
    brown = 139, 69, 19
    
    pig = Pig(screen)
    
    while True:
    
        # Accept events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
    
            # Keydown events
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    pig.moving_right = True
                elif event.key == pygame.K_LEFT:
                    pig.moving_left = True
                elif event.key == pygame.K_UP:
                    pig.moving_up = True
                elif event.key == pygame.K_DOWN:
                    pig.moving_down = True
    
            # Keyup events
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT:
                    pig.moving_right = False
                elif event.key == pygame.K_LEFT:
                    pig.moving_left = False
                elif event.key == pygame.K_UP:
                    pig.moving_up = False
                elif event.key == pygame.K_DOWN:
                    pig.moving_down = False
    
        screen.fill(blue_sky)
    
        pig.blitme()
        pig.update()
    
        pygame.display.flip()
    

    The pig class: (This is indented. I just don't know how to properly copy and paste my code here)

    import pygame 
    
    class Pig():
    
        def __init__(self, screen):
            """Initialize the pig and set its starting position."""
            self.screen = screen
    
            # Load the pig image and set pig and screen to rect.
            self.image = pygame.image.load('pig.png')
            self.rect = self.image.get_rect()
            self.screen_rect = screen.get_rect()
    
            # Start the pig at the bottom center of the screen.
            self.rect.centerx = self.screen_rect.centerx
            self.rect.bottom = self.screen_rect.bottom
    
            # Speed of the pig
            self.pig_speed = 1.5
            self.center = float(self.pig_speed)
    
            # Set a variable for each movement.
            self.moving_right = False
            self.moving_left = False
            self.moving_up = False
            self.moving_down = False
    
            self.direction = ['right', 'left']
    
        def update(self):
            """Update the position of the pig."""
    
            if self.rect.right <= self.screen_rect.right:
                if self.moving_right:
                    self.rect.centerx += self.pig_speed
    
            if self.rect.left > 0:
                if self.moving_left:
                    self.rect.centerx -= self.pig_speed
    
            if self.rect.top > 0:
                if self.moving_up:
                    self.rect.bottom -= self.pig_speed
    
            if self.rect.bottom <= self.screen_rect.bottom:
                if self.moving_down:
                    self.rect.bottom += self.pig_speed
    
        def blitme(self):
            """Draw the pig at its current location."""
            self.screen.blit(self.image, self.rect)
    
    • skrx
      skrx almost 7 years
      To format the code correctly, you have to select it in the submission window and press "Ctrl-K" (that adds four extra spaces before each line of code).
  • Katrina
    Katrina almost 7 years
    When I press the left arrow key it flips to the left (so the pig is looking to the left) but when I release it, it flips back to the original image (so the pig is now looking to the right again). How do I make it stay looking to the left even if i release the key?
  • skrx
    skrx almost 7 years
    You could do it like so: First load the original image and create the flipped version in the global scope. When the player presses the left key, set pig.image to the left image and when the player presses the right key set the pig.image back to the right image.
  • Katrina
    Katrina almost 7 years
    Can you elaborate more?
  • Saedeas
    Saedeas almost 7 years
    See my edit. I think it should clarify (note you may have to tweak things a little).
  • skrx
    skrx almost 7 years
    Side note: I recommend to add a pygame.time.Clock to limit the frame rate.
  • skrx
    skrx almost 7 years
    Also, note that constantly flipping or scaling a surface during the run time of the game is a lot more costly than creating the surfaces beforehand and to switch the self.image attribute.