diff --git a/Project Proposal - Softdes MP4.pdf b/Project Proposal - Softdes MP4.pdf new file mode 100644 index 00000000..ce127a7b Binary files /dev/null and b/Project Proposal - Softdes MP4.pdf differ diff --git a/README.md b/README.md index 5f822327..f9592d30 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,13 @@ # InteractiveProgramming This is the base repo for the interactive programming project for Software Design, Spring 2018 at Olin College. + +Installation Guide: + +pip install pygame +pip install numpy +pip install random +pip install sys +pip install time +pip install copy + +to run game, run command: python3 Tetris.py diff --git a/Tetris.ipynb b/Tetris.ipynb new file mode 100644 index 00000000..d1679235 --- /dev/null +++ b/Tetris.ipynb @@ -0,0 +1,287 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 106, + "metadata": {}, + "outputs": [], + "source": [ + "import pygame\n", + "from pygame.locals import *\n", + "import numpy\n", + "import random\n", + "import sys\n", + "import time\n", + "\n", + "FPS = 25\n", + "WindowWidth = 450 #used to be 415\n", + "WindowHeight = 900 #used to be 815\n", + "BoxSize = 30\n", + "BoardWidth = 20\n", + "BoardHeight = 40\n", + "BorderColor = (255,255,255)\n", + "BGColor = (0, 0, 0)\n", + "TemplateWidth = 15\n", + "TemplateHeight = 15\n", + "\n", + "XMargin = int((WindowWidth - BoardWidth * BoxSize)/2)\n", + "TopMargin = WindowHeight - (BoardHeight * BoxSize) -5\n", + "\n", + "#Templates of pieces:\n", + "\n", + "S_Shape = [[[180,0], [225,0], [135,45], [180,45]], [[180,0],[180,45],[225,45],[225,90]]]\n", + "\n", + "Z_Shape = [[[135,0],[180,0],[180,45],[225,45]],[[225,0],[225,45],[180,45],[180,90]]]\n", + "\n", + "I_Shape = [[[180,0],[180,45],[180,90],[180,135]],[[135,0],[180,0],[225,0],[270,0]]]\n", + "\n", + "O_Shape = [[180,45],[225,45],[180,90],[225,90]]\n", + "\n", + "J_Shape = [[[180,45],[180,90],[225,90],[270,90]], [[180,0],[225,0],[180,45],[180,90]],[[180,45],[225,45],[270,45],[270,90]], [[225,0],[225,45],[225,90],[180,90]]]\n", + "\n", + "L_Shape = [[[180,45],[225,45],[270,45],[270,0]],[[180,0],[180,45],[180,90],[225,90]],[[180,45],[225,45],[270,45],[180,90]], [[180,0],[225,0],[225,45],[225,90]]]\n", + "\n", + "T_Shape = [[[180,0],[135,45],[180,45],[225,45]],[[180,0],[180,45],[180,90],[225,45]], [[180,45],[225,45],[270,45],[225,90]],[[225,0],[225,45],[225,90],[180,45]]]\n", + "\n", + "\n", + " \n", + "Pieces = {'S': [[[180,0], [225,0], [135,45], [180,45]], [[180,0],[180,45],[225,45],[225,90]]],\n", + " 'Z': Z_Shape,\n", + " 'J': J_Shape,\n", + " 'L': L_Shape,\n", + " 'I': I_Shape,\n", + " 'O': O_Shape,\n", + " 'T': T_Shape}\n", + "\n", + "Coordinates = {'1': [135,0],\n", + " '2': [180,0],\n", + " '3': [225,0],\n", + " '4': [270,0],\n", + " '5': [135,45],\n", + " '6': [180,45],\n", + " '7': [225,45],\n", + " '8': [270,45],\n", + " '9': [135,90],\n", + " '10': [180,90],\n", + " '11': [225,90],\n", + " '12': [270,90],\n", + " '13': [135,135],\n", + " '14': [180,135],\n", + " '15': [225,135],\n", + " '16': [270,135]}\n", + "\n", + "\n", + "\n", + "\n", + "class Block():\n", + " def __init__(self,width,height,x1,y1,val):\n", + " self.width = width\n", + " self.height = height\n", + " self.x1 = x1\n", + " self.y1 = y1\n", + " self.val = val\n", + " \n", + " def convertToPixelCoords(self):\n", + " return (XMargin + (self.x1 * BoxSize),(TopMargin +(self.y1 * BoxSize)))\n", + " \n", + " def drawBlock(self, pixelx = None, pixely = None):\n", + " if self.val == 0:\n", + " return \n", + " if pixelx == None and pixely == None:\n", + " pixelx,pixely = convertToPixelCoords(self.x1, self.y1)\n", + " pygame.draw.rect(DisplaySurf, (0,0,0), (pixelx + 1, pixely + 1, BoxSize - 1, BoxSize - 1))\n", + " pygame.draw.rect(DisplaySurf, (34,89,233), (pixelx + 1, pixely + 1, BoxSize - 4, BoxSize - 4))\n", + " \n", + " def __str__(self):\n", + " return 'Coords are: (%.d, %.d) with val %.d' %(self.x1,self.y1,self.val)\n", + " \n", + "class Piece():\n", + " def __init__(self):\n", + " self.shape = random.choice(list(Pieces.keys()))\n", + " self.rotation = int(random.randint(0,len(Pieces[self.shape])-1))\n", + " \n", + " self.coordinates = []\n", + " \n", + " \n", + " \n", + " b1 = Block(20,20,Pieces[self.shape][self.rotation][0][0],Pieces[self.shape][self.rotation][0][1],1)\n", + " b2 = Block(20,20,Pieces[self.shape][self.rotation][1][0],Pieces[self.shape][self.rotation][1][1],1)\n", + " b3 = Block(20,20,Pieces[self.shape][self.rotation][2][0],Pieces[self.shape][self.rotation][2][1],1)\n", + " b4 = Block(20,20,Pieces[self.shape][self.rotation][3][0],Pieces[self.shape][self.rotation][3][1],1)\n", + " print(b1,b2,b3,b4)\n", + " self.blocks = [b1,b2,b3,b4]\n", + " print(self.blocks)\n", + " \n", + " def convertToShapeCoords(self):\n", + " \n", + " for i in self.shape[self.rotation]:\n", + " self.coordinates = self.coordinates.append(Coordinates[Shapes[self.rotation][i]])\n", + " \n", + " def drawPiece(self,pixelx=None,pixely=None):\n", + " \n", + " if b.val == 0:\n", + " return \n", + " if pixelx == None and pixely == None:\n", + " pixelx = b.x1\n", + " pixely = b.y1\n", + "\n", + " pygame.draw.rect(DisplaySurf, (0,0,0), (pixelx + 1, pixely + 1, BoxSize - 1, BoxSize - 1))\n", + " pygame.draw.rect(DisplaySurf, (34,89,233), (pixelx + 1, pixely + 1, BoxSize - 4, BoxSize - 4))\n", + " \n", + " def translate():\n", + " #Loop through blocks and change x y coords\n", + " #localize block to its own coordinate system, so that it can be defined by one point\n", + " #Need a get-block positions () function to get block x and y coords\n", + " pass\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "class Grid():\n", + " def __init__(self, width, height):\n", + " self.width = width\n", + " self.height = height\n", + " self.grid = []\n", + " def append(self, thing):\n", + " self.grid.append(thing)\n", + " def make_grid(self):\n", + " grid = []\n", + " for i in range(self.width):\n", + " self.append([0] * self.height)\n", + " return grid\n", + " \n", + " def draw_grid(self):\n", + " #Draws the grid\n", + " pygame.draw.rect(DisplaySurf, BorderColor, (XMargin - 3, TopMargin - 7, (BoardWidth * BoxSize) + 8, (BoardHeight * BoxSize) + 8), 5)\n", + " \n", + " #Fill Background of board\n", + " pygame.draw.rect(DisplaySurf, BGColor, (XMargin, TopMargin, BoxSize * BoardWidth, BoxSize * BoardHeight))\n", + " \n", + " #Draw individual boxes\n", + " #or x in range (BoardWidth):\n", + " #or y in range(BoardHeight):\n", + " #elf.block.drawBlock(x,y)\n", + " \n", + " def addToBoard(self, block):\n", + " for x in range(TemplateWidth):\n", + " for y in range(TemplateHeight):\n", + " if block.val == 1:\n", + " block.drawBlock(x + block.x1, y + block.y1)\n", + " \n", + " def addShape(self,piece):\n", + " for block in piece.blocks:\n", + " for x in range(TemplateWidth):\n", + " for y in range(TemplateHeight):\n", + " if block.val == 1:\n", + " block.drawBlock(x + block.x1, y + block.y1)\n", + " \n", + "def checkForQuit():\n", + " for event in pygame.event.get(QUIT): # get all the QUIT events\n", + " terminate() # terminate if any QUIT events are present\n", + " for event in pygame.event.get(KEYUP): # get all the KEYUP events\n", + " if event.key == K_ESCAPE:\n", + " terminate() # terminate if the KEYUP event was for the Esc key\n", + " pygame.event.post(event) # put the other KEYUP event objects back\n", + " \n", + "def checkForKeyPress():\n", + " # Go through event queue looking for a KEYUP event.\n", + " # Grab KEYDOWN events to remove them from the event queue.\n", + " checkForQuit()\n", + "\n", + " for event in pygame.event.get([KEYDOWN, KEYUP]):\n", + " if event.type == KEYDOWN:\n", + " continue\n", + " return event.key\n", + " return None\n" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coords are: (135, 0) with val 1 Coords are: (180, 0) with val 1 Coords are: (180, 45) with val 1 Coords are: (225, 45) with val 1\n", + "[<__main__.Block object at 0x7fb702296a90>, <__main__.Block object at 0x7fb702296f98>, <__main__.Block object at 0x7fb702296e10>, <__main__.Block object at 0x7fb7022962e8>]\n", + "<__main__.Piece object at 0x7fb70226e6a0>\n" + ] + } + ], + "source": [ + "def main():\n", + " global FPSClock, DisplaySurf, BasicFont, BigFont, BorderColor\n", + " pygame.init()\n", + " DisplaySurf = pygame.display.set_mode((WindowWidth, WindowHeight))\n", + " runGame()\n", + " \n", + "def runGame():\n", + " \n", + " piece = Piece()\n", + " print(piece)\n", + " grid = Grid(20, 40)\n", + " grid.make_grid()\n", + " grid.draw_grid()\n", + " grid.addShape(piece)\n", + " \n", + " \n", + " pygame.display.update()\n", + "\n", + "def terminate():\n", + " pygame.quit()\n", + " sys.exit()\n", + " \n", + " \n", + "if __name__ == '__main__':\n", + " main()\n", + " \n", + " \n", + "\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Tetris.pdf b/Tetris.pdf new file mode 100644 index 00000000..1952ed8a Binary files /dev/null and b/Tetris.pdf differ diff --git a/Tetris.py b/Tetris.py new file mode 100644 index 00000000..6736ea7c --- /dev/null +++ b/Tetris.py @@ -0,0 +1,349 @@ +import pygame +from pygame.locals import * +import numpy +import random +import sys +import time +import copy + +MOVEDOWNFREQ = 0.1 +MOVESIDEWAYSFREQ = 0.15 + +#Colors for reference + +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) + +#2048 Colors: +NUM2 = (255,177,120) +NUM4 = (237, 224, 200) +NUM8 = (242, 177, 121) +NUM16 = (245,149,99) +NUM32 = (255, 83, 13) +NUM64 = (255,10,10) +NUM128 = (237,207,114) +NUM2048 = (237,194,46) + +#List of colors so that we can randomly choose one: +Colors = [NUM2,NUM4,NUM8,NUM16,NUM32,NUM64,NUM128,NUM2048] + +BORDERCOLOR = BLUE +BGCOLOR = BLACK +TEXTCOLOR = WHITE +TEXTSHADOWCOLOR = GRAY + +# Global variables for creating the board +FPS = 25 +WindowWidth = 450 #used to be 415 +WindowHeight = 900 #used to be 815 +BoxSize = 30 +BoardWidth = 20 +BoardHeight = 40 +BorderColor = (255,255,255) +BGColor = (0, 0, 0) +TemplateWidth = 15 +TemplateHeight = 15 + +XMargin = int((WindowWidth - BoardWidth * BoxSize)/2) +TopMargin = WindowHeight - (BoardHeight * BoxSize) -5 + +#Templates of pieces: + +S_Shape = [[[180,0], [225,0], [135,45], [180,45]], [[180,0],[180,45],[225,45],[225,90]]] + +Z_Shape = [[[135,0],[180,0],[180,45],[225,45]],[[225,0],[225,45],[180,45],[180,90]]] + +I_Shape = [[[180,0],[180,45],[180,90],[180,135]],[[135,0],[180,0],[225,0],[270,0]]] + +O_Shape = [[[180,45],[225,45],[180,90],[225,90]]] + +J_Shape = [[[180,45],[180,90],[225,90],[270,90]], [[180,0],[225,0],[180,45],[180,90]],[[180,45],[225,45],[270,45],[270,90]], [[225,0],[225,45],[225,90],[180,90]]] + +L_Shape = [[[180,45],[225,45],[270,45],[270,0]],[[180,0],[180,45],[180,90],[225,90]],[[180,45],[225,45],[270,45],[180,90]], [[180,0],[225,0],[225,45],[225,90]]] + +T_Shape = [[[180,0],[135,45],[180,45],[225,45]],[[180,0],[180,45],[180,90],[225,45]], [[180,45],[225,45],[270,45],[225,90]],[[225,0],[225,45],[225,90],[180,45]]] + + +#Dictionary of Pieces to choose randomly from +Pieces = {'S': S_Shape, + 'Z': Z_Shape, + 'J': J_Shape, + 'L': L_Shape, + 'I': I_Shape, + 'O': O_Shape, + 'T': T_Shape} + +class Block(): #Defines attributes of singular block + def __init__(self,width,height,x1,y1,val): + self.width = width + self.height = height + self.x1 = x1 + self.y1 = y1 + self.val = val + self.color = random.choice(Colors) + + def convertToPixelCoords(self): + return (XMargin + (self.x1 * BoxSize),(TopMargin +(self.y1 * BoxSize))) + + def drawBlock(self, pixelx = None, pixely = None): + """ Draws a block on the board """ + if self.val == 0: + return + if pixelx == None and pixely == None: + pixelx,pixely = convertToPixelCoords(self.x1, self.y1) + pygame.draw.rect(DisplaySurf, (0,0,0), (pixelx + 1, pixely + 1, BoxSize - 1, BoxSize - 1)) + pygame.draw.rect(DisplaySurf, self.color, (pixelx + 1, pixely + 1, BoxSize - 4, BoxSize - 4)) + + def __str__(self): + """print statement for debugging purposes""" + return 'Coords are: (%.d, %.d) with val %.d' %(self.x1,self.y1,self.val) + +class Piece(): + # Piece is a list of block objects + def __init__(self): + self.shape = random.choice(list(Pieces.keys())) + self.rotation = 0 + # Defining blocks of shape + b1 = Block(20,20,Pieces[self.shape][self.rotation][0][0],Pieces[self.shape][self.rotation][0][1],1) + b2 = Block(20,20,Pieces[self.shape][self.rotation][1][0],Pieces[self.shape][self.rotation][1][1],1) + b3 = Block(20,20,Pieces[self.shape][self.rotation][2][0],Pieces[self.shape][self.rotation][2][1],1) + b4 = Block(20,20,Pieces[self.shape][self.rotation][3][0],Pieces[self.shape][self.rotation][3][1],1) + + self.blocks = [b1,b2,b3,b4] + + def rotatePiece(self): + """Redefines piece according to next rotation, and adds back distance from start""" + xdiff = self.blocks[0].x1 - Pieces[self.shape][self.rotation][0][0] + ydiff = self.blocks[0].y1 - Pieces[self.shape][self.rotation][0][1] + + # Increasing index of rotation (To switch to rotated template), looping back to first when reached the end + if self.rotation < len(Pieces[self.shape]) - 1: + self.rotation += 1 + else: + self.rotation = 0 + # Redefining piece based on new rotation. Also has fun side effect of making piece change color + self.blocks[0] = Block(20,20,Pieces[self.shape][self.rotation][0][0]+xdiff ,Pieces[self.shape][self.rotation][0][1]+ydiff,1) + self.blocks[1] = Block(20,20,Pieces[self.shape][self.rotation][1][0]+xdiff ,Pieces[self.shape][self.rotation][1][1]+ydiff,1) + self.blocks[2] = Block(20,20,Pieces[self.shape][self.rotation][2][0]+xdiff ,Pieces[self.shape][self.rotation][2][1]+ydiff,1) + self.blocks[3] = Block(20,20,Pieces[self.shape][self.rotation][3][0]+xdiff ,Pieces[self.shape][self.rotation][3][1]+ydiff,1) + + def down(self): + """Moving block down one block""" + for block in self.blocks: + block.y1 += 45 + + def left(self): + """ Moving block left one block """ + for block in self.blocks: + block.x1 -= 45 + + def right(self): + """ Moving block right one block""" + for block in self.blocks: + block.x1 += 45 + + def gameover(self): + """ Tells you when block has stacked to top """ + for block in self.blocks: + if block.y1 <= 0: + return True + return False + +class Grid(): + """ Grid is an array spanning the size of the board, and you can store markers + inside it to tell you where the pieces are.""" + def __init__(self, width, height): + self.width = width + self.height = height + self.grid = [] + for i in range(450): + self.grid.append([0] * 900) + + def draw_grid(self): + #Draws the grid + pygame.draw.rect(DisplaySurf, BorderColor, (XMargin - 3, TopMargin - 7, (BoardWidth * BoxSize) + 8, (BoardHeight * BoxSize) + 8), 5) + + #Fill Background of board + pygame.draw.rect(DisplaySurf, BGColor, (XMargin, TopMargin, BoxSize * BoardWidth, BoxSize * BoardHeight)) + + #Draw already placed pieces + for x in range (450): + for y in range(900): + if self.grid[x][y] != 0: + pygame.draw.rect(DisplaySurf, self.grid[x][y], (x + 1, y + 1, 45 - 4, 45 - 4)) + + def addToBoard(self, piece): + """ Makes piece permanently part of the board when it's reached its final position""" + for block in piece.blocks: + for x in range(450): + for y in range(900): + if x == block.x1 and y == block.y1: + self.grid[x][y] = block.color + + def addShape(self,piece): + """ draws a piece on the board """ + for block in piece.blocks: + for x in range(TemplateWidth): + for y in range(TemplateHeight): + if block.val == 1: + block.drawBlock(x + block.x1, y + block.y1) + +def checkForQuit(): + """ Quits the game """ + 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 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 makeTextObjs(text, font, color): + surf = font.render(text, True, color) + return surf, surf.get_rect() + +def showTextScreen(text): + """large text in the center of the screen until a key is pressed and + draws 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() + +def isValidPosition(board, piece, adjx = 0, adjy = 0): + # Return True if the piece is within the board and not colliding + for block in piece.blocks: + if block.x1 + (adjx*45) >= 405: + return False + if block.x1 + (adjx*45) <= 0: + return False + if block.y1 + (adjy*45) > 855: + return False + if board.grid[block.x1 + (adjx * 45)][block.y1 + (adjy * 45)] != 0: + return False + return True + +def main(): + global FPSCLOCK, DisplaySurf, BASICFONT, BIGFONT, BorderColor + 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', 80) + pygame.display.set_caption('Tetris!') + + showTextScreen('Tetris') + while True: # infinite game loop + runGame() + showTextScreen('Game Over') + +def runGame(): + # Initializing variables + board = Grid(20,40) + movingDown = False # note: there is no movingUp variable + movingLeft = False + movingRight = False + + fallingPiece = Piece() + + while True: # game loop + movingDown = False # note: there is no movingUp variable + movingLeft = False + movingRight = False + rotate = False + + if not isValidPosition(board, fallingPiece) and fallingPiece.gameover() == True: + return # can't fit a new piece on the board, so game over + + checkForQuit() + for event in pygame.event.get(): # event handling loop + if event.type == KEYUP: #Lifting the hand from the key + if (event.key == K_p): + # Pausing the game (Press P) + DisplaySurf.fill(BGCOLOR) + + showTextScreen('Paused') # pause until a key press + + elif event.type == KEYDOWN: #Pressing a key + # moving the piece sideways + if (event.key == K_LEFT or event.key == K_a) : + movingLeft = True + movingRight = False + + elif (event.key == K_RIGHT or event.key == K_d): + movingRight = True + movingLeft = False + + # rotating the piece (if there is room to rotate) + elif (event.key == K_UP or event.key == K_w): + rotate = True + + # making the piece fall faster with the down key + elif (event.key == K_DOWN or event.key == K_s): + movingDown = True + + # drawing everything on the screen + DisplaySurf.fill(BGCOLOR) + board.draw_grid() + board.addShape(fallingPiece) + + """ Actually moving the piece """ + if movingLeft == True and isValidPosition(board,fallingPiece,adjx=-1): + fallingPiece.left() + if movingRight == True and isValidPosition(board,fallingPiece,adjx=1): + fallingPiece.right() + if movingDown == True and isValidPosition(board,fallingPiece,adjy=1): + fallingPiece.down() + if rotate == True: + temp = copy.deepcopy(fallingPiece) + temp.rotatePiece() + if isValidPosition(board,temp): + fallingPiece.rotatePiece() + + if isValidPosition(board,fallingPiece,adjy=1): + fallingPiece.down() + else: #if piece has reached the bottom + board.addToBoard(fallingPiece) # Makes fallingPiece a part of the board drawn every step + fallingPiece = Piece() + + pygame.display.update() + FPSCLOCK.tick(20) + pygame.time.delay(250) + +def terminate(): + pygame.quit() + +if __name__ == '__main__': + main()