I'm making a very simple pixel art software in pygame. My logic was creating a grid class, which has a 2D list, containing 0's. When I click, the grid approximates the row and column selected, and mark the cell with a number, corresponding to the color. For simplicity, let's say '1'.
The code works correctly, but It's slow. If the number of rows and columns is less or equal than 10, It works perfectly, but if It's more, it's very laggy.
I think the problem is that I'm updating the entire screen everytime, and, since the program has to check EVERY cell, It can't handle a bigger list
import pygame
from grid import Grid
from pincel import Pincel
from debugger import Debugger
from display import Display
from pygame.locals import *
pygame.init()
pygame.mixer_music.load("musica/musica1.wav")
pygame.mixer_music.play(-1)
width = 1300
height = 1300
screen = pygame.display.set_mode((1366, 768), pygame.RESIZABLE)
pygame.display.set_caption("SquareDraw")
#Grid Creator
numberOfRows = 25
numberOfColumns = 25
grid = Grid(numberOfRows, numberOfColumns)
# Medidas
basicX = width / numberOfColumns
basicY = height / numberOfRows
#Tool Creator
pincel = Pincel(2)
#variáveis de controle
running = 1
#Initial values
grid.equipTool(pincel)
#variáveis de controle de desenho
clicking = 0
def drawScreen(screen, grid, rows, columns, basicX, basicY):
for i in range(rows):
for j in range(columns):
if grid[i][j]:
print('yes')
print(i, j)
pygame.draw.rect(screen, (0, 0, 0), (j * basicX, i * basicY, basicX, basicY))
while running:
screen.fill((255, 255, 255))
Display.drawScreen(screen, grid.board, grid.getRows(), grid.getColumns(), basicX, basicY)
pygame.display.flip()
events = pygame.event.get()
for event in events:
if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = 0
if event.type == pygame.MOUSEBUTTONDOWN or clicking:
clicking = 1
x, y = pygame.mouse.get_pos()
Debugger.printArray2D(grid.board)
print('')
xInGrid = int(x / basicX)
yInGrid = int(y / basicY)
grid.ferramenta.draw(grid.board, xInGrid, yInGrid)
Debugger.printArray2D(grid.board)
print('')
if event.type == pygame.MOUSEBUTTONUP:
clicking = 0
if event.type == pygame.VIDEORESIZE:
width = event.w
height = event.h
basicX = width / numberOfColumns
basicY = height / numberOfRows
print(width, height)
pygame.quit()
The class grid contains the 2D list. The class "Pincel" marks the cells and The class "Debugger" is just for printing lists or anything related to debugging.
Is there a way to update only the part of the screen that was changed? If so, how can I apply that in my logic?
Thanks in advance :)
A few things:
Here is the updated code:
import pygame
#from grid import Grid
#from pincel import Pincel
#from debugger import Debugger
#from display import Display
from pygame.locals import *
pygame.init()
#pygame.mixer_music.load("musica/musica1.wav")
#pygame.mixer_music.play(-1)
width = 1000
height = 1000
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)
pygame.display.set_caption("SquareDraw")
#Grid Creator
numberOfRows = 250
numberOfColumns = 250
#grid = Grid(numberOfRows, numberOfColumns)
grid = [[0 for x in range(numberOfRows)] for y in range(numberOfColumns)] # use array for grid: 0=white, 1=black
# Medidas
basicX = width / numberOfColumns
basicY = height / numberOfRows
#Tool Creator
#pincel = Pincel(2)
#xx
running = 1
#Initial values
#grid.equipTool(pincel)
#xx
clicking = 0
def drawScreen(screen, grid, basicX, basicY): # draw rectangles from grid array
for i in range(numberOfColumns):
for j in range(numberOfRows):
if grid[i][j]:
#print('yes')
#print(i, j)
pygame.draw.rect(screen, (0, 0, 0), (j * basicX, i * basicY, basicX, basicY))
screen.fill((255, 255, 255)) # start screen
while running:
events = pygame.event.get()
for event in events:
if (event.type == pygame.QUIT) or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = 0
if event.type == pygame.MOUSEBUTTONDOWN or clicking: # mouse button down
clicking = 1
x, y = pygame.mouse.get_pos()
#Debugger.printArray2D(grid.board)
#print('')
xInGrid = int(x / basicX)
yInGrid = int(y / basicY)
grid[yInGrid][xInGrid] = 1 # save this point = 1, for screen redraw (if resize)
pygame.draw.rect(screen, (0, 0, 0), (xInGrid * basicX, yInGrid * basicY, basicX, basicY)) # draw rectangle
#grid.ferramenta.draw(grid.board, xInGrid, yInGrid)
#Debugger.printArray2D(grid.board)
#print('')
pygame.display.flip() # update screen
if event.type == pygame.MOUSEBUTTONUP:
clicking = 0
if event.type == pygame.VIDEORESIZE: # screen resized, must adjust grid height, width
width = event.w
height = event.h
basicX = width / numberOfColumns
basicY = height / numberOfRows
#print(width, height)
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE) # reset screen with new height, width
screen.fill((255, 255, 255)) # clear screen
drawScreen(screen, grid, basicX, basicY) # redraw rectangles
pygame.display.flip() # update screen
pygame.quit()