class Next_figure(Board): def __init__(self, figure, color, screen): self.screen = screen width = 5 height = 5 self.ACTIVE_PIECE = 1 self.spic_colors_act = [ 'red', 'blue', 'orange', 'brown', 'purple', 'green', 'yellow' ] self.next_figure = Piece(figure, 0, 0) self.color = color self.color += 1 self.color %= 7 super().__init__(width, height, left=375, top=115, cell_size=20) self.border_color = pygame.Color('white') self.render_next_piece() def render_cell(self, i, j, screen): x, y = self.get_cell_position(i, j) rect = pygame.Rect(x, y, self.cell_size, self.cell_size) val = self.board[i][j] if val == self.ACTIVE_PIECE: pygame.draw.rect(screen, pygame.Color('black'), rect) elif val == self.default_value: pygame.draw.rect(screen, pygame.Color(self.spic_colors_act[self.color]), rect) else: pygame.draw.rect(screen, self.border_color, rect, width=self.border_width) def is_valid_pos(self, row, col): return 0 <= row < self.height and 0 <= col < self.width def render_next_piece(self): shape = self.next_figure.get_shape() for i in range(self.next_figure.size): for j in range(self.next_figure.size): board_row = i + self.next_figure.row board_column = j + self.next_figure.column if self.is_valid_pos(board_row, board_column): shape_val = int(shape[i][j]) if shape_val == self.ACTIVE_PIECE: self.board[board_row][ board_column] = self.default_value self.render_cell(i, j, self.screen)
class Tetris(Board): def __init__(self, fps, screen, rating, top_rating, music_win): self.music_win = music_win self.max_rating = top_rating self.screen = screen self.running = True self.confirmed_lose = False self.knight = Animation(screen) self.knight.update() self.stack_rating = rating main_font = pygame.font.SysFont('lucidasansroman', 60) self.title_tetris = main_font.render('TETRIS', True, pygame.Color('white')) screen.blit(self.title_tetris, (340, 30)) next_title = pygame.font.SysFont('lucidasansroman', 15) self.next_tetris = next_title.render('next figure:', True, pygame.Color('white')) screen.blit(self.next_tetris, (400, 110)) rating_title = pygame.font.SysFont('lucidasansroman', 15) self.rating_tetris = rating_title.render('current rating:', True, pygame.Color('white')) screen.blit(self.rating_tetris, (390, 220)) max_rating = pygame.font.SysFont('lucidasansroman', 15) self.max_rating_tetris = max_rating.render('the best rating:', True, pygame.Color('white')) screen.blit(self.max_rating_tetris, (390, 425)) width = 10 height = 20 super().__init__(width, height, left=30, top=40, cell_size=26) self.count = 0 self.spic_colors_act = [ 'red', 'blue', 'orange', 'brown', 'purple', 'green', 'yellow' ] self.fps = fps self.difficulty = 30 self.border_color = pygame.Color('white') self.ACTIVE_PIECE = 1 self.BLOCK = 11 self.stack_active_piece_color = int(random.randint(0, 3)) self.BLOCK_COLOR = pygame.Color('white') self.next_piece = Piece( [['00000', '00000', '01100', '01100', '00000']], 0, 0) self.create_active_piece() self.render_active_piece() def render_cell(self, i, j, screen): x, y = self.get_cell_position(i, j) rect = pygame.Rect(x, y, self.cell_size, self.cell_size) val = self.board[i][j] if val == self.ACTIVE_PIECE: pygame.draw.rect( screen, self.spic_colors_act[self.stack_active_piece_color], rect) elif val == self.BLOCK: pygame.draw.rect(screen, self.BLOCK_COLOR, rect) else: pygame.draw.rect(screen, self.border_color, rect, width=self.border_width) def update(self): self.knight.draw(self.screen) self.knight.update() self.display_next_figure() self.screen.blit(self.title_tetris, (340, 30)) self.screen.blit(self.next_tetris, (400, 110)) self.screen.blit(self.rating_tetris, (390, 220)) self.screen.blit(self.max_rating_tetris, (390, 465)) rating_num = pygame.font.SysFont('lucidasansroman', 30) rating_display = rating_num.render(str(self.stack_rating), True, pygame.Color('yellow')) self.screen.blit(rating_display, (390, 250)) max_rating = pygame.font.SysFont('lucidasansroman', 30) max_rating_display = max_rating.render(str(self.max_rating), True, pygame.Color('yellow')) self.screen.blit(max_rating_display, (390, 495)) self.count += 1 if self.count % (self.fps - self.difficulty) == 0: self.update_world() def update_world(self): if self.can_move(pygame.K_DOWN): self.remove_active_piece() self.active_piece.down() self.render_active_piece() else: self.active_piece_to_block() self.check_complete_lines() if self.check_for_lose(): self.knight = Animation(self.screen, False, False, True) size = 100 normal_size = 40 color = pygame.Color('red') main_font = pygame.font.SysFont('Arial', size) font = pygame.font.SysFont('Arial', normal_size) text = ['Вы проиграли!', 'Нажмите любую кнопку чтобы выйти'] rendered = [ main_font.render(text[0], True, color), font.render(text[1], True, color) ] rects = [rendered[0].get_rect(), rendered[1].get_rect()] width = max(rects[0].width, rects[1].width) height = 10 + rects[0].height + rects[1].height surface = pygame.Surface((width, height), pygame.SRCALPHA) rects[1].y += 110 for i in range(2): text = rendered[i] rect = rects[i] rect.x = width // 2 - rect.width // 2 surface.blit(text, rect) x = config.get_value('width') // 2 - width // 2 y = config.get_value('height') // 2 - height // 2 self.screen.blit(surface, pygame.Rect(x, y, width, height)) self.running = False self.create_active_piece() self.render_active_piece() def active_piece_to_block(self): self.stack_active_piece_color += 1 self.stack_active_piece_color %= 7 shape = self.active_piece.get_shape() for i in range(self.active_piece.size): for j in range(self.active_piece.size): board_row = i + self.active_piece.row board_column = j + self.active_piece.column if self.is_valid_pos(board_row, board_column): shape_val = int(shape[i][j]) if shape_val == self.ACTIVE_PIECE: self.board[board_row][board_column] = self.BLOCK def check_complete_lines(self): for row in range(self.height): if self.board[row].count(self.BLOCK) == self.width: self.knight = Animation(self.screen, False, True, False) self.knight.update() self.delete_line(row) def delete_line(self, index): for i in range(index, 0, -1): self.board[i] = self.board[i - 1] self.board[0] = [0] * self.width self.music_win.play() self.stack_rating = 100 + int(self.stack_rating) if self.stack_rating > self.max_rating: self.max_rating = self.stack_rating def render_active_piece(self): shape = self.active_piece.get_shape() for i in range(self.active_piece.size): for j in range(self.active_piece.size): board_row = i + self.active_piece.row board_column = j + self.active_piece.column if self.is_valid_pos(board_row, board_column): shape_val = int(shape[i][j]) if shape_val == self.ACTIVE_PIECE: self.board[board_row][board_column] = self.ACTIVE_PIECE def remove_active_piece(self): shape = self.active_piece.get_shape() for i in range(self.active_piece.size): for j in range(self.active_piece.size): board_row = i + self.active_piece.row board_column = j + self.active_piece.column if self.is_valid_pos(board_row, board_column): shape_val = int(shape[i][j]) if shape_val == self.ACTIVE_PIECE: self.board[board_row][ board_column] = self.default_value def is_valid_pos(self, row, col): return 0 <= row < self.height and 0 <= col < self.width def get_random_shape(self): return random.choice(list(shapes.values())) def display_next_figure(self): next_fig = Next_figure(self.next_piece.shape, self.stack_active_piece_color, self.screen) def create_active_piece(self): if len(self.next_piece.shape) < 1: self.active_piece = Piece(self.get_random_shape(), -1, 0) self.next_piece = Piece(self.get_random_shape(), -1, 0) else: self.active_piece = self.next_piece self.next_piece = Piece(self.get_random_shape(), -1, 0) def can_move(self, direction): actions = { pygame.K_DOWN: self.active_piece.down, pygame.K_LEFT: self.active_piece.left, pygame.K_RIGHT: self.active_piece.right, pygame.K_UP: self.active_piece.rotate } reverse_actions = { pygame.K_DOWN: self.active_piece.up, pygame.K_LEFT: self.active_piece.right, pygame.K_RIGHT: self.active_piece.left, pygame.K_UP: self.active_piece.rotate_prev } result = True actions[direction]() shape = self.active_piece.get_shape() for i in range(self.active_piece.size): for j in range(self.active_piece.size): board_row = i + self.active_piece.row board_column = j + self.active_piece.column shape_val = int(shape[i][j]) if not self.is_valid_pos( board_row, board_column) and shape_val == self.ACTIVE_PIECE: result = False break if not self.is_valid_pos(board_row, board_column): continue board_val = self.board[board_row][board_column] if shape_val == self.ACTIVE_PIECE and board_val == self.BLOCK: result = False break reverse_actions[direction]() return result def move_action(self, action, direction): if self.can_move(direction): self.remove_active_piece() action() self.render_active_piece() def on_key_pressed(self, key): actions = { pygame.K_DOWN: self.active_piece.down, pygame.K_LEFT: self.active_piece.left, pygame.K_RIGHT: self.active_piece.right, pygame.K_UP: self.active_piece.rotate } if key in actions: self.move_action(actions[key], key) def check_for_lose(self): for i in range(self.width): if self.board[1][i] == self.BLOCK: return True return False def confirm_lose(self): new_max = self.get_max_rating_value() out = open('stack_max.txt', 'w') out.write(str(new_max)) out.close() self.confirmed_lose = True def get_max_rating_value(self): return self.max_rating