[Python] 纯文本查看 复制代码
import random
import pygame
# 定义方块类
class Block:
def __init__(self, shape, color, x, y):
self.shape = shape
self.color = color
self.x = x
self.y = y
def draw(self, surface):
pygame.draw.rect(surface, self.color, (self.x*25+1, self.y*25+1, 24, 24))
# 定义游戏类
class Game:
def __init__(self, width=10, height=20):
self.width = width
self.height = height
self.board = [[0 for x in range(self.width)] for y in range(self.height)]
self.score = 0
self.level = 1
self.falling_block = None
self.next_block = None
self.game_over = False
def new_block(self):
# 随机生成新的方块
shapes = [
[[[1, 1, 1, 1]], (255, 0, 0)],
[[[1, 1], [1, 1]], (0, 255, 0)],
[[[1, 1, 0], [0, 1, 1]], (0, 0, 255)],
[[[0, 1, 1], [1, 1, 0]], (255, 255, 0)],
[[[1, 1, 1], [0, 1, 0]], (0, 255, 255)],
[[[1, 1, 0], [0, 1, 1]], (255, 0, 255)],
[[[0, 1, 0], [1, 1, 1]], (128, 0, 128)]
]
shape, color = random.choice(shapes)
self.falling_block = Block(shape, color, self.width//2-2, 0)
shape, color = random.choice(shapes)
self.next_block = Block(shape, color, 0, 0)
def draw_board(self, surface):
# 绘制游戏区域
for y in range(self.height):
for x in range(self.width):
pygame.draw.rect(surface, (255, 255, 255), (x*25, y*25, 25, 25), 1)
if self.board[y][x]:
pygame.draw.rect(surface, self.board[y][x], (x*25+1, y*25+1, 24, 24))
def draw_falling_block(self, surface):
# 绘制当前下落的方块
if self.falling_block:
for y, row in enumerate(self.falling_block.shape):
for x, val in enumerate(row):
if val:
b = Block(self.falling_block.shape, self.falling_block.color, self.falling_block.x+x, self.falling_block.y+y)
b.draw(surface)
def draw_next_block(self, surface):
# 绘制下一个方块
if self.next_block:
for y, row in enumerate(self.next_block.shape):
for x, val in enumerate(row):
if val:
b = Block(self.next_block.shape, self.next_block.color, self.width+x, y)
b.draw(surface)
def move_left(self):
# 向左移动方块
if self.falling_block:
if self.falling_block.x > 0 and not self.collides(self.falling_block, -1):
self.falling_block.x -= 1
def move_right(self):
# 向右移动方块
if self.falling_block:
if self.falling_block.x < self.width-len(self.falling_block.shape[0]) and not self.collides(self.falling_block, 1):
self.falling_block.x += 1
def rotate(self):
# 旋转方块
if self.falling_block:
tmp = list(zip(*self.falling_block.shape[::-1]))
if self.falling_block.x + len(tmp[0]) <= self.width and not self.collides(Block(tmp, self.falling_block.color, self.falling_block.x, self.falling_block.y), 0):
self.falling_block.shape = tmp
def fall(self):
# 下落方块
if self.falling_block:
if self.falling_block.y < self.height-len(self.falling_block.shape) and not self.collides(self.falling_block, 0, 1):
self.falling_block.y += 1
return False
else:
self.merge_falling_block()
self.new_block()
return True
def merge_falling_block(self):
# 将当前方块合并到游戏区域
for y, row in enumerate(self.falling_block.shape):
for x, val in enumerate(row):
if val:
self.board[self.falling_block.y+y][self.falling_block.x+x] = self.falling_block.color
# 消除填满一行的方块
for y in range(self.height):
if all(self.board[y]):
self.board.pop(y)
self.board.insert(0, [0 for x in range(self.width)])
self.score += 10
if self.score % 100 == 0:
self.level += 1
def collides(self, block, dx=0, dy=0):
# 判断方块是否与游戏区域或已有方块重叠
for y, row in enumerate(block.shape):
for x, val in enumerate(row):
if val:
try:
if self.board[block.y+y+dy][block.x+x+dx]:
return True
except IndexError:
return True
return False
# 游戏主循环
def main():
pygame.init()
screen = pygame.display.set_mode((320, 480))
clock = pygame.time.Clock()
game = Game()
game.new_block()
paused = False
font = pygame.font.SysFont('Arial', 20)
while not game.game_over:
clock.tick(game.level * 5)
screen.fill((0, 0, 0))
game.draw_board(screen)
game.draw_falling_block(screen)
game.draw_next_block(screen)
# 显示分数
text = font.render('Score: ' + str(game.score), True, (255, 255, 255))
screen.blit(text, (10, 10))
# 监听键盘事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
game.game_over = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
game.move_left()
elif event.key == pygame.K_RIGHT:
game.move_right()
elif event.key == pygame.K_UP:
game.rotate()
elif event.key == pygame.K_DOWN:
if not paused:
game.fall()
elif event.key == pygame.K_p:
paused = not paused
elif event.key == pygame.K_SPACE:
if paused:
game = Game()
game.new_block()
paused = False
# 游戏暂停时不更新屏幕
if not paused:
if game.fall():
if game.collides(game.falling_block, 0, 0):
# 游戏结束
text = font.render('Game Over', True, (255, 255, 255))
screen.blit(text, (100, 200))
paused = True
pygame.display.update()
pygame.quit()
if __name__ == '__main__':
main()