栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Numpy + Pygame 实现钻石方块

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Numpy + Pygame 实现钻石方块

      这个小游戏是我许久以前做的,像素画风,也没有炫酷的消除动画和动听的背景音乐,但也着实是让我重温了一把用(盗版的)15合1的游戏卡玩游戏的童年时光。

import pygame, sys, time, random, pprint


class Diamonds:
    def __init__(self):
        pygame.init()
        self.row = 15
        self.col = 8
        self.diamond_size = 50

        self.screen = pygame.display.set_mode((self.col * self.diamond_size, self.row * self.diamond_size), 0, 32)
        pygame.display.set_caption("钻石方块")

        self.init()

    # 游戏初始化
    def init(self):
        self.finished = False
        self.distribution = [["" for i in range(self.col)] for i in range(self.row)]
        self.diamonds = []
        self.score = 0
        group = DiamondGroup(self.screen, -3, self.col // 2, 50)
        self.diamonds.append(group)
        # 计时器归零
        self.start_time = time.time()
        self.pace = 1 / 3
        self.steps = 0

    def running(self):
        while True:
            self.check_events()
            if self.finished:
                font = pygame.font.SysFont(None, 100)
                text = font.render("Restart: R", True, "white", None)
                self.screen.blit(text, (10, 10))
                pygame.display.flip()
                continue
            self.update()
            self.draw()

    def check_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if event.type == pygame.KEYDOWN:
                # 按下  键,在全屏和原始窗口间切换
                diamond = self.diamonds[-1]
                # 在全屏模式下关闭窗口
                elif event.key == pygame.K_q:
                    sys.exit()
                # 移动钻石
                elif event.key == pygame.K_LEFT:
                    # 碰撞阻止
                    if not self.check_coincidence(-1):
                        diamond.move(event.key)
                elif event.key == pygame.K_RIGHT:
                    if not self.check_coincidence(1):
                        diamond.move(event.key)
                # 加快对象更新的速度
                elif event.key == pygame.K_DOWN:
                    self.start_time = time.time()
                    self.pace *= 1/3
                    self.steps = 0
                # 变换方块排序
                elif event.key == pygame.K_SPACE:
                    diamond.change_order()
                # 重新启动
                elif event.key == pygame.K_r and self.finished:
                    self.init()
                    
            elif event.type == pygame.KEYUP:
                # 恢复初始速度
                if event.key == pygame.K_DOWN:
                    self.start_time = time.time()
                    self.pace *= 3
                    self.steps = 0 

    
    # 每隔pace秒,更新一次对象
    def update(self):
        if (time.time() - self.start_time) // self.pace > self.steps:
            self.steps += 1
            # 先画出移动再检查移动
            self.check_collision()
            self.diamonds[-1].fall()
            diamond_on_line = self.check_line()
            # 多更新几次
            while diamond_on_line:
                self.emit_line(diamond_on_line)
                self.draw()
                time.sleep(0.2)
                diamond_on_line = self.check_line()
            # pprint.pprint(self.distribution)
            

    # 更新屏幕情况
    def update_distribution(self):
        for diamond in self.diamonds:
            for diamond in diamond.diamonds:
                row, col = diamond.row, diamond.col
                self.distribution[row][col] = diamond.colour
        # pprint.pprint(self.distribution)

    # 检查碰撞
    def check_collision(self):
        diamond = self.diamonds[-1]
        if diamond.collide_on_bottom() or diamond.collide_list(self.diamonds):
            # 更新方块位置
            self.update_distribution()
            # 把新的方块组放进列表
            new_diamond = DiamondGroup(self.screen, -4, 4, self.diamond_size)
            self.diamonds.append(new_diamond)
            # 结束游戏
            if diamond.row <= -1:
                self.finished = True

    def check_coincidence(self, i):
        group = self.diamonds[-1]
        diamond = group.diamonds[-1]
        for g in self.diamonds[:-1]:
            for d in g.diamonds:
                if diamond.row == d.row and diamond.col + i == d.col:
                    return True
        return False

    # 分四个方向检查连线
    def check_line(self):
        diamond_on_line = []
        for row in range(self.row):
            for col in range(self.col):
                # 由左往右
                if self.distribution[row][col] and col + 2 <= self.col - 1:
                    if self.distribution[row][col] == self.distribution[row][col + 1] == self.distribution[row][col + 2]:
                        diamond_on_line += [(col, row), (col + 1, row), (col + 2, row)]
                        # 检查连线上剩余的方块
                        for c in range(col + 3, self.col):
                            if self.distribution[row][c] == self.distribution[row][col]:
                                diamond_on_line += [(c, row)]
                            else:
                                break
                # 由上到下
                if self.distribution[row][col] and row + 2 <= self.row - 1:
                    if self.distribution[row][col] == self.distribution[row + 1][col] == self.distribution[row + 2][col]:
                        diamond_on_line += [(col, row), (col, row + 1), (col, row + 2)]
                        # 检查连线上剩余的方块
                        for r in range(row + 3, self.row):
                            if self.distribution[r][col] == self.distribution[row][col]:
                                diamond_on_line += [(col, r)]
                            else:
                                break
                # 从左上到右下
                if self.distribution[row][col] and row + 2 <= self.row - 1 and col + 2 <= self.col -1:
                    if self.distribution[row][col] == self.distribution[row + 1][col + 1] == self.distribution[row + 2][col + 2]:
                        diamond_on_line += [(col, row), (col + 1, row + 1), (col + 2, row + 2)]
                        # 检查连线上剩余的方块
                        for i in range(3, min(self.row - row, self.col - col)):
                            if self.distribution[row + i][col + i] == self.distribution[row][col]:
                                diamond_on_line += [(col + i, row + i)]
                            else:
                                break

                # 从左下到右上
                if self.distribution[row][col] and row - 2 >= 0 and col + 2 <= self.col -1:
                    if self.distribution[row][col] == self.distribution[row - 1][col + 1] == self.distribution[row - 2][col + 2]:
                        diamond_on_line += [(col, row), (col + 1, row - 1), (col + 2, row - 2)]
                        # 检查连线上剩余的方块
                        for i in range(3, min(self.row - row, self.col - col)):
                            if self.distribution[row - i][col + i] == self.distribution[row][col]:
                                diamond_on_line += [(col + i, row - i)]
                            else:
                                break
        return diamond_on_line
                        

    # 消除一条连线上的方块
    def emit_line(self, diamonds):
        for col, row in diamonds:
            # 遍历所有方块
            for d_group in self.diamonds:
                for d in d_group.diamonds:
                    # 删除方块,更新方块组,修改方块分布图
                    if d.row == row and d.col == col:
                        d_group.diamonds.remove(d)
                        # 得1分
                        self.score += 1
                        if len(d_group.diamonds) == 0:
                            self.diamonds.remove(d_group)
                        elif d_group.diamonds != []:
                            d_group.row = d_group.diamonds[0].row
                        self.distribution[row][col] = ""
        self.update_diamonds()
        self.update_diamonds()
        self.update_diamonds()

    # 强迫下方有空格的方块向下移动
    def update_diamonds(self):
        for group in self.diamonds[:-1]:
            for diamond in group.diamonds:
                try:
                    row, col = diamond.row, diamond.col
                    while self.distribution[row + 1][col] == "":
                        # 清除原位置的颜色,继续向下
                        diamond.row += 1
                        self.distribution[row + 1][col] = diamond.colour
                        self.distribution[row][col] = ""
                        if row + 1 == self.row:
                            break
                        row += 1
                except :
                    pass

    def show_score(self):
        font = pygame.font.SysFont(None, 20)
        text = font.render(f"{self.score}", True, "white", None)
        self.screen.blit(text, (self.col * self.diamond_size - 40, 10))

    def draw(self):
        self.screen.fill((30, 30, 30))
        for diamond in self.diamonds:
            diamond.draw()
        self.show_score()
        pygame.display.flip()


class Diamond:
    def __init__(self, screen, row, col, size, colour):
        self.row, self.col = row, col
        self.size = size
        self.colour = colour
        self.screen = screen
        self.rect = pygame.Rect(col * size, row * size, size, size)

    def fall(self, pace):
        self.rect.y += self.size * pace
        self.row += pace

    def draw(self):
        self.rect.y = self.row * self.size
        pygame.draw.rect(self.screen, self.colour, self.rect, 0)
        pygame.draw.rect(self.screen, "white", self.rect, 1)


class DiamondGroup:
    def __init__(self, screen, row, col, size):
        self.col, self.row = col, row
        self.size = size
        self.span = 1
        self.bottom_row = self.row + 2
        self.screen = screen
        self.diamonds = []
        self.colours = ["yellow", "green", "purple", "blue", "red", "white"]
        for i in range(3):
            diamond = Diamond(screen, row + i, col, size, random.choice(self.colours))
            diamond.index = i
            self.diamonds.append(diamond)

    def fall(self):
        for diamond in self.diamonds:
            diamond.fall(self.span)
        self.row += 1

    def move(self, key):
        """水平移动方块组"""
        if key == pygame.K_LEFT and 0 <= self.col - 1:
            self.col -= 1
            for diamond in self.diamonds:
                diamond.rect.left -= self.size
                diamond.col -= 1
        elif key == pygame.K_RIGHT and (self.col + 2) * self.size <= self.screen.get_width():
            self.col += 1
            for diamond in self.diamonds:
                diamond.rect.left += self.size
                diamond.col += 1

    # 碰撞屏幕底部,速度降为零
    def collide_on_bottom(self):
        if self.diamonds[-1].rect.bottom >= self.screen.get_height():
            self.span = 0
            return True
        else:
            return False

    # 方块是否与列表中的对象碰撞
    def collide_list(self, diamonds):
        for diamond_group in diamonds:
            if self.diamonds[-1].row + 1 == diamond_group.diamonds[0].row and self.diamonds[-1].col == diamond_group.diamonds[0].col:
                self.span = 0
                return True

    # 由下往上变换三颗钻石的颜色
    def change_order(self):
        d1, d2, d3 = self.diamonds
        d1.colour, d2.colour, d3.colour = d3.colour, d1.colour, d2.colour
            
    # 从下往上绘制三颗方块
    def draw(self):
        for diamond in self.diamonds:
            diamond.draw()

    



game = Diamonds()
game.running()

轻映录屏 2022-07-01 21-07-32

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1002320.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号