Search code examples
pythonpygamelogicsprite

How do I flip this sprite in pygame?


EDIT: I've now flipped the sprite, but when the animation plays on the flipped sprite, it has a black background instead of blending in with the major background. Just updated my code to the current situation. (2/8/2021)

I'm trying to flip a sprite in pygame, for example, I don't want them running left but looking right, which is what is happening right now.

The part that is giving me issues is the second comment that says ISSUES.

Here is my code (spritesheet is a class that transforms the image into a surface):

import pygame
import os
import sys
import random
from pygame.locals import *
import spritesheet
import time

pygame.init()

clock = pygame.time.Clock()
FPS = 60
prev_time = time.time()

pygame.display.set_caption('Platformer')

BG_COLOR = (50, 50, 50)
BLACK = (0, 0, 0)

WIN_SIZE = [1920,1080]

WIN = pygame.display.set_mode((WIN_SIZE[0], WIN_SIZE[1]), 0, 32)

# CONFIGURING Animations

IDLE_INDEX = 0

RUN_INDEX = 0

moving_right = False
moving_left = False

lookingRight = True

speed = 4
animation_tick = 8

player_location = [50, 50]
player_y_momentum = 0

player_rect = pygame.Rect(player_location[0] + 155, player_location[1] + 140, 70, 133)

def retrieve_list(animType, image):
    if animType == "idle":
        IDLE_FRAMES = []
        IDLE_STEPS = 9
        sprite_sheet = spritesheet.SpriteSheet(image)
        for step in range(IDLE_STEPS):
            newFRAME = sprite_sheet.get_image(step, 120, 80, 3.5, BLACK)
            IDLE_FRAMES.append(newFRAME)
        return IDLE_FRAMES
    if animType == "run":
        RUN_FRAMES = []
        RUN_STEPS = 9
        sprite_sheet = spritesheet.SpriteSheet(image)
        for step in range(RUN_STEPS):
            newFRAME = sprite_sheet.get_image(step, 120, 80, 3.5, BLACK)
            RUN_FRAMES.append(newFRAME)
        return RUN_FRAMES

sprite_sheet_img_IDLE = pygame.image.load('Spritesheets/Outline/120x80_PNGSheets/_Idle.png')
sprite_sheet_img_RUN = pygame.image.load('Spritesheets/Outline/120x80_PNGSheets/_Run.png')
IDLE_FRAMES = retrieve_list("idle", sprite_sheet_img_IDLE)
RUN_FRAMES = retrieve_list("run", sprite_sheet_img_RUN)
currentANIMATION = "idle"
playingAnim = None

while True:

    clock.tick(FPS)
    now = time.time()
    dt = now - prev_time
    prev_time = now
    WIN.fill(BG_COLOR)

    if currentANIMATION == "idle":
        if player_location[1] > WIN_SIZE[1] - IDLE_FRAMES[IDLE_INDEX].get_height():
            player_y_momentum = -player_y_momentum
        else:
            player_y_momentum += 0.2
        player_location[1] += player_y_momentum
    elif currentANIMATION == "run":
        if player_location[1] > WIN_SIZE[1] - RUN_FRAMES[RUN_INDEX].get_height():
            player_y_momentum = -player_y_momentum
        else:
            player_y_momentum += 0.2
        player_location[1] += player_y_momentum

    if moving_right:
        currentANIMATION = "run"
        if not lookingRight:
            lookingRight = True
        WIN.fill(BG_COLOR)
        playingAnim = WIN.blit(RUN_FRAMES[RUN_INDEX], (player_location[0], player_location[1]))
        player_location[0] += speed
    if moving_left:
        currentANIMATION = "run"
        if lookingRight:
            lookingRight = False
        leftFrame = pygame.transform.flip(RUN_FRAMES[RUN_INDEX], True, False)
        WIN.fill(BG_COLOR)
        playingAnim = WIN.blit(leftFrame, (player_location[0], player_location[1]))
        player_location[0] -= speed
    elif moving_right != True and moving_left != True:
        currentANIMATION = "idle"
        WIN.fill(BG_COLOR)
        playingAnim = WIN.blit(IDLE_FRAMES[IDLE_INDEX], (player_location[0], player_location[1]))


    player_rect.x = player_location[0] + 155
    player_rect.y = player_location[1] + 140

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_RIGHT or event.key == ord('d'):
                moving_right = True
            if event.key == K_LEFT or event.key == ord('a'):
                moving_left = True
        if event.type == KEYUP:
            if event.key == K_RIGHT or event.key == ord('d'):
                moving_right = False
            if event.key == K_LEFT or event.key == ord('a'):
                moving_left = False

    pygame.display.update()
    if animation_tick == 8:  # change 20 to how ever many ticks in between animation frames
        if currentANIMATION == "idle":
            if IDLE_INDEX < 8:
                IDLE_INDEX += 1
            else:
                IDLE_INDEX = 0
        if currentANIMATION == "run":
            if RUN_INDEX < 8:
                RUN_INDEX += 1
            else:
                RUN_INDEX = 0
        animation_tick = 0  # reset tick back to 0 after changing frame
    else:
        animation_tick += 1  # add 1 each iteration of the while loop

Here are the spritesheets if you want to replicate my situation: running spritesheet: enter image description here

idle spritesheet: enter image description here

I've tried flipping the original surface, but then the image gets messed up with black around it, and it doesn't play the animation.


Solution

  • Forgot to add .convert_alpha() when I was flipping the image. Apparently when the image is flipped it recreates the black rectangle.