Skip to content

Dirty rects (3079)ย #1560

Open
Open
@GalacticEmperor1

Description

@GalacticEmperor1

Issue โ„–3079 opened by dahsa333 at 2022-03-14 22:06:25

Hello! I'm trying to use the "dirty rects" principle in my pygame project and I'm running into some strange behavior. Here is the code for a simple example, in which a circle + square is drawn at the cursor location. When using the pygame.display.update() function with no arguments - the whole screen is updated and everything looks good, when using pygame.display.update() with arguments - only parts of the screen are updated and I see - full_screen_capture.mp4 (OBS recording with capture of all monitor screen). For some reason, when moving sharply, the cursor update area is truncated. However, when capturing only the window with the game (window_capture.mp4) in OBS, this problem disappears. When using pygame.sprite.DirtySprite, etc, this problem persists. What could be the reason for this behaviour?

import pygame as pg
import copy


class Game:
    def __init__(self, fps=60, is_full_screen=False, width=1280, height=720):
        pg.init()
        if is_full_screen:
            self.width = pg.display.Info().current_w
            self.height = pg.display.Info().current_h
            self.screen = pg.display.set_mode((0, 0), pg.FULLSCREEN | pg.NOFRAME | pg.DOUBLEBUF | pg.HWSURFACE)
        else:
            self.width = width
            self.height = height
            self.screen = pg.display.set_mode((self.width, self.height),  pg.DOUBLEBUF | pg.HWSURFACE)
        self.screen.convert_alpha()
        self.screen.set_alpha(255)
        
        self.background_color = (30, 30, 30)
        
        self.clock = pg.time.Clock()
        self.fps = fps
        
        pg.font.init()
        self.font = pg.font.SysFont("Arial", 30)
        self.font_color = (255, 200, 120)
        
        #  list of updating rects
        self.rects_to_update = []
        self.rects_to_refresh_background = []
        
        self.cursor_surface = pg.Surface((100, 100))
        self.cursor_surface.convert_alpha()
        self.cursor_surface.set_alpha(255)
        self.cursor_color = (45, 134, 255)
        pg.draw.circle(self.cursor_surface, self.cursor_color, (50, 50), 40)
        pg.draw.rect(self.cursor_surface, self.cursor_color, (0, 0, 100, 100), 2)
        self.cursor_surface.set_colorkey((0, 0, 0))
        
    
    def show_work_info(self):
        fps = self.clock.get_fps()
        try:
            fps = int(fps)
        except OverflowError:
            fps = str(fps)
        text_surface_1 = self.font.render(f"fps:{fps}", True, self.font_color)
        text_surface_2 = self.font.render(f"width:{self.width}", True, self.font_color)
        text_surface_3 = self.font.render(f"height:{self.height}", True, self.font_color)
        
        pos_1 = (10, 0)
        pos_2 = (10, text_surface_1.get_height() + 5)
        pos_3 = (10, (text_surface_1.get_height() + 5) * 2)
        
        self.rects_to_update.append(text_surface_1.get_rect().move(pos_1))
        self.rects_to_update.append(text_surface_2.get_rect().move(pos_2))
        self.rects_to_update.append(text_surface_3.get_rect().move(pos_3))
        
        self.screen.blit(text_surface_1, pos_1)
        self.screen.blit(text_surface_2, pos_2)
        self.screen.blit(text_surface_3, pos_3)
    
    def draw_cursor(self):
        if pg.mouse.get_pressed()[0]:
            mouse_pos = pg.mouse.get_pos()
            cursor_rect = self.cursor_surface.get_rect().move(mouse_pos)
            self.rects_to_update.append(cursor_rect)
            self.screen.blit(self.cursor_surface, cursor_rect)
    
    def refresh_background(self, rect):
        pg.draw.rect(self.screen, self.background_color, rect)
    
    def event_handler(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
                sys.exit()
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_ESCAPE:
                    pg.quit()
                    sys.exit()
            
    
    def main_loop(self):
        self.screen.fill((self.background_color))
        self.rects_to_update.append(self.screen.get_rect())
        while True:
            
            self.clock.tick(self.fps)
            self.rects_to_refresh_background = copy.deepcopy(self.rects_to_update)
            self.rects_to_update = []
            
            self.screen.fill(self.background_color)
            
            self.event_handler()
            
            self.show_work_info()
            
            new_rect = None
            
            if pg.mouse.get_pressed()[0]:
                mouse_pos = pg.mouse.get_pos()
                cursor_rect = self.cursor_surface.get_rect()
                new_rect = cursor_rect.move(mouse_pos)
                
                self.screen.blit(self.cursor_surface, new_rect)
                
                self.rects_to_update.append(new_rect)
            
            pg.display.update(self.rects_to_update)
            pg.display.update(self.rects_to_refresh_background)
            
            #  pg.display.update()
            



def main():
    game = Game(fps=60, is_full_screen=False)
    game.main_loop()


if __name__ == "__main__":
    main()
full_screen_capture.mp4
window_capture.mp4

Comments

# # robertpfeiffer commented at 2022-03-31 11:51:27

This code of yours is a bit too involved to pinpoint the bug, and it's probably windows-specific. Also it looks like you have one small logic error in your code, and that could explain the problem. We'll post a simplified test program for you to execute and screencapture.


# # dahsa333 commented at 2022-04-05 21:29:11

Ok, Thank you!


# # Starbuck5 commented at 2022-05-02 04:50:33

My theory would be update rects not getting scaled properly with Windows DPI scaling inside SDL, leading to edges getting cut off.

Metadata

Metadata

Assignees

No one assigned

    Labels

    displaypygame.display

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions