Question

I am trying to draw text to a screen in a space above a bunch of rects that are all in the 2d array square. When i try and draw text to the screen it says that "Surfaces must not be locked during blit."

I have tried unlocking, it makes no difference.

import sys, time, random, pygame
from pygame import *
from time import time,sleep
pygame.init()
global isDragging, inDrag, rightDrag, lastDrag, inDragRight, mouseX,mouseY, borderHeight
isDragging = False
isAuto = False
inDrag= False
inDragRight = False
isFilling = False
done = False
lastDrag = None
rightDrag = None
tickTime = 300
font = pygame.font.SysFont(None, 12,False,False)
dragDelay = 2
BLACK    = (   0,   0,   0)
WHITE    = ( 255, 255, 255)
GREEN    = (   0, 255,   0)
RED      = ( 255,   0,   0)
PINK     = ( 255, 150, 200)
BLUE     = (   0,   0, 255)
RED = GREEN
width, height, margin = 100, 100, 1
noWidth, noHeight = 6,6
speed = [2, 2]
borderHeight = 50
size = (width*noWidth,height*noHeight + borderHeight)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("PieStone")
clock = pygame.time.Clock()
pixArray = pygame.PixelArray(screen)
font = pygame.font.SysFont("monospace", 15)
word = font.render("test", 1, (0, 0, 0))

class Null:
    pass
square = [[Null() for i in range(noHeight)]for i in range(noWidth)]
for d1 in range(noWidth):
    for d2 in range(noHeight):
        square[d1][d2].man = False
        square[d1][d2].visits = 0
        square[d1][d2].colour = BLACK
        square[d1][d2].margin = 1
a = 1
i = 1

def text(word,size,pos1,pos2,pos3):
    word = font.render(str(word),size,(pos1,pos2,pos3))
    return word



def colide(obj,mouseX,mouseY):
    if obj.collidepoint(mouseX,mouseY) == 1:
        return True
    else:
        return False

def click(mouseX,mouseY):
    #rint("left")
    global inDrag,lastDrag
    for d1 in range(noWidth):
        for d2 in range(noHeight):
            if colide(square[d1][d2].rect,mouseX,mouseY):
                square[d1][d2].man = True
                #print("square",d1,d2,"has been clicked")
                try:
                    if square[d1][d2] != lastDrag:
                        inDrag = True
                        lastDrag = square[d1][d2]
                    else:
                        inDrag = False
                except UnboundLocalError:
                    print("error")
                    lastDrag = square[d1][d2]
                #print(inDrag)

                if square[d1][d2].margin == 0 and inDrag:
                    square[d1][d2].margin = 1
                    square[d1][d2].visits = square[d1][d2].visits + 1
                elif square[d1][d2].margin == 1 and inDrag:
                    square[d1][d2].margin = 0
                    square[d1][d2].visits = square[d1][d2].visits + 1
                break 
                '''if square[d1][d2].visits >= 5 and square[d1][d2].colour == BLACK:
                    square[d1][d2].visits = 0
                    square[d1][d2].colour = RED
                elif square[d1][d2].visits >= 5 and square[d1][d2].colour == RED:
                    square[d1][d2].visits = 0
                    square[d1][d2].colour = BLACK'''

def rightClick(mouseX,mouseY):

    #print("right")
    global inDragRight, lastRight
    for d1 in range(noWidth):
        for d2 in range(noHeight):

            if colide(square[d1][d2].rect,mouseX,mouseY):
                square[d1][d2].man = True
                #print("colide")
                try:
                    if square[d1][d2] != lastRight:
                        inDragRight = True
                        lastRight = square[d1][d2]
                    else:
                        inDragRight = False
                except:
                    print("error")
                    lastRight = square[d1][d2]

                #print(inDragRight)
                if square[d1][d2].colour == RED and inDragRight:
                    square[d1][d2].colour = BLACK
                    #print("black")
                elif square[d1][d2].colour == BLACK and inDragRight:
                    square[d1][d2].colour = RED
                    #print("red")
                break     

while not done:
    screen.blit(word, (0, 0))
    (mouseX,mouseY) = pygame.mouse.get_pos()
    #print(str(mouseX)+",",mouseY)

    for event in pygame.event.get(): # User did something
        if event.type == pygame.QUIT: # If user clicked close
            done = True # Flag that we are done so we exit this loop
        elif event.type == pygame.MOUSEBUTTONDOWN:
            #print(mouseX,mouseY)
            if pygame.mouse.get_pressed()[0] == 1:
                isDragging = True
            if pygame.mouse.get_pressed()[2] == 1:
                isFilling = True

            elif pygame.mouse.get_pressed()[1] == 1:
                isAuto = True
            #print(pygame.mouse.get_pressed())
        elif event.type == pygame.MOUSEBUTTONUP:
            #print("up")
            isDragging = False
            isFilling = False
            lastDrag = None
            lastRight = False
            if pygame.mouse.get_pressed()[0] == 1:
                isDragging = True
            if pygame.mouse.get_pressed()[2] == 1:
                isFilling = True
    if isAuto:
        rnd1 = random.randint(0,1)
        if rnd1 == 1:
            isDragging = True
            isFilling = False
        else:
            isDragging = False
            isFilling = True
        (mouseX,mouseY) = (random.randint(0,width*noWidth),random.randint(0,height*noHeight)+borderHeight)
        #print(mouseX,mouseY)
    if isDragging:
        click(mouseX,mouseY)
    if isFilling:
        rightClick(mouseX,mouseY)
    screen.fill(WHITE)
    # --- Game logic should go here
    i = 0
    for d1 in range(noWidth):
        if noHeight % 2 == 0:
            '''if i == 0:
                i = 1
            else:
                i = 0'''
        for d2 in range(noHeight):

            #if i % a == 0:
            try:

                if i == 0:
                    pass
                elif i == 1:
                    pass

            except AttributeError:
                print("AttributeError")
                square[d1][d2].margin = random.randint(0,1)

            #print(square[d1][d2].visits)

            square[d1][d2].rect = pygame.draw.rect(screen, square[d1][d2].colour, [(d1*width), ((d2*height)+borderHeight),width,(height)],square[d1][d2].margin)
            #print("d1*width:",d1*width,"d2*height:",d2*height,"d1*width+width:",d1*width+width,"d2*height+height:",d2*height+height)

    pygame.display.flip()
    clock.tick(tickTime)
# Close the window and quit.
# If you forget this line, the program will 'hang'
# on exit if running from IDLE.
pygame.quit()
Was it helpful?

Solution

You're using a PixelArray:

pixArray = pygame.PixelArray(screen)

But using a PixelArray locks your Surface, as stated in the documentation:

During its lifetime, the PixelArray locks the surface, thus you explicitly have to delete it once its not used anymore and the surface should perform operations in the same scope.

Just remove the line, since you're not using it anyway.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top