# Tetromino (a Tetris clone) # By Al Sweigart al@inventwithpython.com # http://inventwithpython.com/pygame # Released under a "Simplified BSD" license import random, time, pygame, sys from pygame.locals import * FPS = 30 #image par seconde WINDOWWIDTH = 1000 #largeur fenêtre WINDOWHEIGHT = 500 #hauteur fenêtre BOXSIZE = 20 #taille boîte (pièce,...) BOARDWIDTH = 10 #largeur jeu BOARDHEIGHT = 20 #hauteur jeu BLANK = '.' #simplification pour dire qu'une liste est vide MOVESIDEWAYSFREQ = 0.15 #temps que la pièce met pour glisser sur le côté MOVEDOWNFREQ = 0.1 #temps que la pièce met pour descendre vers le bas XMARGIN = 10 #marge côté TOPMARGIN = 10 #marge haut XMARGIN2 = int((WINDOWWIDTH - BOARDWIDTH * BOXSIZE) / 2)+100 #marge pour insérer la deuxième grille #Couleurs des pièces # R G B WHITE = (255, 255, 255) GRAY = (185, 185, 185) BLACK = ( 0, 0, 0) RED = (155, 0, 0) LIGHTRED = (175, 20, 20) GREEN = ( 0, 155, 0) LIGHTGREEN = ( 20, 175, 20) BLUE = ( 0, 0, 155) LIGHTBLUE = ( 20, 20, 175) YELLOW = (155, 155, 0) LIGHTYELLOW = (175, 175, 20) ARPLAN = (150, 200, 200) #PIECEF = (150, 0, 25) BORDERCOLOR = BLUE #couleur de la bordure de jeu BGCOLOR = ARPLAN #couleur de l'arrière plan TEXTCOLOR = WHITE #couleur du texte (level, score,...) TEXTSHADOWCOLOR = RED #couleur d'ombre du TETROMINOS COLORS = ( BLUE, GREEN, RED, YELLOW) #superposition des 2 couleurs pour effets d'ombres lors du dessin des pièces LIGHTCOLORS = (LIGHTBLUE, LIGHTGREEN, LIGHTRED, LIGHTYELLOW) ##LIGHTCOLORS = {'LIGHTBLUE':'0.2', 'LIGHTGREEN':'0.2', 'LIGHTRED':'0.2', 'LIGHTYELLOW':'0.2', 'PIECEF':'0.2'} ##def aleatoire(): ## for i in LIGHTCOLORS: ## if random()> LIGHTCOLORS.values(): ## return(LIGHTCOLORS.key()) assert len(COLORS) == len(LIGHTCOLORS) #chaque couleur doit avoir une couleur claire TEMPLATEWIDTH = 5 #largeur de la pièce TEMPLATEHEIGHT = 5 #hauteur de la pièce #différentes formes de pièces S_SHAPE_TEMPLATE = [['.....', '.....', '..OO.', '.OO..', '.....'], #première façon d'être tournée ['.....', '..O..', '..OO.', '...O.', '.....']] #deuxième façon d'être tournée Z_SHAPE_TEMPLATE = [['.....', '.....', '.OO..', '..OO.', '.....'], ['.....', '..O..', '.OO..', '.O...', '.....']] I_SHAPE_TEMPLATE = [['..O..', '..O..', '..O..', '..O..', '.....'], ['.....', '.....', 'OOOO.', '.....', '.....']] O_SHAPE_TEMPLATE = [['.....', '.....', '.OO..', '.OO..', '.....']] J_SHAPE_TEMPLATE = [['.....', '.O...', '.OOO.', '.....', '.....'], ['.....', '..OO.', '..O..', '..O..', '.....'], ['.....', '.....', '.OOO.', '...O.', '.....'], ['.....', '..O..', '..O..', '.OO..', '.....']] L_SHAPE_TEMPLATE = [['.....', '...O.', '.OOO.', '.....', '.....'], ['.....', '..O..', '..O..', '..OO.', '.....'], ['.....', '.....', '.OOO.', '.O...', '.....'], ['.....', '.OO..', '..O..', '..O..', '.....']] T_SHAPE_TEMPLATE = [['.....', '..O..', '.OOO.', '.....', '.....'], ['.....', '..O..', '..OO.', '..O..', '.....'], ['.....', '.....', '.OOO.', '..O..', '.....'], ['.....', '..O..', '.OO..', '..O..', '.....']] PIECES = {'S': S_SHAPE_TEMPLATE, 'Z': Z_SHAPE_TEMPLATE, 'J': J_SHAPE_TEMPLATE, 'L': L_SHAPE_TEMPLATE, 'I': I_SHAPE_TEMPLATE, 'O': O_SHAPE_TEMPLATE, 'T': T_SHAPE_TEMPLATE} def main(): global FPSCLOCK, DISPLAYSURF, BASICFONT, BIGFONT pygame.init() FPSCLOCK = pygame.time.Clock() DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT)) BASICFONT = pygame.font.Font('freesansbold.ttf', 18) BIGFONT = pygame.font.Font('freesansbold.ttf', 100) pygame.display.set_caption('Tetromino') showTextScreen('Tetromino') while True: #boucle de jeu if random.randint(0, 1) == 0: pygame.mixer.music.load('son.wav') else: pygame.mixer.music.load('son.wav') pygame.mixer.music.play(-1, 0.0) runGame() pygame.mixer.music.stop() showTextScreen('Game Over') #time.time --> timer qui provient de la bibliothèque Pygame def runGame(): # variables d'installation pour lancer le jeu board = getBlankBoard() #definition de la première grille vide board1 = getBlankBoard1() #définition de la deuxième grille vide lastMoveDownTime = time.time() lastMoveSidewaysTime = time.time() lastFallTime = time.time() lastFallTime1 = time.time() #Remarque: PAS DE MOVING UP : la pièce ne va pas vers le haut #Au debut pas de mouvement quand on appuie pas sur une touche movingDown = False movingLeft = False movingRight = False movingDown1 = False movingLeft1 = False movingRight1 = False #score initialisé à 0 pour démarrer le jeu score = 0 score1 = 0 #le niveau est calculé avec la fonction calculateLevelAndFallFreq level, fallFreq = calculateLevelAndFallFreq(score) level1, fallFreq1 = calculateLevelAndFallFreq1(score1) fallingPiece = getNewPiece() fallingPiece1 = getNewPiece() nextPiece = getNewPiece() while True: #boucle de jeu if fallingPiece == None: #Si aucune pièce n'est en train de tomber ALORS on en fait venir une nouvelle fallingPiece = nextPiece nextPiece = getNewPiece() lastFallTime = time.time() #reset lastFallTime if not isValidPosition(board, fallingPiece): return #si la pièce n'a pas une position valide on affiche game over ##Même chose pour la deuxième grille elif fallingPiece1 == None: fallingPiece1 = nextPiece nextPiece = getNewPiece() lastFallTime1 = time.time() # réinitialise lastFallTime if not isValidPosition1(board1, fallingPiece1): return ## checkForQuit() for event in pygame.event.get(): #boucle pour les clés de jeu if event.type == KEYUP: #relacher touche if (event.key == K_p): #pour mettre le jeu en pause appuyer sur p DISPLAYSURF.fill(BGCOLOR) #mettre l'arrière plan pygame.mixer.music.stop() #musique se coupe showTextScreen('Paused') #et on affiche pause pygame.mixer.music.play(-1, 0.0) lastFallTime = time.time() lastFallTime1 = time.time() lastMoveDownTime = time.time() lastMoveSidewaysTime = time.time() elif (event.key == K_q): movingLeft = False elif (event.key == K_LEFT): movingLeft1 = False elif (event.key == K_d): movingRight = False elif (event.key == K_RIGHT): movingRight1 = False elif (event.key == K_s): movingDown = False elif (event.key == K_DOWN): movingDown1 = False elif event.type == KEYDOWN: #appuyer sur touche #déplacer la pièce sur le côté if (event.key == K_q) and isValidPosition(board, fallingPiece, adjX=-1): fallingPiece['x'] -= 1 movingLeft = True movingRight = False lastMoveSidewaysTime = time.time() elif (event.key == K_LEFT) and isValidPosition1(board1, fallingPiece1, adjX1=-1): fallingPiece1['x'] -= 1 movingLeft1 = True movingRight1 = False lastMoveSidewaysTime = time.time() elif (event.key == K_d) and isValidPosition(board, fallingPiece, adjX=1): fallingPiece['x'] += 1 movingRight = True movingLeft = False lastMoveSidewaysTime = time.time() elif (event.key == K_RIGHT) and isValidPosition1(board1, fallingPiece1, adjX1=1): fallingPiece1['x'] += 1 movingRight1 = True movingLeft1 = False lastMoveSidewaysTime = time.time() #rotation des pièces (s'il y a de la place pour la faire tourner) elif (event.key == K_z): fallingPiece['rotation'] = (fallingPiece['rotation'] + 1) % len(PIECES[fallingPiece['shape']]) if not isValidPosition(board, fallingPiece): fallingPiece['rotation'] = (fallingPiece['rotation'] - 1) % len(PIECES[fallingPiece['shape']]) elif (event.key == K_UP): fallingPiece1['rotation'] = (fallingPiece1['rotation'] + 1) % len(PIECES[fallingPiece1['shape']]) if not isValidPosition1(board1, fallingPiece1): fallingPiece1['rotation'] = (fallingPiece1['rotation'] - 1) % len(PIECES[fallingPiece1['shape']]) # Faire tomber une pièce plus rapidement avec la touche Bas ou S elif (event.key == K_s): movingDown = True if isValidPosition(board, fallingPiece, adjY=1): fallingPiece['y'] += 1 lastMoveDownTime = time.time() elif (event.key == K_DOWN): movingDown1 = True if isValidPosition1(board1, fallingPiece1, adjY1=1): fallingPiece1['y'] += 1 lastMoveDownTime = time.time() #Bouge la pièce actuelle tout en bas elif event.key == K_SPACE: movingDown = False movingLeft = False movingRight = False for i in range(1, BOARDHEIGHT): if not isValidPosition(board, fallingPiece, adjY=i): break fallingPiece['y'] += i - 1 elif event.key == K_BACKSPACE: movingDown1 = False movingLeft1 = False movingRight1 = False for i in range(1, BOARDHEIGHT): if not isValidPosition1(board1, fallingPiece1, adjY1=i): break fallingPiece1['y'] += i - 1 # handle moving the piece because of user input if (movingLeft or movingRight) and time.time() - lastMoveSidewaysTime > MOVESIDEWAYSFREQ: if movingLeft and isValidPosition(board, fallingPiece, adjX=-1): fallingPiece['x'] -= 1 elif movingRight and isValidPosition(board, fallingPiece, adjX=1): fallingPiece['x'] += 1 lastMoveSidewaysTime = time.time() if movingDown and time.time() - lastMoveDownTime > MOVEDOWNFREQ and isValidPosition(board, fallingPiece, adjY=1): fallingPiece['y'] += 1 lastMoveDownTime = time.time() if (movingLeft1 or movingRight1) and time.time() - lastMoveSidewaysTime > MOVESIDEWAYSFREQ: if movingLeft1 and isValidPosition1(board1, fallingPiece1, adjX1=-1): fallingPiece1['x'] -= 1 elif movingRight1 and isValidPosition1(board1, fallingPiece1, adjX1=1): fallingPiece1['x'] += 1 lastMoveSidewaysTime = time.time() if movingDown1 and time.time() - lastMoveDownTime > MOVEDOWNFREQ and isValidPosition1(board1, fallingPiece1, adjY1=1): fallingPiece1['y'] += 1 lastMoveDownTime = time.time() # Laisse la pièce tombait si il est temps de tomber if time.time() - lastFallTime > fallFreq: # On regarde si la pièce est posé en bas if not isValidPosition(board, fallingPiece, adjY=1): # La pièce à atterit, elle est placée sur le fond addToBoard(board, fallingPiece) score += removeCompleteLines(board) level, fallFreq = calculateLevelAndFallFreq(score) fallingPiece = None else: # Si la pièce n'a pas atterit, elle bouge vers le bas fallingPiece['y'] += 1 lastFallTime = time.time() if time.time() - lastFallTime1 > fallFreq1: # see if the piece has landed if not isValidPosition1(board1, fallingPiece1, adjY1=1): # falling piece has landed, set it on the board addToBoard1(board1, fallingPiece1) score1 += removeCompleteLines1(board1) level1, fallFreq1 = calculateLevelAndFallFreq1(score1) fallingPiece1 = None else: # piece did not land, just move the piece down fallingPiece1['y'] += 1 lastFallTime1 = time.time() # drawing everything on the screen DISPLAYSURF.fill(BGCOLOR) drawBoard(board) drawBoard1(board1) drawStatus(score1, level1) drawStatus1(score, level) drawNextPiece(nextPiece) drawNextPiece1(nextPiece) if fallingPiece != None: drawPiece(fallingPiece) if fallingPiece1 != None: drawPiece1(fallingPiece1) pygame.display.update() FPSCLOCK.tick(FPS) def makeTextObjs(text, font, color): surf = font.render(text, True, color) return surf, surf.get_rect() def terminate(): pygame.quit() sys.exit() def checkForKeyPress(): # Go through event queue looking for a KEYUP event. # Grab KEYDOWN events to remove them from the event queue. checkForQuit() for event in pygame.event.get([KEYDOWN, KEYUP]): if event.type == KEYDOWN: continue return event.key return None def showTextScreen(text): # This function displays large text in the # center of the screen until a key is pressed. # Draw the text drop shadow titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTSHADOWCOLOR) titleRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2)) DISPLAYSURF.blit(titleSurf, titleRect) # Draw the text titleSurf, titleRect = makeTextObjs(text, BIGFONT, TEXTCOLOR) titleRect.center = (int(WINDOWWIDTH / 2) - 3, int(WINDOWHEIGHT / 2) - 3) DISPLAYSURF.blit(titleSurf, titleRect) # Draw the additional "Press a key to play." text. pressKeySurf, pressKeyRect = makeTextObjs('Press a key to play.', BASICFONT, TEXTCOLOR) pressKeyRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2) + 100) DISPLAYSURF.blit(pressKeySurf, pressKeyRect) while checkForKeyPress() == None: pygame.display.update() FPSCLOCK.tick() def checkForQuit(): for event in pygame.event.get(QUIT): # get all the QUIT events terminate() # terminate if any QUIT events are present for event in pygame.event.get(KEYUP): # get all the KEYUP events if event.key == K_ESCAPE: terminate() # terminate if the KEYUP event was for the Esc key pygame.event.post(event) # put the other KEYUP event objects back def calculateLevelAndFallFreq(score): # Based on the score, return the level the player is on and # how many seconds pass until a falling piece falls one space. level = int(score / 2) + 1 fallFreq = 0.27 - (level * 0.02) return level, fallFreq def calculateLevelAndFallFreq1(score1): # Based on the score, return the level the player is on and # how many seconds pass until a falling piece falls one space. level1 = int(score1 / 2) + 1 fallFreq1 = 0.27 - (level1 * 0.02) return level1, fallFreq1 def getNewPiece(): # return a random new piece in a random rotation and color shape = random.choice(list(PIECES.keys())) newPiece = {'shape': shape, 'rotation': random.randint(0, len(PIECES[shape]) - 1), 'x': int(BOARDWIDTH / 2) - int(TEMPLATEWIDTH / 2), 'y': -2, # start it above the board (i.e. less than 0) 'color': random.randint(0, len(COLORS)-1)} return newPiece def addToBoard(board, piece): # fill in the board based on piece's location, shape, and rotation for x in range(TEMPLATEWIDTH): for y in range(TEMPLATEHEIGHT): if PIECES[piece['shape']][piece['rotation']][y][x] != BLANK: board[x + piece['x']][y + piece['y']] = piece['color'] def addToBoard1(board1, piece): # fill in the board based on piece's location, shape, and rotation for x in range(TEMPLATEWIDTH): for y in range(TEMPLATEHEIGHT): if PIECES[piece['shape']][piece['rotation']][y][x] != BLANK: board1[x + piece['x']][y + piece['y']] = piece['color'] def getBlankBoard(): #créer et retourne le premier tableau/grille vide board = [] for i in range(BOARDWIDTH): board.append([BLANK] * BOARDHEIGHT) return board def getBlankBoard1(): # créer et retourne le deuxième tableau/grille vide board1 = [] for i in range(BOARDWIDTH): board1.append([BLANK] * BOARDHEIGHT) return board1 def isOnBoard(x, y): return x >= 0 and x < BOARDWIDTH and y < BOARDHEIGHT def isValidPosition(board, piece, adjX=0, adjY=0): # Return True if the piece is within the board and not colliding for x in range(TEMPLATEWIDTH): for y in range(TEMPLATEHEIGHT): isAboveBoard = y + piece['y'] + adjY < 0 if isAboveBoard or PIECES[piece['shape']][piece['rotation']][y][x] == BLANK: continue if not isOnBoard(x + piece['x'] + adjX, y + piece['y'] + adjY): return False if board[x + piece['x'] + adjX][y + piece['y'] + adjY] != BLANK: return False return True def isValidPosition1(board1, piece, adjX1=0, adjY1=0): # Return True if the piece is within the board and not colliding for x in range(TEMPLATEWIDTH): for y in range(TEMPLATEHEIGHT): isAboveBoard1 = y + piece['y'] + adjY1 < 0 if isAboveBoard1 or PIECES[piece['shape']][piece['rotation']][y][x] == BLANK: continue if not isOnBoard(x + piece['x'] + adjX1, y + piece['y'] + adjY1): return False if board1[x + piece['x'] + adjX1][y + piece['y'] + adjY1] != BLANK: return False return True def isCompleteLine(board, y): # Return True if the line filled with boxes with no gaps. for x in range(BOARDWIDTH): if board[x][y] == BLANK: return False return True def isCompleteLine1(board1, y): # Return True if the line filled with boxes with no gaps. for x in range(BOARDWIDTH): if board1[x][y] == BLANK: return False return True def removeCompleteLines(board): # Remove any completed lines on the board, move everything above them down, and return the number of complete lines. numLinesRemoved = 0 y = BOARDHEIGHT - 1 # start y at the bottom of the board while y >= 0: if isCompleteLine(board, y): # Remove the line and pull boxes down by one line. for pullDownY in range(y, 0, -1): for x in range(BOARDWIDTH): board[x][pullDownY] = board[x][pullDownY-1] # Set very top line to blank. for x in range(BOARDWIDTH): board[x][0] = BLANK numLinesRemoved += 1 # Note on the next iteration of the loop, y is the same. # This is so that if the line that was pulled down is also # complete, it will be removed. else: y -= 1 # move on to check next row up return numLinesRemoved def removeCompleteLines1(board1): # Remove any completed lines on the board, move everything above them down, and return the number of complete lines. numLinesRemoved = 0 y = BOARDHEIGHT - 1 # start y at the bottom of the board while y >= 0: if isCompleteLine1(board1, y): # Remove the line and pull boxes down by one line. for pullDownY1 in range(y, 0, -1): for x in range(BOARDWIDTH): board1[x][pullDownY1] = board1[x][pullDownY1-1] # Set very top line to blank. for x in range(BOARDWIDTH): board1[x][0] = BLANK numLinesRemoved += 1 # Note on the next iteration of the loop, y is the same. # This is so that if the line that was pulled down is also # complete, it will be removed. else: y -= 1 # move on to check next row up return numLinesRemoved def convertToPixelCoords(boxx, boxy): # Convert the given xy coordinates of the board to xy # coordinates of the location on the screen. return (XMARGIN + (boxx * BOXSIZE)), (TOPMARGIN + (boxy * BOXSIZE)) def convertToPixelCoords1(boxx, boxy): # Convert the given xy coordinates of the board to xy # coordinates of the location on the screen. return (XMARGIN2 + (boxx * BOXSIZE)), (TOPMARGIN + (boxy * BOXSIZE)) def drawBox(boxx, boxy, color, pixelx=None, pixely=None): # draw a single box (each tetromino piece has four boxes) # at xy coordinates on the board. Or, if pixelx & pixely # are specified, draw to the pixel coordinates stored in # pixelx & pixely (this is used for the "Next" piece). if color == BLANK: return if pixelx == None and pixely == None: pixelx, pixely = convertToPixelCoords(boxx, boxy) pygame.draw.rect(DISPLAYSURF, COLORS[color], (pixelx + 1, pixely + 1, BOXSIZE - 1, BOXSIZE - 1)) pygame.draw.rect(DISPLAYSURF, LIGHTCOLORS[color], (pixelx + 1, pixely + 1, BOXSIZE - 4, BOXSIZE - 4)) def drawBox1(boxx, boxy, color, pixelx=None, pixely=None): # draw a single box (each tetromino piece has four boxes) # at xy coordinates on the board. Or, if pixelx & pixely # are specified, draw to the pixel coordinates stored in # pixelx & pixely (this is used for the "Next" piece). if color == BLANK: return if pixelx == None and pixely == None: pixelx, pixely = convertToPixelCoords1(boxx, boxy) pygame.draw.rect(DISPLAYSURF, COLORS[color], (pixelx + 1, pixely + 1, BOXSIZE - 1, BOXSIZE - 1)) pygame.draw.rect(DISPLAYSURF, LIGHTCOLORS[color], (pixelx + 1, pixely + 1, BOXSIZE - 4, BOXSIZE - 4)) def drawBoard(board): # draw the border around the board pygame.draw.rect(DISPLAYSURF, BORDERCOLOR, (XMARGIN - 3, TOPMARGIN - 7, (BOARDWIDTH * BOXSIZE) + 8, (BOARDHEIGHT * BOXSIZE) + 8), 5) # fill the background of the board pygame.draw.rect(DISPLAYSURF, BGCOLOR, (XMARGIN, TOPMARGIN, BOXSIZE * BOARDWIDTH, BOXSIZE * BOARDHEIGHT)) # draw the individual boxes on the board for x in range(BOARDWIDTH): for y in range(BOARDHEIGHT): drawBox(x, y, board[x][y]) def drawBoard1(board1): # draw the border around the board pygame.draw.rect(DISPLAYSURF, BORDERCOLOR, (XMARGIN2 - 3, TOPMARGIN- 7, (BOARDWIDTH * BOXSIZE) + 8, (BOARDHEIGHT * BOXSIZE) + 8), 5) # fill the background of the board pygame.draw.rect(DISPLAYSURF, BGCOLOR, (XMARGIN2, TOPMARGIN, BOXSIZE * BOARDWIDTH, BOXSIZE * BOARDHEIGHT)) # draw the individual boxes on the board for x in range(BOARDWIDTH): for y in range(BOARDHEIGHT): drawBox1(x, y, board1[x][y]) def drawStatus(score, level): # draw the score text scoreSurf = BASICFONT.render('Score: %s' % score, True, TEXTCOLOR) scoreRect = scoreSurf.get_rect() scoreRect.topleft = (WINDOWWIDTH - 150, 20) DISPLAYSURF.blit(scoreSurf, scoreRect) # draw the level text levelSurf = BASICFONT.render('Level: %s' % level, True, TEXTCOLOR) levelRect = levelSurf.get_rect() levelRect.topleft = (WINDOWWIDTH - 150, 50) DISPLAYSURF.blit(levelSurf, levelRect) def drawStatus1(score1, level1): # draw the score text score1Surf = BASICFONT.render('Score: %s' % score1, True, TEXTCOLOR) score1Rect = score1Surf.get_rect() score1Rect.topleft = (WINDOWWIDTH - 700, 20) DISPLAYSURF.blit(score1Surf, score1Rect) # draw the level text level1Surf = BASICFONT.render('Level: %s' % level1, True, TEXTCOLOR) level1Rect = level1Surf.get_rect() level1Rect.topleft = (WINDOWWIDTH - 700, 50) DISPLAYSURF.blit(level1Surf, level1Rect) def drawPiece(piece, pixelx=None, pixely=None): shapeToDraw = PIECES[piece['shape']][piece['rotation']] if pixelx == None and pixely == None: # if pixelx & pixely hasn't been specified, use the location stored in the piece data structure pixelx, pixely = convertToPixelCoords(piece['x'], piece['y']) # draw each of the boxes that make up the piece for x in range(TEMPLATEWIDTH): for y in range(TEMPLATEHEIGHT): if shapeToDraw[y][x] != BLANK: drawBox(None, None, piece['color'], pixelx + (x * BOXSIZE), pixely + (y * BOXSIZE)) def drawPiece1(piece, pixelx=None, pixely=None): shapeToDraw = PIECES[piece['shape']][piece['rotation']] if pixelx == None and pixely == None: # if pixelx & pixely hasn't been specified, use the location stored in the piece data structure pixelx, pixely = convertToPixelCoords1(piece['x'], piece['y']) # draw each of the boxes that make up the piece for x in range(TEMPLATEWIDTH): for y in range(TEMPLATEHEIGHT): if shapeToDraw[y][x] != BLANK: drawBox(None, None, piece['color'], pixelx + (x * BOXSIZE), pixely + (y * BOXSIZE)) def drawNextPiece(piece): # draw the "next" text nextSurf = BASICFONT.render('Next:', True, TEXTCOLOR) nextRect = nextSurf.get_rect() nextRect.topleft = (WINDOWWIDTH - 150, 80) DISPLAYSURF.blit(nextSurf, nextRect) # draw the "next" piece drawPiece(piece, pixelx=WINDOWWIDTH-120, pixely=100) def drawNextPiece1(piece): # draw the "next" text nextSurf = BASICFONT.render('Next:', True, TEXTCOLOR) nextRect = nextSurf.get_rect() nextRect.topleft = (WINDOWWIDTH - 700, 80) DISPLAYSURF.blit(nextSurf, nextRect) # draw the "next" piece drawPiece(piece, pixelx=WINDOWWIDTH-700, pixely=100) if __name__ == '__main__': main()