Pygame Screen breaks when moving line across screen

I am trying to move this image:

enter image description here

On my PyGame screen, right to left and back again. However, as the image moves, every second or so, I get screen tearing flickering, making its way like this:

enter image description here

The code I'm using is a loop like this:

screen.blit(img, (x,y))
pygame.update((x,y),(w,h))
pygame.draw.rect(screen,(0,0,0),((x,y),(w,h)))

      

So far I have tried to solve the following problem:

Using flags HWSURFACE

, FULLSCREEN

, DOUBLEBUF

when you create a screen, it is not affected, I also adjusted my .update(rect)

on .flip()

(as it is recommended for use DOUBLEBUF

?)

Sharing memory between GPU and CPU (I'm running this on a raspberry pi 2), I tried to give both more memory and no change.

Setting clock.tick to throttle the refresh rate to 60 FPS (higher and lower), this ironed out some of the tearing, but not all

Adjusting the size of each increment to the left or right, making smaller increments, results in less tearing, but also less speed. (Can't be too slow)

Blitting a new black surface instead of drawing a black rectangle over the previous position (while moving the image to make sure there is no trace behind it) when I read somewhere, which is blit

better supported HWSURFACE

than painting, although I can't confirm it? - It had no effect

If anyone has other solutions that can improve the situation, I would be grateful.

I would rather not switch from PyGame to anything else (like pyglet) as I've used quite a few PyGame implementations so far, but I'm open to suggestions.

Greetings

EDIT

Relevant code as requested:

if scanner == True:
    clocker.tick(clockspeed)
    if x < 11:
        slower = 3
        if firstTime == True:
            img.set_alpha(int(x * 25))
            newSurf.set_alpha(int(x * 25))
            screen.blit(newSurf,(xText,35))
            pygame.display.update((xText,35),((xText + newSurf.get_width()),(50 + newSurf.get_height())))
            img.set_alpha(255)

    elif x > (divider - 15):
        slower = 3
    else:
        slower = 0
        firstTime = False

    screen.blit(img, ((xStart - (x * increment) + slower),100))
    pygame.display.update(((xStart - (x * increment) + slower),100),(95,450))
    pygame.draw.rect(screen, (0,0,0), (((xStart - (x * increment) + slower),100),(95,450)))

      

The variable slower

should provide a sense of inertia as the boom reaches the far left and right sides of its sweep at a speed that it will slow down slightly.

The variable is firstTime

meant to fade in the panel when it first appears.

There is another loop just below this that is very similar, but views the image in reverse.

+3


source to share


1 answer


this break is simply the result of displaying the screen. The next position for the line is rendering, while the previous position is being drawn. If the refresh rate and screen refresh rate are synchronous, this problem goes away. But since this is almost impossible to do accurately, I would suggest that you have your program take the path that the PICO-8 controls, waiting for the screen refresh to complete before changing the screen buffer to prevent tearing. I'm not sure if there is a method to wait for the screen refresh to complete, but if there is, the sequence should go:update back buffer → wait for screen to stop being drawn → flip buffers → screen is drawn again



Refreshing is when the screen is drawn from left to right, top to bottom, pixel by pixel. This is because the triple bus-to-screen connection only allows the brightness for one pixel at a time to come from the screen memory, so each one is drawn sequentially. The gap comes from the memory changing halfway through the update, so the line moves halfway down the screen.

0


source







All Articles