Advertisement
cookertron

Tetris Clone using Python & Pygame

Oct 28th, 2018
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.38 KB | None | 0 0
  1. import math, random, sys, time
  2. import pygame
  3. import pygame.gfxdraw
  4. from pygame.locals import *
  5.  
  6. # define some colors
  7. FUCHSIA = (255,   0, 255)
  8. PURPLE  = (128,   0, 128)
  9. TEAL    = (  0, 128, 128)
  10. LIME    = (  0, 255,   0)
  11. GREEN   = (  0, 128,   0)
  12. OLIVE   = (128, 128,   0)
  13. YELLOW  = (255, 255,   0)
  14. ORANGE  = (255, 165,   0)
  15. RED     = (255,   0,   0)
  16. MAROON  = (128,   0,   0)
  17. SILVER  = (192, 192, 192)
  18. GREY    = (128, 128, 128)
  19. NIGHT   = (32,   32,  32)
  20. BLUE    = (  0,   0, 255)
  21. NAVY    = (  0,   0, 128)
  22. AQUA    = (  0, 255, 255)
  23. WHITE   = (255, 255, 255)
  24. BLACK   = (  0,   0,   0)
  25.  
  26. # define some data
  27. BLOCKS = {1: {'startingY' : [0, 2, 0, 2], 'block' : [[(-1, 0), (0, 0), (1, 0), (2, 0)], [(1, -2), (1, -1), (1, 0), (1, 1)], [(-1, 0), (0, 0), (1, 0), (2, 0)], [(0, -2), (0, -1), (0, 0), (0, 1)]]}, # long one
  28.           2: {'startingY' : [0, 1, 0, 1], 'block' : [[(-1, 0), (0, 0), (1, 0), (0, 1)], [(-1, 0), (0, -1), (0, 0), (0, 1)], [(0, 0), (-1, 1), (0, 1), (1, 1)], [(0, -1), (0, 0), (0, 1), (1, 0)]]}, # T shape
  29.           3: {'startingY' : [0, 1, 0, 1], 'block' : [[(-1, 1), (-1, 0), (0, 0), (1, 0)], [(-1, -1), (0, -1), (0, 0), (0, 1)], [(1, 0), (-1, 1), (0, 1), (1, 1)], [(0, -1), (0, 0), (0, 1), (1, 1)]]}, # L left
  30.           4: {'startingY' : [0, 1, 0, 1], 'block' : [[(-1, 0), (0, 0), (1, 0), (1, 1)], [(0, -1), (0, 0), (0, 1), (-1, 1)], [(-1, 0), (-1, 1), (0, 1), (1, 1)], [(0, -1), (0, 0), (0, 1), (1, -1)]]}, # L right
  31.           5: {'startingY' : [0, 1, 0, 1], 'block' : [[(-1, 0), (0, 0), (0, 1), (1, 1)], [(1, -1), (1, 0), (0, 0), (0, 1)], [(-1, 0), (0, 0), (0, 1), (1, 1)], [(0, -1), (0, 0), (-1, 0), (-1, 1)]]}, # lightening 1
  32.           6: {'startingY' : [0, 1, 0, 1], 'block' : [[(-1, 1), (0, 1), (0, 0), (1, 0)], [(0, -1), (0, 0), (1, 0), (1, 1)], [(-1, 1), (0, 1), (0, 0), (1, 0)], [(-1, -1), (-1, 0), (0, 0), (0, 1)]]}, # lightening 2
  33.           7: {'startingY' : [1], 'block' : [[(-1, -1), (0, -1), (-1, 0), (0, 0)]]}, # square
  34.  
  35.           }
  36.  
  37. BLOCK_COLORS = [BLACK, RED, TEAL, ORANGE, NAVY, PURPLE, GREEN, YELLOW]
  38.  
  39. # exit the program
  40. def quit():
  41.     for event in pygame.event.get():
  42.         if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
  43.             return True
  44.     return False
  45.  
  46. # draw a patterned title
  47. class tiles:
  48.     def __init__(self):
  49.         global NIGHT, W, H
  50.        
  51.         self.tileSize = 32
  52.         self.tile = pygame.Surface((self.tileSize, self.tileSize))
  53.        
  54.         for linePos in range(0, self.tileSize * 2, 8):
  55.             pygame.draw.line(self.tile, NIGHT, (linePos, 0), (linePos - self.tileSize, self.tileSize), 1)
  56.        
  57.         #self.tile.convert()       
  58.         self.displayWidthInTiles = (W / self.tileSize) * self.tileSize
  59.         if W % self.tileSize > 0: self.displayWidthInTiles += self.tileSize
  60.  
  61.         self.displayHeightInTiles = (H / self.tileSize) * self.tileSize
  62.         if H % self.tileSize > 0: self.displayHeightInTiles += self.tileSize
  63.  
  64.         print self.displayWidthInTiles, self.displayHeightInTiles
  65.  
  66.     def fillDisplay(self, displaySurf):
  67.         global AREAS, W, H
  68.         for tilePosY in range(0, self.displayHeightInTiles, self.tileSize):
  69.             for tilePosX in range(0, self.displayWidthInTiles, self.tileSize):
  70.                 displaySurf.blit(self.tile, (tilePosX, tilePosY))
  71.         AREAS.append((0, 0, W, H))
  72.        
  73. class blockZone:
  74.     def __init__(self):
  75.         global BLOCKS, W, H
  76.        
  77.         #define the area in which the blocks fall and stack in
  78.         self.height = (int(H * 0.9722222222222222) / 20) * 20
  79.         self.topMargin = (H - self.height) / 2     
  80.  
  81.         self.blockSize = int(float(self.height) / 20)
  82.        
  83.         self.width = self.blockSize * 10
  84.         self.leftMargin = (W - self.width) / 2
  85.        
  86.         self.bzSurf = pygame.Surface((self.width, self.height))
  87.    
  88.         self.stack = [[0 for y in range(20)] for x in range(10)]
  89.        
  90.         self.currentBlock = random.randint(1, 7)
  91.         self.rotation = 0
  92.         self.blockPosX = 5
  93.         self.blockPosY = BLOCKS[self.currentBlock]['startingY'][self.rotation]
  94.         self.nextBlock = random.randint(1, 7)
  95.        
  96.     def blitToDisplay(self, displaySurf):
  97.         global AREAS
  98.         displaySurf.blit(self.bzSurf, (self.leftMargin, self.topMargin))
  99.         AREAS.append((self.leftMargin, self.topMargin, self.width, self.height))
  100.    
  101.     def drawStack(self):
  102.         global BLOCK_COLORS
  103.         for x in range(10):
  104.             for y in range(20):
  105.                 pygame.draw.rect(self.bzSurf, BLOCK_COLORS[self.stack[x][y]], (x * self.blockSize, y * self.blockSize, self.blockSize, self.blockSize), 0)
  106.        
  107.     def drawBlock(self, delete = False):
  108.         global BLOCKS, BLOCK_COLORS
  109.        
  110.         block = BLOCKS[self.currentBlock]['block'][self.rotation]
  111.         if delete:
  112.             blockID = 0
  113.         else:
  114.             blockID = self.currentBlock
  115.            
  116.         for bit in block:
  117.             y = self.blockPosY + bit[1]
  118.             self.stack[self.blockPosX + bit[0]][y] = blockID
  119.    
  120.     def fall(self):
  121.         global BLOCKS
  122.         self.drawBlock(True)
  123.         if self.collisionOnFall():
  124.             self.drawBlock()
  125.             self.currentBlock = self.nextBlock
  126.             self.nextBlock = random.randint(1, 7)
  127.             self.rotation = 0
  128.             self.blockPosY = BLOCKS[self.currentBlock]['startingY'][0]
  129.             self.blockPosX = 5
  130.             self.drawBlock()
  131.         else:
  132.             self.blockPosY += 1
  133.             self.drawBlock()
  134.    
  135.     def collisionOnFall(self):
  136.         global BLOCKS
  137.         block = BLOCKS[self.currentBlock]['block'][self.rotation]
  138.        
  139.         tempY = self.blockPosY + 1
  140.         for bit in block:
  141.             x = self.blockPosX + bit[0]
  142.             y = tempY + bit[1]
  143.             if y > 19: return True
  144.             if self.stack[x][y] > 0: return True
  145.            
  146.         return False
  147.        
  148.     def collisionOnMove(self, rotate = True):
  149.         global BLOCKS
  150.        
  151.         if rotate:
  152.             block = BLOCKS[self.currentBlock]['block'][(self.rotation + 1) % len(BLOCKS[self.currentBlock]['block'])]
  153.         else:
  154.             block = BLOCKS[self.currentBlock]['block'][self.rotation]
  155.            
  156.         for bit in block:
  157.             x = self.blockPosX + bit[0]
  158.             y = self.blockPosY + bit[1]
  159.             if x > 9 or x < 0 or y > 19 or y < 0: return True
  160.             if self.stack[x][y] > 0: return True
  161.        
  162.         return False
  163.        
  164.     def rotateBlock(self):
  165.         global BLOCKS
  166.         if not self.collisionOnMove():
  167.             self.rotation += 1
  168.             self.rotation %= len(BLOCKS[self.currentBlock]['block'])
  169.    
  170. # define display surface           
  171. W, H = 1280, 720
  172. HW, HH = W / 2, H / 2
  173.  
  174. # initialise display
  175. pygame.init()
  176. FONT = pygame.font.SysFont(None, 72)
  177. DS = pygame.display.set_mode((W, H))
  178. pygame.display.set_caption("Tetris Clone")
  179. FPS = 1
  180. SPF = 1.00 / FPS
  181.  
  182. # the areas of the display that need updating
  183. AREAS = []
  184.  
  185. # create the background tiles instance
  186. TILES = tiles()
  187. TILES.fillDisplay(DS)
  188.  
  189. BZ = blockZone()
  190. BZ.drawBlock()
  191.  
  192. # start FPS monitoring
  193. FPSTime = time.time()
  194.  
  195. # monitor key held
  196. keyHeld = False
  197.  
  198. # main loop
  199. while not quit():
  200.     k = pygame.key.get_pressed()
  201.    
  202.     if k[K_DOWN]:
  203.         SPF = 1.00 / (FPS * 20)
  204.     else:
  205.         SPF = 1.00 / FPS
  206.  
  207.     if k[K_LEFT] and not keyHeld:
  208.         BZ.drawBlock(True)         
  209.         BZ.blockPosX -= 1
  210.         print BZ.blockPosX
  211.         if BZ.collisionOnMove(False):
  212.             BZ.blockPosX += 1
  213.         BZ.drawBlock()
  214.    
  215.     if k[K_RIGHT] and not keyHeld:
  216.         BZ.drawBlock(True)         
  217.         BZ.blockPosX += 1
  218.         print BZ.blockPosX
  219.         if BZ.collisionOnMove(False):
  220.             BZ.blockPosX -= 1
  221.         BZ.drawBlock()
  222.    
  223.     if k[K_UP] and not keyHeld:
  224.         BZ.drawBlock(True)
  225.         BZ.rotateBlock()
  226.         BZ.drawBlock()
  227.        
  228.     if k[K_RETURN]:
  229.         pygame.image.save(DS, "screenshot.png")
  230.         pygame.quit()
  231.         sys.exit()
  232.  
  233.     # when a key is pressed it has to be released and pressed again to repeat action
  234.     if True in k[273:277]:
  235.         keyHeld = True
  236.     else:
  237.         keyHeld = False
  238.  
  239.        
  240.     BZ.drawStack()
  241.     BZ.blitToDisplay(DS)
  242.  
  243.     if time.time() > FPSTime + SPF:
  244.         # test for collision
  245.         BZ.fall()
  246.         FPSTime = time.time()
  247.    
  248.     pygame.display.update(AREAS)
  249.     AREAS = []
  250.        
  251.     #DS.fill(BLACK)
  252. pygame.quit()
  253. sys.exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement