好的,以下是一个简单的示例代码,实现了一个由tkinter按钮指令控制的封装成函数的pygame俄罗斯方块小游戏:
```python
import pygame
import random
import tkinter as tk
# 游戏窗口尺寸
WINDOW_SIZE = (300, 600)
# 游戏区域尺寸
PLAY_AREA_SIZE = (10, 20)
# 方块尺寸
BLOCK_SIZE = 30
# 方块颜色
COLORS = [
(0, 0, 0), # 黑色
(255, 0, 0), # 红色
(0, 255, 0), # 绿色
(0, 0, 255), # 蓝色
(255, 255, 0), # 黄色
(255, 0, 255), # 紫色
(0, 255, 255), # 青色
]
# 方块形状
SHAPES = [
[[1, 1], [1, 1]], # 方块
[[0, 2, 0], [2, 2, 2]], # L形状
[[0, 3, 3], [3, 3, 0]], # J形状
[[4, 4, 0], [0, 4, 4]], # Z形状
[[0, 5, 5], [5, 5, 0]], # S形状
[[6, 6, 6], [0, 6, 0]], # T形状
[[7, 7, 7, 7]], # 长条形状
]
class Block:
"""方块类"""
def __init__(self, x, y, shape):
self.x = x
self.y = y
self.shape = shape
self.color = random.randint(1, len(COLORS) - 1)
def move(self, dx, dy):
"""移动方块"""
self.x += dx
self.y += dy
def rotate(self):
"""旋转方块"""
self.shape = [[self.shape[j][i] for j in range(len(self.shape))] for i in range(len(self.shape[0]) - 1, -1, -1)]
class Tetris:
"""俄罗斯方块游戏类"""
def __init__(self):
# 初始化pygame
pygame.init()
# 创建游戏窗口
self.screen = pygame.display.set_mode(WINDOW_SIZE)
# 创建字体
self.font = pygame.font.Font(None, 30)
# 设置游戏区域位置和尺寸
self.play_area_x = (WINDOW_SIZE[0] - PLAY_AREA_SIZE[0] * BLOCK_SIZE) // 2
self.play_area_y = (WINDOW_SIZE[1] - PLAY_AREA_SIZE[1] * BLOCK_SIZE) // 2
self.play_area_width = PLAY_AREA_SIZE[0] * BLOCK_SIZE
self.play_area_height = PLAY_AREA_SIZE[1] * BLOCK_SIZE
# 创建游戏区域
self.play_area = [[0] * PLAY_AREA_SIZE[0] for _ in range(PLAY_AREA_SIZE[1])]
# 创建当前方块
self.current_block = self.get_new_block()
# 创建下一个方块
self.next_block = self.get_new_block()
# 创建计时器
self.timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(self.timer_event, 1000)
# 创建按钮指令控制
self.root = tk.Tk()
self.root.geometry('200x100')
self.root.title('俄罗斯方块')
self.up_btn = tk.Button(self.root, text='上', command=self.move_up)
self.up_btn.pack(side=tk.TOP, pady=5)
self.down_btn = tk.Button(self.root, text='下', command=self.move_down)
self.down_btn.pack(side=tk.BOTTOM, pady=5)
self.left_btn = tk.Button(self.root, text='左', command=self.move_left)
self.left_btn.pack(side=tk.LEFT, padx=10)
self.right_btn = tk.Button(self.root, text='右', command=self.move_right)
self.right_btn.pack(side=tk.RIGHT, padx=10)
def get_new_block(self):
"""生成新方块"""
shape = random.choice(SHAPES)
x = PLAY_AREA_SIZE[0] // 2 - len(shape[0]) // 2
y = 0
return Block(x, y, shape)
def draw_block(self, x, y, color):
"""绘制方块"""
rect = pygame.Rect(self.play_area_x + x * BLOCK_SIZE, self.play_area_y + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
pygame.draw.rect(self.screen, COLORS[color], rect)
def draw_play_area(self):
"""绘制游戏区域"""
for y in range(PLAY_AREA_SIZE[1]):
for x in range(PLAY_AREA_SIZE[0]):
if self.play_area[y][x] != 0:
self.draw_block(x, y, self.play_area[y][x])
def draw_current_block(self):
"""绘制当前方块"""
for y in range(len(self.current_block.shape)):
for x in range(len(self.current_block.shape[0])):
if self.current_block.shape[y][x] != 0:
self.draw_block(self.current_block.x + x, self.current_block.y + y, self.current_block.color)
def move_down(self):
"""向下移动方块"""
if self.check_collision(self.current_block, 0, 1):
self.current_block.move(0, 1)
def move_left(self):
"""向左移动方块"""
if self.check_collision(self.current_block, -1, 0):
self.current_block.move(-1, 0)
def move_right(self):
"""向右移动方块"""
if self.check_collision(self.current_block, 1, 0):
self.current_block.move(1, 0)
def move_up(self):
"""旋转方块"""
self.current_block.rotate()
if not self.check_collision(self.current_block, 0, 0):
self.current_block.rotate()
self.current_block.rotate()
self.current_block.rotate()
def check_collision(self, block, dx, dy):
"""检查方块是否与游戏区域或其他方块发生碰撞"""
for y in range(len(block.shape)):
for x in range(len(block.shape[0])):
if block.shape[y][x] != 0:
if block.y + y + dy < 0:
return False
elif block.y + y + dy >= PLAY_AREA_SIZE[1]:
return False
elif block.x + x + dx < 0:
return False
elif block.x + x + dx >= PLAY_AREA_SIZE[0]:
return False
elif self.play_area[block.y + y + dy][block.x + x + dx] != 0:
return False
return True
def update_play_area(self):
"""更新游戏区域"""
for y in range(len(self.current_block.shape)):
for x in range(len(self.current_block.shape[0])):
if self.current_block.shape[y][x] != 0:
self.play_area[self.current_block.y + y][self.current_block.x + x] = self.current_block.color
def remove_complete_lines(self):
"""删除已完成的行"""
num_lines_removed = 0
for y in range(PLAY_AREA_SIZE[1]):
if all(self.play_area[y]):
del self.play_area[y]
self.play_area.insert(0, [0] * PLAY_AREA_SIZE[0])
num_lines_removed += 1
return num_lines_removed
def draw_next_block(self):
"""绘制下一个方块"""
x = self.play_area_x + self.play_area_width + 30
y = self.play_area_y + 2 * BLOCK_SIZE
shape = self.next_block.shape
color = self.next_block.color
for i, row in enumerate(shape):
for j, cell in enumerate(row):
if cell != 0:
rect = pygame.Rect(x + j * BLOCK_SIZE, y + i * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
pygame.draw.rect(self.screen, COLORS[color], rect)
self.draw_text('Next:', x, y - 30)
def draw_score(self, score):
"""绘制得分"""
self.draw_text(f'Score: {score}', self.play_area_x, self.play_area_y - 30)
def draw_text(self, text, x, y):
"""绘制文本"""
surface = self.font.render(text, True, (255, 255, 255))
rect = surface.get_rect()
rect.topleft = (x, y)
self.screen.blit(surface, rect)
def draw_game_over(self):
"""绘制游戏结束"""
self.draw_text('Game Over', self.play_area_x + self.play_area_width // 2 - 70, self.play_area_y + self.play_area_height // 2 - 15)
def run(self):
"""运行游戏"""
score = 0
clock = pygame.time.Clock()
running = True
while running:
# 处理事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.type == self.timer_event:
if self.check_collision(self.current_block, 0, 1):
self.current_block.move(0, 1)
else:
self.update_play_area()
num_lines_removed = self.remove_complete_lines()
score += num_lines_removed ** 2
self.current_block = self.next_block
self.next_block = self.get_new_block()
if not self.check_collision(self.current_block, 0, 0):
running = False
# 绘制游戏界面
self.screen.fill(COLORS[0])
self.draw_play_area()
self.draw_current_block()
self.draw_next_block()
self.draw_score(score)
if not running:
self.draw_game_over()
# 更新屏幕
pygame.display.update()
# 控制帧率
clock.tick(60)
# 更新按钮指令控制
self.root.update()
```
使用以下代码运行游戏:
```python
if __name__ == '__main__':
game = Tetris()
game.run()
```
按钮指令控制需要在游戏运行前在另一个线程中运行以下代码:
```python
game.root.mainloop()
```
完整代码: