[Help] Understanding pygame.display.update(rects)
I recently began using PyGame as a fun side project in Python. Yesterday, I came across some documentation about the DirtyRectangle Animation technique and tried implementing it in a render method. I noticed that even though I was only supposed to be updating the section of the screen that fell under the rectangle, the entire screen would actually update which is unexpected behavior and seems to defeat the purpose.
Here is a simplified version of my original code that confused me. I am blitting three rectangles onto the top third of the screen but never updating that portion of the display, yet those rectangles appear when using pygame.display.update(self.updatedRects) when updatedRects doesn't include the top third of the screen. You can test this yourself but running my code and clicking in the bottom 2/3rds of the screen.
import pygame
import sys
pygame.init()
screenInfo = pygame.display.Info()
clock = pygame.time.Clock()
windowSize = (1000, 1000)
screen = pygame.display.set_mode(windowSize)
class GameConstants:
windowSize = windowSize
board_size = 3
white = (255, 255, 255)
class Board:
def __init__(self):
self.size = GameConstants.board_size
self.location = (0, 0)
self.rectSize = (round(GameConstants.windowSize[0] / GameConstants.board_size) + 1,
round(GameConstants.windowSize[1] / GameConstants.board_size) + 1)
self.rects = []
for row in range(3):
y = self.rectSize[0] * row
for col in range(3):
x = self.rectSize[1] * col
self.rects.append((pygame.Rect((x, y), self.rectSize), (255 // (row + 1), 255 // (col + 1), 200)))
class Game:
def __init__(self, board):
self.board = board
self.piecePos = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
self.updateRects = []
def newPiece(self, mousePosition):
pos = self.convertPos(mousePosition)
if pos and self.piecePos[pos[0]][pos[1]] == 0:
x, y = pos
self.piecePos[x][y] = 1
# blit on screen
rect = self.board.rects[x + y * 3]
screen.fill(rect[1], rect[0])
self.updateRects.append(rect[0])
def render(self):
print(self.updateRects)
pygame.display.update(self.updateRects)
self.updateRects = []
def convertPos(self, position):
for index, rect in enumerate(self.board.rects):
if rect[0].collidepoint(position):
return (index - 3 * (index // 3), index // 3)
def reset(self):
self.piecePos = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
screen.fill(GameConstants.white)
pygame.display.flip()
for rect in board.rects[0:3]:
screen.fill(rect[1], rect[0])
board = Board()
game = Game(board)
game.reset()
while True:
clock.tick(40)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
mousePosition = pygame.mouse.get_pos()
game.newPiece(mousePosition)
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
sys.exit()
elif event.key == pygame.K_r:
game.reset()
if game.updateRects:
game.render()
Posted Nov 30, 2017, 4:52 AM UTC
here: https://pastebin.com/DtQnB8Y7
Here is a screen recording of your code. As you can tell, it doesn't seem to work on my end.
it works on my end. I don't know why its not working for you.
Edit if the background switches from black to white when you press UP and DOWN, then it seems to behave exactly like pg.display.upate(), for when I use pg.display.update(rect = None), the screen does not update at all. Why it behaves differently for you, I don't know. Perhaps it has to do with being on a Mac.
I just ran your code on my desktop (Windows 10), and the code executed and displayed correctly. I believe this means that it's an issue with Macs.