Search code examples
windowrendererpysdl2

PySDL2: Renderer or Window Surface for handling colors and text?


My question concerns the sdl2.ext.Renderer mainly, and has to do with a problem I've encountered when trying to render sprites on a sdl2.ext.Window surface.

So right now, for coloring my background on an SDL2 Window, I make the following call:

White = sdl2.ext.Color(255,255,255)

    class Background(sdl2.ext.SoftwareSpriteRenderSystem):
        def __init__(self,window):
            super(Background,self).__init__(window)
            sdl2.ext.fill(self.surface,White)

This colors the surface of the Window with a white background. However, I also want to display text on the screen. This is done by creating a TextureSprite using the from_text method of the sdl2.ext.SpriteFactory class as follows:

Renderer = sdl2.ext.Renderer(W) # Creating Renderer

ManagerFont = sdl2.ext.FontManager(font_path = "OpenSans.ttf", size = 14) # Creating Font Manager

Factory = sdl2.ext.SpriteFactory(renderer=Renderer) # Creating Sprite Factory

Text = Factory.from_text("Unisung Softworks",fontmanager=ManagerFont) # Creating TextureSprite from Text

Renderer.copy(Text, dstrect= (0,0,Text.size[0],Text.size[1])) # Resizing the Texture to fit the text dimensions when rendered

The problem occurs when the event loop is run.

 running = True
    while running:
        events = sdl2.ext.get_events()
        for event in events:
            if event.type == sdl2.SDL_QUIT:
                running = False
                break
            if event.type == sdl2.SDL_MOUSEBUTTONDOWN:
                pass

        Renderer.copy(Text, dstrect= (0,0,Text.size[0],Text.size[1]))
        Renderer.present() # Problem 1
        W.refresh() # Problem 2
    return 0

Full Example Paste

When both Renderer.present() and W.refresh() are called, I get a flickering effect from the screen. This seems to be because the Renderer overwrites the White colored Window surface, which then gets colored over again by the Window.refresh() call. This then repeats, resulting in a flickering mess.

I would like to know what I can do to solve this problem? Should I even be using both Window.refresh() and the Renderer at the same time? Is there a way to let one render the other? (Renderer renders background for example). If anyone can help me out, that would be great.


Solution

  • The problem is that you are using Window.refresh() along with a SDL_Renderer and a SoftwareSpriteSystem with SDL_Texture objects.

    As outlined in the PySDL2 docs, this is likely to break (since software surface buffers get mixed with hardware-based textures) and you should avoid it. If you want to color the window background, you should use Renderer.clear(White) instead of your Background class and call it before copying the text via Renderer.copy():

    Renderer.clear(White)
    Renderer.copy(Text, dstrect= (0,0,Text.size[0],Text.size[1]))
    Renderer.present()
    

    Do not forget to change the color for your FontManager. By default it uses a white text color, so you should change it to e.g. your Red color:

    ManagerFont = sdl2.ext.FontManager(font_path = "OpenSans.ttf", size = 14, color=Red)