Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import math, random, sys, time
- import pygame
- import pygame.gfxdraw
- from pygame.locals import *
- # define some colors
- FUCHSIA = (255, 0, 255)
- PURPLE = (128, 0, 128)
- TEAL = ( 0, 128, 128)
- LIME = ( 0, 255, 0)
- GREEN = ( 0, 128, 0)
- OLIVE = (128, 128, 0)
- YELLOW = (255, 255, 0)
- ORANGE = (255, 165, 0)
- RED = (255, 0, 0)
- MAROON = (128, 0, 0)
- SILVER = (192, 192, 192)
- GREY = (128, 128, 128)
- NIGHT = (32, 32, 32)
- BLUE = ( 0, 0, 255)
- NAVY = ( 0, 0, 128)
- AQUA = ( 0, 255, 255)
- WHITE = (255, 255, 255)
- BLACK = ( 0, 0, 0)
- # define some data
- 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
- 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
- 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
- 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
- 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
- 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
- 7: {'startingY' : [1], 'block' : [[(-1, -1), (0, -1), (-1, 0), (0, 0)]]}, # square
- }
- BLOCK_COLORS = [BLACK, RED, TEAL, ORANGE, NAVY, PURPLE, GREEN, YELLOW]
- SCORES = [40, 100, 300, 1200]
- tetrisFont = {
- 'width' : 10,
- 'height' : 14,
- 'space' : 4,
- 'totalWidth' : 14,
- 'a' : [[0, 5, 5, 0], [5, 0, 10, 5], [10, 5, 10, 14], [0, 7, 10, 7], [0, 14, 0, 5]],
- 'b' : [[0, 0, 5, 0], [5, 0, 10, 4], [10, 4, 5, 7], [5, 7, 10, 10], [10, 10, 5, 14], [5, 14, 0, 14], [0, 14, 0, 0]],
- 'c' : [[0, 0, 10, 0], [0, 0, 0, 14], [0, 14, 10, 14]],
- 'd' : [[0, 0, 5, 0], [5, 0, 10, 5], [10, 5, 10, 9], [10, 9, 5, 14], [5, 14, 0, 14], [0, 14, 0, 0]],
- 'e' : [[0, 0, 10, 0], [0, 0, 0, 14], [0, 7, 8, 7], [0, 14, 10, 14]],
- 'f' : [[0, 0, 10, 0], [0, 0, 0, 14], [0, 7, 8, 7]],
- 'g' : [[0, 0, 10, 0], [0, 0, 0, 14], [0, 14, 10, 14], [10, 14, 10, 9], [10, 9, 8, 7]],
- 'h' : [[0, 0, 0, 14], [0, 7, 10, 7], [10, 0, 10, 14]],
- 'i' : [[0, 0, 10, 0], [5, 0, 5, 14], [0, 14, 10, 14]],
- 'j' : [[0, 9, 5, 14], [5, 14, 10, 14], [10, 14, 10, 0]],
- 'k' : [[0, 0, 0, 14], [0, 7, 10, 0], [0, 7, 10,14]],
- 'l' : [[0, 0, 0, 14], [0, 14, 10, 14]],
- 'm' : [[0, 14, 0, 0], [0, 0, 5, 5], [5, 5, 10, 0], [10, 0, 10, 14]],
- 'n' : [[0, 14, 0, 0], [0, 0, 10, 14], [10, 14, 10, 0]],
- 'o' : [[0, 0, 10, 0], [10, 0, 10, 14], [10, 14, 0, 14], [0, 14, 0, 0]],
- 'p' : [[0, 14, 0, 0], [0, 0, 10, 0], [10, 0, 10, 7], [10, 7, 0, 9]],
- 'q' : [[0, 0, 10, 0], [10, 0, 10, 9], [10, 9, 0, 14], [0, 14, 0, 0], [5, 9, 10, 14]],
- 'r' : [[0, 14, 0, 0], [0, 0, 10, 0], [10, 0, 10, 7], [10, 7, 0, 9], [5, 8, 10, 14]],
- 's' : [[0, 12, 3, 14], [3, 14, 10, 14], [10, 14, 10, 9], [10, 9, 0, 5], [0, 5, 0, 0], [0, 0, 7, 0], [7, 0, 10, 2]],
- 't' : [[0, 0, 10, 0], [5, 0, 5, 14]],
- 'u' : [[0, 0, 0, 9], [0, 9, 5, 14], [5, 14, 10,9], [10, 9, 10, 0]],
- 'v' : [[0, 0, 5, 14], [5, 14, 10, 0]],
- 'w' : [[0, 0, 3, 14], [3, 14, 5, 9], [5, 9, 7, 14], [7, 14, 10, 0]],
- 'x' : [[0, 0, 10, 14], [0, 14, 10, 0]],
- 'y' : [[0, 0, 5, 7], [10, 0, 5, 7], [5, 7, 5, 14]],
- 'z' : [[0, 0, 10, 0], [10, 0, 0, 14], [0, 14, 10, 14]],
- '0' : [[0, 0, 10, 0], [10, 0, 10, 14], [10, 14, 0, 14], [0, 14, 0, 0], [0, 14, 10, 0]],
- '1' : [[3, 3, 5, 0], [5, 0, 5, 14]],
- '2' : [[0, 0, 10, 0], [10, 0, 10, 5], [10, 5, 0, 9], [0, 9, 0, 14], [0, 14, 10, 14]],
- '3' : [[0, 0, 10, 0], [10, 0, 10, 14], [10, 14, 0, 14], [0, 7, 10, 7]],
- '4' : [[0, 0, 0, 7], [0, 7, 10, 7], [10, 0, 10, 14]],
- '5' : [[10, 0, 0, 0], [0, 0, 0, 5], [0, 5, 10, 9], [10, 9, 10, 14], [10, 14, 0, 14]],
- '6' : [[0, 0, 0, 14], [0, 14, 10, 14], [10, 14, 10, 9], [10, 9, 0, 5]],
- '7' : [[0, 0, 10, 0], [10, 0, 10, 7], [10, 7, 5, 14]],
- '8' : [[0, 0, 10, 0], [10, 0, 10, 14], [10, 14, 0, 14], [0, 14, 0, 0], [0, 7, 10, 7]],
- '9' : [[10, 14, 10, 0], [10, 0, 0, 0], [0, 0, 0, 5], [0, 5, 10, 9]],
- ':' : [[5, 3, 5, 5], [5, 9, 5, 11]],
- '.' : [[5, 11, 5, 14]],
- '!' : [[5, 0, 5, 7], [5, 11, 5, 14]],
- }
- # exit the program
- def quit():
- for event in pygame.event.get():
- if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
- return True
- return False
- # this function draws a string to the display surface using the font line data
- def fontSurface(font, text, scale, fgColor):
- width = math.ceil(len(text) * (font['totalWidth'] * scale))
- height = math.ceil(font['height'] * scale)
- surface = pygame.Surface((width, height + 1))
- offset = 0
- for char in text:
- if char != ' ':
- lines = font[char]
- for line in lines:
- sx, sy, ex, ey = (line[0] * scale) + offset, (line[1] * scale), (line[2] * scale) + offset, (line[3] * scale)
- pygame.draw.line(surface, fgColor, (sx, sy), (ex, ey), 1)
- offset += font['totalWidth'] * scale
- surface.set_colorkey(0)
- return surface
- def miniBlock(x, y, blockID):
- global BLOCK_COLORS, BLOCKS
- surface = pygame.display.get_surface()
- block = BLOCKS[blockID]['block'][0]
- for bit in block:
- pygame.draw.rect(surface, BLOCK_COLORS[blockID], (x + bit[0] * 7, y + bit[1] * 7, 7, 7), 0)
- # draw a patterned title
- class tiles:
- def __init__(self):
- global NIGHT, W, H
- self.tileSize = 32
- self.tile = pygame.Surface((self.tileSize, self.tileSize))
- for linePos in range(0, self.tileSize * 2, 8):
- pygame.draw.line(self.tile, NIGHT, (linePos, 0), (linePos - self.tileSize, self.tileSize), 1)
- #self.tile.convert()
- self.displayWidthInTiles = (W / self.tileSize) * self.tileSize
- if W % self.tileSize > 0: self.displayWidthInTiles += self.tileSize
- self.displayHeightInTiles = (H / self.tileSize) * self.tileSize
- if H % self.tileSize > 0: self.displayHeightInTiles += self.tileSize
- def fillDisplay(self, displaySurf):
- global AREAS, W, H
- for tilePosY in range(0, self.displayHeightInTiles, self.tileSize):
- for tilePosX in range(0, self.displayWidthInTiles, self.tileSize):
- displaySurf.blit(self.tile, (tilePosX, tilePosY))
- AREAS.append((0, 0, W, H))
- class blockZone:
- def __init__(self):
- global BLOCKS, W, H
- #define the area in which the blocks fall and stack in
- self.height = (int(H * 0.9722222222222222) / 20) * 20
- self.topMargin = (H - self.height) / 2
- self.blockSize = int(float(self.height) / 20)
- self.width = self.blockSize * 10
- self.leftMargin = (W - self.width) / 2
- self.bzSurf = pygame.Surface((self.width, self.height))
- self.stack = [[0 for x in range(10)] for y in range(20)]
- self.currentBlock = random.randint(1, 7)
- self.rotation = 0
- self.blockPosX = 5
- self.blockPosY = BLOCKS[self.currentBlock]['startingY'][self.rotation]
- self.nextBlock = random.randint(1, 7)
- def blitToDisplay(self, displaySurf):
- global AREAS
- displaySurf.blit(self.bzSurf, (self.leftMargin, self.topMargin))
- AREAS.append((self.leftMargin, self.topMargin, self.width, self.height))
- def drawStack(self):
- global BLOCK_COLORS
- for x in range(10):
- for y in range(20):
- pygame.draw.rect(self.bzSurf, BLOCK_COLORS[self.stack[y][x]], (x * self.blockSize, y * self.blockSize, self.blockSize, self.blockSize), 0)
- def drawBlock(self, delete = False):
- global BLOCKS, BLOCK_COLORS
- block = BLOCKS[self.currentBlock]['block'][self.rotation]
- if delete:
- blockID = 0
- else:
- blockID = self.currentBlock
- for bit in block:
- y = self.blockPosY + bit[1]
- self.stack[y][self.blockPosX + bit[0]] = blockID
- def fall(self):
- global BLOCKS, previousScore
- self.drawBlock(True)
- if self.collisionOnFall():
- self.drawBlock()
- # test for complete lines
- self.testForFullLines()
- self.currentBlock = self.nextBlock
- self.nextBlock = random.randint(1, 7)
- self.rotation = 0
- self.blockPosY = BLOCKS[self.currentBlock]['startingY'][0]
- self.blockPosX = 5
- self.drawBlock()
- previousScore = -1
- SPF = 0
- # test for collision on spawn
- else:
- self.blockPosY += 1
- self.drawBlock()
- def collisionOnFall(self):
- global BLOCKS
- block = BLOCKS[self.currentBlock]['block'][self.rotation]
- tempY = self.blockPosY + 1
- for bit in block:
- x = self.blockPosX + bit[0]
- y = tempY + bit[1]
- if y > 19: return True
- if self.stack[y][x] > 0: return True
- return False
- def collisionOnMove(self, rotate = True):
- global BLOCKS
- if rotate:
- block = BLOCKS[self.currentBlock]['block'][(self.rotation + 1) % len(BLOCKS[self.currentBlock]['block'])]
- else:
- block = BLOCKS[self.currentBlock]['block'][self.rotation]
- for bit in block:
- x = self.blockPosX + bit[0]
- y = self.blockPosY + bit[1]
- if x > 9 or x < 0 or y > 19 or y < 0: return True
- if self.stack[y][x] > 0: return True
- return False
- def testForFullLines(self):
- global SCORES, score, level, lines, FPS, SPF
- popList = []
- for y in range(19, 0, -1):
- if 0 in self.stack[y]:
- continue
- popList.append(y)
- if popList:
- for y in popList:
- self.stack.pop(y)
- for y in popList:
- self.stack.insert(0, [0 for x in range(10)])
- score += SCORES[len(popList) - 1] * level
- lines += len(popList)
- if lines >= 10:
- lines %= 10
- level += 1
- FPS += 0.3
- def rotateBlock(self):
- global BLOCKS
- if not self.collisionOnMove():
- self.rotation += 1
- self.rotation %= len(BLOCKS[self.currentBlock]['block'])
- # define display surface
- W, H = 1280, 720
- HW, HH = W / 2, H / 2
- # initialise display
- pygame.init()
- FONT = pygame.font.SysFont(None, 72)
- DS = pygame.display.set_mode((W, H))
- pygame.display.set_caption("Tetris Clone")
- FPS = 1
- SPF = 1.00 / FPS
- # the areas of the display that need updating
- AREAS = []
- # create the background tiles instance
- TILES = tiles()
- TILES.fillDisplay(DS)
- BZ = blockZone()
- BZ.drawBlock()
- # draw the tetris logo against the side of the stack window
- logo = fontSurface(tetrisFont, "tetris", 8, WHITE)
- verticalLogo = pygame.transform.rotate(logo, 90)
- DS.blit(verticalLogo, (BZ.leftMargin - 10 - verticalLogo.get_rect().width, 10))
- # copy a section of the background for the score and level
- scorePosX = BZ.leftMargin + BZ.width + 10
- scoreRect = (scorePosX, BZ.topMargin, 48, BZ.height)
- scoreBackground = pygame.Surface(scoreRect[2:4])
- scoreBackground.blit(DS, (0, 0), scoreRect)
- # track the score
- previousScore = -1
- score = 0
- # track the level
- level = 1
- # track number of lines completed
- lines = 0
- # monitor key held
- keyHeld = False
- # start FPS monitoring
- FPSTime = time.time()
- # main loop
- while not quit():
- k = pygame.key.get_pressed()
- if k[K_DOWN]:
- SPF = 0.05
- else:
- SPF = 1.00 / FPS
- if k[K_LEFT] and not keyHeld:
- BZ.drawBlock(True)
- BZ.blockPosX -= 1
- if BZ.collisionOnMove(False):
- BZ.blockPosX += 1
- BZ.drawBlock()
- if k[K_RIGHT] and not keyHeld:
- BZ.drawBlock(True)
- BZ.blockPosX += 1
- if BZ.collisionOnMove(False):
- BZ.blockPosX -= 1
- BZ.drawBlock()
- if k[K_UP] and not keyHeld:
- BZ.drawBlock(True)
- BZ.rotateBlock()
- BZ.drawBlock()
- if k[K_RETURN]:
- pygame.image.save(DS, "screenshot.png")
- pygame.quit()
- sys.exit()
- # when a key is pressed it has to be released and pressed again to repeat action
- if True in k[273:277]:
- keyHeld = True
- else:
- keyHeld = False
- BZ.drawStack()
- BZ.blitToDisplay(DS)
- if score != previousScore:
- previousScore = score
- scoreSurf = fontSurface(tetrisFont, "score: {0} level: {1}".format(score, level), 2, WHITE)
- DS.blit(scoreBackground, (scorePosX, BZ.topMargin))
- DS.blit(pygame.transform.rotate(scoreSurf, -90), (scorePosX + 10, BZ.topMargin + 48))
- miniBlock(scorePosX + 17, BZ.topMargin + 10, BZ.nextBlock)
- AREAS.append(scoreRect)
- if time.time() > FPSTime + SPF:
- # test for collision
- BZ.fall()
- FPSTime = time.time()
- pygame.display.update(AREAS)
- AREAS = []
- #DS.fill(BLACK)
- pygame.quit()
- sys.exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement