Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Tetris-Game/main.py /
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
401 lines (316 sloc)
10.2 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import pygame | |
| import random | |
| """ | |
| 10 x 20 square grid | |
| shapes: S, Z, I, O, J, L, T | |
| represented in order by 0 - 6 | |
| """ | |
| pygame.font.init() | |
| # GLOBALS VARS | |
| s_width = 800 | |
| s_height = 700 | |
| play_width = 300 # meaning 300 // 10 = 30 width per block | |
| play_height = 600 # meaning 600 // 20 = 20 height per blo ck | |
| block_size = 30 | |
| top_left_x = (s_width - play_width) // 2 | |
| top_left_y = s_height - play_height | |
| # SHAPE FORMATS | |
| S = [['.....', | |
| '.....', | |
| '..00.', | |
| '.00..', | |
| '.....'], | |
| ['.....', | |
| '..0..', | |
| '..00.', | |
| '...0.', | |
| '.....']] | |
| Z = [['.....', | |
| '.....', | |
| '.00..', | |
| '..00.', | |
| '.....'], | |
| ['.....', | |
| '..0..', | |
| '.00..', | |
| '.0...', | |
| '.....']] | |
| I = [['..0..', | |
| '..0..', | |
| '..0..', | |
| '..0..', | |
| '.....'], | |
| ['.....', | |
| '0000.', | |
| '.....', | |
| '.....', | |
| '.....']] | |
| O = [['.....', | |
| '.....', | |
| '.00..', | |
| '.00..', | |
| '.....']] | |
| J = [['.....', | |
| '.0...', | |
| '.000.', | |
| '.....', | |
| '.....'], | |
| ['.....', | |
| '..00.', | |
| '..0..', | |
| '..0..', | |
| '.....'], | |
| ['.....', | |
| '.....', | |
| '.000.', | |
| '...0.', | |
| '.....'], | |
| ['.....', | |
| '..0..', | |
| '..0..', | |
| '.00..', | |
| '.....']] | |
| L = [['.....', | |
| '...0.', | |
| '.000.', | |
| '.....', | |
| '.....'], | |
| ['.....', | |
| '..0..', | |
| '..0..', | |
| '..00.', | |
| '.....'], | |
| ['.....', | |
| '.....', | |
| '.000.', | |
| '.0...', | |
| '.....'], | |
| ['.....', | |
| '.00..', | |
| '..0..', | |
| '..0..', | |
| '.....']] | |
| T = [['.....', | |
| '..0..', | |
| '.000.', | |
| '.....', | |
| '.....'], | |
| ['.....', | |
| '..0..', | |
| '..00.', | |
| '..0..', | |
| '.....'], | |
| ['.....', | |
| '.....', | |
| '.000.', | |
| '..0..', | |
| '.....'], | |
| ['.....', | |
| '..0..', | |
| '.00..', | |
| '..0..', | |
| '.....']] | |
| shapes = [S, Z, I, O, J, L, T] | |
| shape_colors = [(0, 255, 0), (255, 0, 0), (0, 255, 255), (255, 255, 0), (255, 165, 0), (0, 0, 255), (128, 0, 128)] | |
| # index 0 - 6 represent shape | |
| class Piece(object): | |
| rows = 20 # y | |
| columns = 10 # x | |
| def __init__(self, column, row, shape): | |
| self.x = column | |
| self.y = row | |
| self.shape = shape | |
| self.color = shape_colors[shapes.index(shape)] | |
| self.rotation = 0 # number from 0-3 | |
| def create_grid(locked_positions={}): | |
| grid = [[(0,0,0) for x in range(10)] for x in range(20)] | |
| for i in range(len(grid)): | |
| for j in range(len(grid[i])): | |
| if (j,i) in locked_positions: | |
| c = locked_positions[(j,i)] | |
| grid[i][j] = c | |
| return grid | |
| def convert_shape_format(shape): | |
| positions = [] | |
| format = shape.shape[shape.rotation % len(shape.shape)] | |
| for i, line in enumerate(format): | |
| row = list(line) | |
| for j, column in enumerate(row): | |
| if column == '0': | |
| positions.append((shape.x + j, shape.y + i)) | |
| for i, pos in enumerate(positions): | |
| positions[i] = (pos[0] - 2, pos[1] - 4) | |
| return positions | |
| def valid_space(shape, grid): | |
| accepted_positions = [[(j, i) for j in range(10) if grid[i][j] == (0,0,0)] for i in range(20)] | |
| accepted_positions = [j for sub in accepted_positions for j in sub] | |
| formatted = convert_shape_format(shape) | |
| for pos in formatted: | |
| if pos not in accepted_positions: | |
| if pos[1] > -1: | |
| return False | |
| return True | |
| def check_lost(positions): | |
| for pos in positions: | |
| x, y = pos | |
| if y < 1: | |
| return True | |
| return False | |
| def get_shape(): | |
| global shapes, shape_colors | |
| return Piece(5, 0, random.choice(shapes)) | |
| def draw_text_middle(text, size, color, surface): | |
| font = pygame.font.SysFont('comicsans', size, bold=True) | |
| label = font.render(text, 1, color) | |
| surface.blit(label, (top_left_x + play_width/2 - (label.get_width() / 2), top_left_y + play_height/2 - label.get_height()/2)) | |
| def draw_grid(surface, row, col): | |
| sx = top_left_x | |
| sy = top_left_y | |
| for i in range(row): | |
| pygame.draw.line(surface, (128,128,128), (sx, sy+ i*30), (sx + play_width, sy + i * 30)) # horizontal lines | |
| for j in range(col): | |
| pygame.draw.line(surface, (128,128,128), (sx + j * 30, sy), (sx + j * 30, sy + play_height)) # vertical lines | |
| def clear_rows(grid, locked): | |
| # need to see if row is clear the shift every other row above down one | |
| inc = 0 | |
| for i in range(len(grid)-1,-1,-1): | |
| row = grid[i] | |
| if (0, 0, 0) not in row: | |
| inc += 1 | |
| # add positions to remove from locked | |
| ind = i | |
| for j in range(len(row)): | |
| try: | |
| del locked[(j, i)] | |
| except: | |
| continue | |
| if inc > 0: | |
| for key in sorted(list(locked), key=lambda x: x[1])[::-1]: | |
| x, y = key | |
| if y < ind: | |
| newKey = (x, y + inc) | |
| locked[newKey] = locked.pop(key) | |
| def draw_next_shape(shape, surface): | |
| font = pygame.font.SysFont('comicsans', 30) | |
| label = font.render('Next Shape', 1, (255,255,255)) | |
| sx = top_left_x + play_width + 50 | |
| sy = top_left_y + play_height/2 - 100 | |
| format = shape.shape[shape.rotation % len(shape.shape)] | |
| for i, line in enumerate(format): | |
| row = list(line) | |
| for j, column in enumerate(row): | |
| if column == '0': | |
| pygame.draw.rect(surface, shape.color, (sx + j*30, sy + i*30, 30, 30), 0) | |
| surface.blit(label, (sx + 10, sy- 30)) | |
| def draw_window(surface): | |
| surface.fill((0,0,0)) | |
| # Tetris Title | |
| font = pygame.font.SysFont('comicsans', 60) | |
| label = font.render('TETRIS', 1, (255,255,255)) | |
| surface.blit(label, (top_left_x + play_width / 2 - (label.get_width() / 2), 30)) | |
| for i in range(len(grid)): | |
| for j in range(len(grid[i])): | |
| pygame.draw.rect(surface, grid[i][j], (top_left_x + j* 30, top_left_y + i * 30, 30, 30), 0) | |
| # draw grid and border | |
| draw_grid(surface, 20, 10) | |
| pygame.draw.rect(surface, (255, 0, 0), (top_left_x, top_left_y, play_width, play_height), 5) | |
| # pygame.display.update() | |
| def main(): | |
| global grid | |
| locked_positions = {} # (x,y):(255,0,0) | |
| grid = create_grid(locked_positions) | |
| change_piece = False | |
| run = True | |
| current_piece = get_shape() | |
| next_piece = get_shape() | |
| clock = pygame.time.Clock() | |
| fall_time = 0 | |
| level_time = 0 | |
| fall_speed = 0.27 | |
| score = 0 | |
| while run: | |
| grid = create_grid(locked_positions) | |
| fall_time += clock.get_rawtime() | |
| level_time += clock.get_rawtime() | |
| clock.tick() | |
| if level_time/1000 > 4: | |
| level_time = 0 | |
| if fall_speed > 0.15: | |
| fall_speed -= 0.005 | |
| # PIECE FALLING CODE | |
| if fall_time/1000 >= fall_speed: | |
| fall_time = 0 | |
| current_piece.y += 1 | |
| if not (valid_space(current_piece, grid)) and current_piece.y > 0: | |
| current_piece.y -= 1 | |
| change_piece = True | |
| for event in pygame.event.get(): | |
| if event.type == pygame.QUIT: | |
| run = False | |
| pygame.display.quit() | |
| quit() | |
| if event.type == pygame.KEYDOWN: | |
| if event.key == pygame.K_LEFT: | |
| current_piece.x -= 1 | |
| if not valid_space(current_piece, grid): | |
| current_piece.x += 1 | |
| elif event.key == pygame.K_RIGHT: | |
| current_piece.x += 1 | |
| if not valid_space(current_piece, grid): | |
| current_piece.x -= 1 | |
| elif event.key == pygame.K_UP: | |
| # rotate shape | |
| current_piece.rotation = current_piece.rotation + 1 % len(current_piece.shape) | |
| if not valid_space(current_piece, grid): | |
| current_piece.rotation = current_piece.rotation - 1 % len(current_piece.shape) | |
| if event.key == pygame.K_DOWN: | |
| # move shape down | |
| current_piece.y += 1 | |
| if not valid_space(current_piece, grid): | |
| current_piece.y -= 1 | |
| '''if event.key == pygame.K_SPACE: | |
| while valid_space(current_piece, grid): | |
| current_piece.y += 1 | |
| current_piece.y -= 1 | |
| print(convert_shape_format(current_piece))''' # todo fix | |
| shape_pos = convert_shape_format(current_piece) | |
| # add piece to the grid for drawing | |
| for i in range(len(shape_pos)): | |
| x, y = shape_pos[i] | |
| if y > -1: | |
| grid[y][x] = current_piece.color | |
| # IF PIECE HIT GROUND | |
| if change_piece: | |
| for pos in shape_pos: | |
| p = (pos[0], pos[1]) | |
| locked_positions[p] = current_piece.color | |
| current_piece = next_piece | |
| next_piece = get_shape() | |
| change_piece = False | |
| # call four times to check for multiple clear rows | |
| if clear_rows(grid, locked_positions): | |
| score += 10 | |
| draw_window(win) | |
| draw_next_shape(next_piece, win) | |
| pygame.display.update() | |
| # Check if user lost | |
| if check_lost(locked_positions): | |
| run = False | |
| draw_text_middle("You Lost", 40, (255,255,255), win) | |
| pygame.display.update() | |
| pygame.time.delay(2000) | |
| def main_menu(): | |
| run = True | |
| while run: | |
| win.fill((0,0,0)) | |
| draw_text_middle('Press any key to begin.', 60, (255, 255, 255), win) | |
| pygame.display.update() | |
| for event in pygame.event.get(): | |
| if event.type == pygame.QUIT: | |
| run = False | |
| if event.type == pygame.KEYDOWN: | |
| main() | |
| pygame.quit() | |
| win = pygame.display.set_mode((s_width, s_height)) | |
| pygame.display.set_caption('Tetris') | |
| main_menu() # start game | |