Search code examples
pygameflicker

PyGame Image Flickering


I'm making a catch game. But when the apples fall from the sky the apples are flickering. I tried to rewrite the falling system but it doesn't work. There's no rect override.

There is no double screen update or something like this. If I noticed right, it's only flickering when there's more than one apple on the screen.

import pygame
import time
import catch
import random

pygame.init()

pygame.display.set_caption("apple")

clock = pygame.time.Clock()
prev_time = time.time()
last_apple = time.time()
dt = 0

running = True
velocity = 1300
FPS = 60
appleSize = 50
WIDTH, HEIGHT = 1200, 800
screen = pygame.display.set_mode((WIDTH, HEIGHT))

catch = catch.Catch(487.5, 600, 225, 100,"images/catch.jpg", WIDTH, HEIGHT)


apples = []

appleImg = pygame.image.load("images/apple.png")
appleImg = pygame.transform.scale(appleImg, (appleSize, appleSize))
index = 0
apples.insert(index,[random.randint(0,WIDTH-appleSize),50])

def game(dt):
    global last_apple
    global index
    if(time.time() - last_apple >= 0.7):
        last_apple = time.time()
        index += 1
        apples.insert(index,[random.randint(0,WIDTH-appleSize),50])
    pressedKeys = pygame.key.get_pressed()
    if (pressedKeys[pygame.K_a]):
        catch.moveLeft(velocity * dt)
    if (pressedKeys[pygame.K_d]):
        catch.moveRight(velocity * dt)
    if (pressedKeys[pygame.K_w]):
        index += 1
        apples.insert(index,[random.randint(0,WIDTH-appleSize),50])

    for i, x in enumerate(apples):
        value = (velocity - 1000) * dt
        apples[i][1] += value
        col = pygame.Rect(apples[i][0],apples[i][1],appleSize,appleSize).colliderect(pygame.Rect(catch.x,catch.y+5,catch.w,catch.h))
        screen.blit(appleImg,(apples[i][0],apples[i][1]))
        if(col and apples[i][1]+appleSize <= catch.y+30) or (apples[i][1]+appleSize >= catch.height):
            apples.pop(i)

    catch.draw()


    pygame.draw.rect(screen,(30,30,30),pygame.Rect(0,HEIGHT-75,WIDTH,75))



while running:
    clock.tick(FPS)
    now = time.time()
    dt = now - prev_time
    prev_time = now

    for event in pygame.event.get():
        if (event.type == pygame.QUIT):
            running = False

    screen.fill((0, 157, 255))
    game(dt)

    pygame.display.update()

pygame.quit()



Solution

  • The problem is that you remove objects from the container apples while iterating. You have to iterate through a shallow copy of the list, when you want to remove objects from the list in the loop (e.g. for apple in apples[:]:). Also see How to remove items from a list while iterating?.

    def game(dt):
        # [...]
    
        catch_rect = pygame.Rect(catch.x, catch.y+5, catch.w, catch.h)
        value = (velocity - 1000) * dt
        for apple in apples[:]:
            apple[1] += value
            screen.blit(appleImg, apple)
            col = pygame.Rect(*apple, appleSize, appleSize).colliderect(catch_rect)
            if(col and apple[1]+appleSize <= catch.y+30) or (apple[1]+appleSize >= catch.height):
                apples.remove(apple)
    
        # [...]