Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import pygame, random
- from pygame.locals import *
- pygame.init()
- # TETRIS GAME FUNCTIONS #######################################
- def makeGrid():
- # set up a row list
- row = []
- # set up an array for entire grid
- grid = []
- for x in range(0, 20):
- for y in range(0, 10):
- # add 10 items to the row
- row.append(0)
- # add the row 20 times to the grid
- grid.append(row)
- row = []
- return grid # get a 10 x 20 grid
- def placePiece(activeGrid, activeBlock, startY, startX):
- for x in range(0, len(activeBlock)):
- # for the number of vertical rows in the block grid
- for y in range(0, len(activeBlock[1])):
- # copy the block data to the corresponding position on the grid,
- # with the starting value being at the top center of the grid
- if activeBlock[x][y] != 0:
- activeGrid[x + startX][startY + y] = activeBlock[x][y]
- return activeGrid
- # use the current active grid, vertMove (only 1 or 0), horizMove (1 or -1 or 0)
- def movePiece(activeGrid, mainGrid, vertMove, horizMove=0):
- # create a new grid to copy the movement to
- newGrid = makeGrid()
- # iterates through every point on the grid
- for x in range(0, len(activeGrid)):
- for y in range(0, len(activeGrid[1])):
- # once a grid space is found that is not empty -
- if activeGrid[x][y] != 0:
- # if a vertical or horizontal move of the piece would place it out of bounds, don't move the piece
- if (x + vertMove) > 19 or (y + horizMove > 9 or y + horizMove < 0):
- return activeGrid
- # copy the space in the old grid to the corresponding place on the new grid (including the movement)
- newGrid[x + vertMove][y + horizMove] = activeGrid[x][y]
- # if the new grid will collide with other blocks, do not move the piece
- if collision(newGrid, mainGrid):
- return activeGrid
- else:
- return newGrid
- def rotatePiece(activeBlock):
- # rotate the piece - turn the rows into the columns and vice versa
- rotatedBlock = zip(*activeBlock[::-1])
- # since zip turns it into a list of tuples, turn it back into a list of lists
- rotatedBlock = [list(elem) for elem in rotatedBlock]
- return rotatedBlock
- def collision(activeGrid, mainGrid):
- # iterate through the entire active grid
- for x in range(0, len(activeGrid)):
- for y in range(0, len(activeGrid[1])):
- # if the position on the active grid is not empty
- if activeGrid[x][y] != 0:
- # if the corresponding position on the main grid is also not empty, there is a collision
- if mainGrid[x][y] != 0:
- return True
- # if the entire loop is run without a collision, return false
- return False
- def addToMain(activeGrid, mainGrid):
- # once the piece is at its final spot, it has to be added to the main grid
- # iterate through the entire active grid
- for x in range(0, len(activeGrid)):
- for y in range(0, len(activeGrid[1])):
- # if the position on the active grid is not empty
- if activeGrid[x][y] != 0:
- # replace the main grid spaces with the active grid spaces
- mainGrid[x][y] = activeGrid[x][y]
- return mainGrid
- def drawActive():
- for x in range(0, 20):
- for y in range(0, 10):
- if activeGrid[x][y] != 0:
- # first, get the colour of the block
- colour = colours[activeGrid[x][y] - 1]
- colourAlt = colourAlts[activeGrid[x][y] - 1]
- # draw the rectangle
- pygame.draw.rect(screen, colour, [(y * 40), (x * 40), 40, 40])
- pygame.draw.rect(screen, colourAlt, [(y * 40), (x * 40), 40, 40], 3)
- def drawMain():
- # loop through the main grid. Every time there is a non 0 space, draw a 40x40 square
- for x in range(0, 20):
- for y in range(0, 10):
- if mainGrid[x][y] != 0:
- # first, get the colour of the block
- colour = colours[mainGrid[x][y] - 1]
- colourAlt = colourAlts[mainGrid[x][y] - 1]
- # draw the rectangle
- pygame.draw.rect(screen, colour, [(y * 40), (x * 40), 40, 40])
- pygame.draw.rect(screen, colourAlt, [(y * 40), (x * 40), 40, 40], 3)
- else:
- # draw the rest of the grid
- pygame.draw.rect(screen, (40, 40, 40), [(y * 40), (x * 40), 40, 40], 3)
- def lineCheck(mainGrid):
- # loop through the mainGrid
- for x in range(0, len(mainGrid)):
- # start a line counter each time a new line is started
- lineCounter = 0
- for y in range(0, len(mainGrid[1])):
- # if the position on the line is not empty, add 1 to the line counter
- if mainGrid[x][y] != 0:
- lineCounter += 1
- # if the line counter hits 10 (entire line is filled)
- if lineCounter == 10:
- # remove that line from the grid, and append a new, blank line at the beginning
- mainGrid.remove(mainGrid[x])
- mainGrid.insert(0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
- return mainGrid
- def refreshScreen():
- screen.fill(BLACK)
- drawMain()
- drawActive()
- ###############################################################
- # PYGAME VARIABLES ############################################
- WIDTH = 600
- HEIGHT = 800
- ###############################################################
- # COLOURS USED FOR GAME #######################################
- BLACK = (0, 0, 0)
- WHITE = (255, 255, 255)
- LIGHT_BLUE = (108, 237, 239)
- DARK_BlUE = (0, 30, 231)
- ORANGE = (230, 164, 57)
- YELLOW = (241, 239, 79)
- GREEN = (110, 235, 71)
- PURPLE = (147, 44, 231)
- RED = (221, 47, 33)
- LIGHT_BLUE_ALT = (0, 120, 120)
- DARK_BLUE_ALT = (0, 0, 120)
- ORANGE_ALT = (120, 80, 0)
- YELLOW_ALT = (120, 120, 0)
- GREEN_ALT = (0, 120, 0)
- PURPLE_ALT = (80, 0, 120)
- RED_ALT = (120, 0, 0)
- # append colours of blocks to a list
- colours = [YELLOW, LIGHT_BLUE, GREEN, RED, ORANGE, DARK_BlUE, PURPLE]
- # append all colour alts to a list
- colourAlts = [YELLOW_ALT, LIGHT_BLUE_ALT, GREEN_ALT, RED_ALT, ORANGE_ALT, DARK_BLUE_ALT, PURPLE_ALT]
- ###############################################################
- # BLOCK SHAPES - number used to make shape determines colour ##
- oBlock = [[1, 1],
- [1, 1]]
- iBlock = [[0, 0, 0, 0],
- [2, 2, 2, 2],
- [0, 0, 0, 0],
- [0, 0, 0, 0]]
- sBlock = [[0, 3, 3],
- [3, 3, 0],
- [0, 0, 0]]
- zBlock = [[4, 4, 0],
- [0, 4, 4],
- [0, 0, 0]]
- lBlock = [[5, 5, 5],
- [5, 0, 0],
- [0, 0, 0]]
- jBlock = [[6, 6, 6],
- [0, 0, 6],
- [0, 0, 0]]
- tBlock = [[7, 7, 7],
- [0, 7, 0],
- [0, 0, 0]]
- ###############################################################
- # INITIAL SETUP ###############################################
- # set the screen & caption
- screen = pygame.display.set_mode((WIDTH, HEIGHT))
- pygame.display.set_caption('TETRIS')
- # append all blocks to a single list
- blocks = [oBlock, iBlock, sBlock, zBlock, lBlock, jBlock, tBlock]
- # append colours of blocks to a list
- colours = [YELLOW, LIGHT_BLUE, GREEN, RED, ORANGE, DARK_BlUE, PURPLE]
- # draw main grid - used to hold all of the blocks that are no longer in play (have been dropped)
- mainGrid = makeGrid()
- # initialize activeBlock as an empty list to begin
- activeBlock = []
- # coords for where the active block currently is
- # start a clock to control tick rate
- clock = pygame.time.Clock()
- drawMain()
- ###############################################################
- # GAME LOOP ###################################################
- gameOver = False
- while gameOver is False:
- pygame.display.flip()
- # if there is no active block, create one
- if not activeBlock:
- activeBlock = blocks[random.randint(0, 6)]
- # draw the grid for the piece in play
- activeGrid = makeGrid()
- # add the game piece to the grid
- # the code piece for startX determines the starting position for the block by taking the length
- # and dividing by 2, which is then subtracted from half of the board width
- # for the number of horizontal rows in the block grid
- activeGrid = placePiece(activeGrid, activeBlock, int(5 - len(activeBlock) // 2), 0)
- clock.tick(5)
- # draw the main grid on the bottom. the active grid which
- # holds the moving piece will be layered on top of that
- screen.fill(BLACK)
- tempGrid = movePiece(activeGrid, mainGrid, 1)
- # if the block has not moved
- if tempGrid == activeGrid:
- if collision(tempGrid, mainGrid):
- gameOver = True
- else:
- mainGrid = addToMain(tempGrid, mainGrid)
- activeBlock = []
- activeGrid = makeGrid()
- else:
- activeGrid = tempGrid
- refreshScreen()
- # CONTROLS
- for event in pygame.event.get():
- if event.type == pygame.KEYDOWN:
- # if they press the right arrow key
- if event.key == pygame.K_RIGHT:
- # move the piece one space right
- activeGrid = movePiece(activeGrid, mainGrid, 0, 1)
- # refresh screen
- refreshScreen()
- elif event.key == pygame.K_LEFT:
- # if they press the left arrow key
- activeGrid = movePiece(activeGrid, mainGrid, 0, -1)
- refreshScreen()
- elif event.key == pygame.K_UP:
- activeBlock = rotatePiece(activeBlock)
- activeGrid = makeGrid()
- activeGrid = placePiece(activeGrid, activeBlock, 4, 0)
- refreshScreen()
- elif event.key == pygame.K_DOWN:
- activeGrid = movePiece(activeGrid, mainGrid, 1)
- refreshScreen()
- mainGrid = lineCheck(mainGrid)
- for event in pygame.event.get():
- if event.type == QUIT:
- gameOver = True
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement