俄罗斯方块

俄罗斯方块简单实现

使用 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()

效果展示
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值