
专栏导读
-
🌸 欢迎来到Pygame基础专栏—大家可以在这里学习pygame基础知识
-
🏳️🌈 博客主页:请点击——> 一晌小贪欢的博客主页
-
👍 该系列文章专栏:请点击——>Pygame基础专栏
-
文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
-
❤️ 欢迎各位佬关注! ❤️
完整代码
import pygame
import random
import time
pygame.init()
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
ORANGE = (255, 165, 0)
YELLOW = (255, 255, 0)
GREEN = (0, 255, 0)
PURPLE = (128, 0, 128)
RED = (255, 0, 0)
BLOCK_SIZE = 30
GRID_WIDTH = 10
GRID_HEIGHT = 20
SCREEN_WIDTH = BLOCK_SIZE * (GRID_WIDTH + 8)
SCREEN_HEIGHT = BLOCK_SIZE * GRID_HEIGHT
GAME_AREA_LEFT = BLOCK_SIZE * 4
GAME_AREA_TOP = 0
SHAPES = [[[1, 1, 1, 1]], [[1, 1], [1, 1]], [[1, 1, 1], [0, 1, 0]], [[1, 1, 1], [1, 0, 0]], [[1, 1, 1], [0, 0, 1]], [[0, 1, 1], [1, 1, 0]], [[1, 1, 0], [0, 1, 1]]
]
SHAPE_COLORS = [CYAN, YELLOW, PURPLE, ORANGE, BLUE, GREEN, RED]
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("俄罗斯方块")
clock = pygame.time.Clock()class Tetromino:def __init__(self):self.shape_index = random.randint(0, len(SHAPES) - 1)self.shape = SHAPES[self.shape_index]self.color = SHAPE_COLORS[self.shape_index]self.x = GRID_WIDTH // 2 - len(self.shape[0]) // 2self.y = 0def rotate(self):rows = len(self.shape)cols = len(self.shape[0])rotated = [[0 for _ in range(rows)] for _ in range(cols)]for r in range(rows):for c in range(cols):rotated[c][rows - 1 - r] = self.shape[r][c]return rotateddef draw(self, surface):for y, row in enumerate(self.shape):for x, cell in enumerate(row):if cell:rect = pygame.Rect(GAME_AREA_LEFT + (self.x + x) * BLOCK_SIZE,GAME_AREA_TOP + (self.y + y) * BLOCK_SIZE,BLOCK_SIZE, BLOCK_SIZE)pygame.draw.rect(surface, self.color, rect)pygame.draw.rect(surface, WHITE, rect, 1)class TetrisGame:def __init__(self):self.font = pygame.font.SysFont('simhei', 13)self.grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]self.current_piece = Tetromino()self.next_piece = Tetromino()self.game_over = Falseself.score = 0self.level = 1self.lines_cleared = 0self.fall_time = 0self.fall_speed = 0.5 self.last_fall_time = time.time()def draw_grid(self, surface):pygame.draw.rect(surface, BLACK, (GAME_AREA_LEFT, GAME_AREA_TOP,GRID_WIDTH * BLOCK_SIZE,GRID_HEIGHT * BLOCK_SIZE))for x in range(GRID_WIDTH + 1):pygame.draw.line(surface, WHITE,(GAME_AREA_LEFT + x * BLOCK_SIZE, GAME_AREA_TOP),(GAME_AREA_LEFT + x * BLOCK_SIZE, GAME_AREA_TOP + GRID_HEIGHT * BLOCK_SIZE))for y in range(GRID_HEIGHT + 1):pygame.draw.line(surface, WHITE,(GAME_AREA_LEFT, GAME_AREA_TOP + y * BLOCK_SIZE),(GAME_AREA_LEFT + GRID_WIDTH * BLOCK_SIZE, GAME_AREA_TOP + y * BLOCK_SIZE))for y in range(GRID_HEIGHT):for x in range(GRID_WIDTH):if self.grid[y][x]:color_idx = self.grid[y][x] - 1rect = pygame.Rect(GAME_AREA_LEFT + x * BLOCK_SIZE,GAME_AREA_TOP + y * BLOCK_SIZE,BLOCK_SIZE, BLOCK_SIZE)pygame.draw.rect(surface, SHAPE_COLORS[color_idx], rect)pygame.draw.rect(surface, WHITE, rect, 1)def draw_info(self, surface):info_area = pygame.Rect(0, 0, GAME_AREA_LEFT, SCREEN_HEIGHT)pygame.draw.rect(surface, (50, 50, 50), info_area)next_text = self.font.render("下一个:", True, WHITE)surface.blit(next_text, (20, 20))next_piece_surface = pygame.Surface((len(self.next_piece.shape[0]) * BLOCK_SIZE,len(self.next_piece.shape) * BLOCK_SIZE))next_piece_surface.fill((50, 50, 50))for y, row in enumerate(self.next_piece.shape):for x, cell in enumerate(row):if cell:rect = pygame.Rect(x * BLOCK_SIZE,y * BLOCK_SIZE,BLOCK_SIZE, BLOCK_SIZE)pygame.draw.rect(next_piece_surface, self.next_piece.color, rect)pygame.draw.rect(next_piece_surface, WHITE, rect, 1)surface.blit(next_piece_surface, (20, 60))score_text = self.font.render(f"分数: {self.score}", True, WHITE)surface.blit(score_text, (20, 180))level_text = self.font.render(f"等级: {self.level}", True, WHITE)surface.blit(level_text, (20, 220))lines_text = self.font.render(f"消除行: {self.lines_cleared}", True, WHITE)surface.blit(lines_text, (20, 260))controls_text = ["操作说明:","←→: 左右移动","↑: 旋转","↓: 加速下落","空格: 直接落下","P: 暂停游戏","R: 重新开始"]for i, text in enumerate(controls_text):ctrl_text = self.font.render(text, True, WHITE)surface.blit(ctrl_text, (20, 320 + i * 30))def draw_game_over(self, surface):overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))overlay.set_alpha(150)overlay.fill(BLACK)surface.blit(overlay, (0, 0))font = pygame.font.SysFont(None, 50)game_over_text = self.font.render("游戏结束!", True, WHITE)restart_text = self.font.render("按R键重新开始", True, WHITE)surface.blit(game_over_text,(SCREEN_WIDTH // 2 - game_over_text.get_width() // 2,SCREEN_HEIGHT // 2 - 50))surface.blit(restart_text,(SCREEN_WIDTH // 2 - restart_text.get_width() // 2,SCREEN_HEIGHT // 2 + 10))def is_collision(self, shape, x, y):for row_idx, row in enumerate(shape):for col_idx, cell in enumerate(row):if cell:if (x + col_idx < 0 or x + col_idx >= GRID_WIDTH ory + row_idx >= GRID_HEIGHT):return Trueif y + row_idx >= 0 and self.grid[y + row_idx][x + col_idx]:return Truereturn Falsedef merge_piece(self):for y, row in enumerate(self.current_piece.shape):for x, cell in enumerate(row):if cell and 0 <= self.current_piece.y + y < GRID_HEIGHT:self.grid[self.current_piece.y + y][self.current_piece.x + x] = self.current_piece.shape_index + 1def clear_lines(self):lines_to_clear = []for y in range(GRID_HEIGHT):if all(self.grid[y]):lines_to_clear.append(y)for line in lines_to_clear:del self.grid[line]self.grid.insert(0, [0 for _ in range(GRID_WIDTH)])if lines_to_clear:self.lines_cleared += len(lines_to_clear)self.score += [100, 300, 500, 800][min(len(lines_to_clear) - 1, 3)] * self.levelself.level = min(10, 1 + self.lines_cleared // 10)self.fall_speed = max(0.05, 0.5 - (self.level - 1) * 0.05)return len(lines_to_clear)def move(self, dx, dy):if not self.is_collision(self.current_piece.shape,self.current_piece.x + dx,self.current_piece.y + dy):self.current_piece.x += dxself.current_piece.y += dyreturn Truereturn Falsedef rotate_piece(self):rotated = self.current_piece.rotate()if not self.is_collision(rotated, self.current_piece.x, self.current_piece.y):self.current_piece.shape = rotatedreturn Truefor dx in [-1, 1, -2, 2]:if not self.is_collision(rotated, self.current_piece.x + dx, self.current_piece.y):self.current_piece.x += dxself.current_piece.shape = rotatedreturn Truereturn Falsedef drop_piece(self):while self.move(0, 1):passdef new_piece(self):self.current_piece = self.next_pieceself.next_piece = Tetromino()if self.is_collision(self.current_piece.shape,self.current_piece.x,self.current_piece.y):self.game_over = Truedef update(self):current_time = time.time()if current_time - self.last_fall_time > self.fall_speed:if not self.move(0, 1):self.merge_piece()self.clear_lines()self.new_piece()self.last_fall_time = current_timedef reset(self):self.__init__()def main():game = TetrisGame()paused = Falsewhile True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()returnif event.type == pygame.KEYDOWN:if event.key == pygame.K_r:game.reset()paused = Falseif game.game_over:continueif event.key == pygame.K_p:paused = not pausedif paused:continueif event.key == pygame.K_LEFT:game.move(-1, 0)elif event.key == pygame.K_RIGHT:game.move(1, 0)elif event.key == pygame.K_DOWN:game.move(0, 1)elif event.key == pygame.K_UP:game.rotate_piece()elif event.key == pygame.K_SPACE:game.drop_piece()if not game.game_over and not paused:game.update()screen.fill((50, 50, 50))game.draw_grid(screen)game.draw_info(screen)if not game.game_over:game.current_piece.draw(screen)if game.game_over:game.draw_game_over(screen)pygame.display.flip()clock.tick(60)if __name__ == "__main__":main()
总结
-
希望对初学者有帮助
-
致力于办公自动化的小小程序员一枚
-
希望能得到大家的【一个免费关注】!感谢
-
求个 🤞 关注 🤞
-
此外还有办公自动化专栏,欢迎大家订阅:Python办公自动化专栏
-
求个 ❤️ 喜欢 ❤️
-
此外还有爬虫专栏,欢迎大家订阅:Python爬虫基础专栏
-
求个 👍 收藏 👍
-
此外还有Python基础专栏,欢迎大家订阅:Python基础学习专栏