Description
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.