俄罗斯方块简单实现
使用 pygame 模块实现俄罗斯方块的简单实现,这里没有使用pygame 自带的碰撞检测,而是自定义的方法实现边界碰撞和方块间碰撞检测。
代码实现
import random
import pygame
import time
# 初始化游戏
pygame.init()
# 设置游戏窗口大小
WINDOW_WIDTH = 400
WINDOW_HEIGHT = 600
WINDOW_SIZE = (WINDOW_WIDTH, WINDOW_HEIGHT)
# 设置游戏窗口标题
pygame.display.set_caption("俄罗斯方块")
# 设置游戏窗口
screen = pygame.display.set_mode(WINDOW_SIZE)
# 定义方块大小和颜色
BLOCK_SIZE = 20
BLOCK_COLOR = (255, 255, 255)
# 定义方块类
class Block:
def __init__(self, x, y):
self.x = x
self.y = y
def draw(self, color):
pygame.draw.rect(screen, color, (self.x, self.y, BLOCK_SIZE, BLOCK_SIZE))
# 定义方块组类
class BlockGroup:
block_groups = list()
shape_set = {
"1": [(0, 1), (0, 2), (0, 3)],
"一": [(1, 0), (2, 0), (3, 0)],
"T": [(1, 0), (1, 1), (2, 0)],
"Z": [(1, 0), (1, 1), (2, 1)],
"田": [(1, 0), (0, 1), (1, 1)],
"L": [(0, 1), (0, 2), (1, 2)],
}
bottom_boundary_points = set()
def __init__(self):
self.blocks = list()
self.color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
def init(self):
group = self.generate_group()
self.block_groups.append(group)
@staticmethod
def generate_group():
group = BlockGroup()
x0 = random.randint(0, WINDOW_WIDTH-2 * BLOCK_SIZE)//BLOCK_SIZE * BLOCK_SIZE
y0 = -3 * BLOCK_SIZE
group.blocks.append(Block(x0, y0))
shape = random.choice(list(group.shape_set.keys()))
for _x, _y in group.shape_set[shape]:
# block = Block(random.randint(0, WINDOW_WIDTH - BLOCK_SIZE), i * BLOCK_SIZE)
x = x0 + _x * BLOCK_SIZE
y = y0 + _y * BLOCK_SIZE
group.blocks.append(Block(x, y))
group.shape = shape
return group
def draw(self):
for group in self.block_groups:
for block in group.blocks:
block.draw(group.color)
def move_down(self):
if self.collision_detection("bottom"):
group = self.generate_group()
BlockGroup.block_groups.append(group)
return
for block in self.block_groups[-1].blocks:
block.y += BLOCK_SIZE
def move_left(self):
if self.collision_detection("left"):
return
for block in self.block_groups[-1].blocks:
block.x -= BLOCK_SIZE
def move_right(self):
if self.collision_detection("right"):
return
for block in self.block_groups[-1].blocks:
block.x += BLOCK_SIZE
def collision_detection(self, move_direction):
# 移动方向上的偏移量
offset = {
"left": {"x0": -1*BLOCK_SIZE, "y0": 0},
"right": {"x0": 1*BLOCK_SIZE, "y0": 0},
"bottom": {"x0": 0, "y0": 1*BLOCK_SIZE}
}
block_collision = False
boundary_collision = False
# 获取当前活动组每个方块的坐标像素值
for block in self.block_groups[-1].blocks:
after_offset_pos = (block.x + offset[move_direction]["x0"], block.y + offset[move_direction]["y0"])
print(after_offset_pos, self.bottom_boundary_points)
if after_offset_pos in self.bottom_boundary_points:
print(f"预测到方块碰撞点", after_offset_pos)
block_collision = True
if after_offset_pos[0] < 0 or after_offset_pos[0] >= WINDOW_WIDTH or after_offset_pos[1] >= WINDOW_HEIGHT:
print(f"预测到第边界碰撞点", after_offset_pos)
boundary_collision = True
# 方块下移时,发生方块碰撞
if (block_collision or after_offset_pos[1] >= WINDOW_HEIGHT) and move_direction == "bottom":
shape = self.block_groups[-1].shape
print(self.blocks)
start_block = self.block_groups[-1].blocks[0]
self.bottom_boundary_points.update({(start_block.x, start_block.y)})
for _x, _y in self.block_groups[-1].shape_set[shape]:
self.bottom_boundary_points.update({(start_block.x + _x * BLOCK_SIZE, start_block.y + _y * BLOCK_SIZE)})
print(len(self.bottom_boundary_points), self.bottom_boundary_points)
# time.sleep(3)
# print(f"{self}检测到碰撞, 坐标{(block.x, block.y)}")
return block_collision or boundary_collision
# 定义游戏主循环
def main():
clock = pygame.time.Clock()
# 创建方块组
block_groups = BlockGroup()
block_groups.init()
# 游戏循环
while True:
clock.tick(3)
# 处理事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
block_groups.move_left()
elif event.key == pygame.K_RIGHT:
block_groups.move_right()
# 绘制背景
screen.fill((0, 0, 0))
# 移动方块组
block_groups.move_down()
# 绘制方块组
block_groups.draw()
# 更新屏幕
pygame.display.update()
# 启动游戏
if __name__ == '__main__':
main()
效果展示