• 猿创征文|为了练习自己的Python基础语法,我用pygame写了一个打砖块闯关的游戏


    ✅作者简介:人工智能专业本科在读,喜欢计算机与编程,写博客记录自己的学习历程。
    🍎个人主页:小嗷犬的博客
    🍊个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。
    🥭本文内容:为了练习自己的Python基础语法,我用pygame写了一个打砖块闯关的游戏



    事件之始

    那是一个百无聊赖的夜晚,我回顾了自己自大学以来的经历,感觉生活十分平淡,学习了许多计算机知识,但是似乎什么东西都没有用上。

    考虑到我的Python有些生疏了,我便计划练习一下Python,我像往常一样点开网课,带上耳机,准备慢慢地听。

    只听了3分钟,我便没了耐心,听谁还不会啊,关键还是要写,为了缓解大学以来的无味,也为了练习Python,我决定写点有趣的东西。

    pip install pygame
    
    • 1

    于是我在命令行里输入了上面的代码。

    我的第一个游戏应允而生。


    萌新复现经典游戏打砖块

    最开始,我本来只是想简单复现一下经典游戏,我学习了一下pygame的基本用法,就开始动手了。

    在我一段时间的埋头苦写之下,一个大概150行代码的小游戏就诞生了:

    '''
    Time    : 2022-4-18
    Author  : Marquis
    FileName: Dog打砖块1.0.py
    Software: VScode
    '''
    
    import pygame
    import sys
    import pygame.freetype
    import os
    import random
    # 初始化
    os.chdir(os.path.dirname(sys.argv[0]))
    pygame.init()
    pygame.display.set_icon(pygame.image.load(r".\img\dog50x.jpg"))
    size = width, height = 1500, 700
    speed = [2, -2]
    Black = 0, 0, 0
    Red = 255, 0, 0
    White = 255, 255, 255
    screen = pygame.display.set_mode(size)
    pygame.display.set_caption("Dog Ball2")
    ball = pygame.image.load("./img/dog50x.jpg")
    board = pygame.image.load("./img/board160x20.png")
    ballrect = ball.get_rect()
    boardrect = board.get_rect()
    f1 = pygame.freetype.Font("C:/Windows/Fonts/msyh.ttc", 36)
    fps = 160
    fclock = pygame.time.Clock()
    pause = 1
    flag = 0
    boardrect = boardrect.move(0, 600)
    ballrect = ballrect.move(700, 450)
    brick_list = []
    brick_color = []
    for i in range(0, 20):
        for j in range(0, 10):
            # 随机生成砖块(可调节概率)
            if random.randint(0, 3) == 1:
                brick_list.append(pygame.Rect(i*75, j*30, 75, 30))
                brick_color.append((random.randint(100, 200), random.randint(
                    100, 200), random.randint(100, 200)))
    beginsurf, beginrect = f1.render("<按下空格键开始游戏>", fgcolor=White, size=60)
    screen.blit(beginsurf, (450, 300))
    pygame.display.update()
    
    # 游戏主体
    while True:
        # 运行循环
        while not pause:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
                # 挡板跟随鼠标移动
                elif event.type == pygame.MOUSEMOTION:
                    boardrect = boardrect.move(
                        event.pos[0]-(boardrect.left+boardrect.right)/2, 0)
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        sys.exit()
                    # 5档变速
                    elif event.key == pygame.K_1:
                        speed[0], speed[1] = speed[0] / \
                            abs(speed[0])*1, speed[1]/abs(speed[1])*1
                    elif event.key == pygame.K_2:
                        speed[0], speed[1] = speed[0] / \
                            abs(speed[0])*2, speed[1]/abs(speed[1])*2
                    elif event.key == pygame.K_3:
                        speed[0], speed[1] = speed[0] / \
                            abs(speed[0])*3, speed[1]/abs(speed[1])*3
                    elif event.key == pygame.K_4:
                        speed[0], speed[1] = speed[0] / \
                            abs(speed[0])*4, speed[1]/abs(speed[1])*4
                    elif event.key == pygame.K_5:
                        speed[0], speed[1] = speed[0] / \
                            abs(speed[0])*5, speed[1]/abs(speed[1])*5
                    elif event.key == pygame.K_SPACE:
                        pause = 1
    
            # 球的移动
            ballrect = ballrect.move(speed[0], speed[1])
            # 球与板的撞击判断
            if ballrect.colliderect(boardrect):
                if ballrect.top <= boardrect.bottom and ballrect.bottom > boardrect.bottom and speed[1] < 0:
                    speed[1] = -speed[1]
                elif ballrect.bottom >= boardrect.top and ballrect.top < boardrect.top and speed[1] > 0:
                    speed[1] = -speed[1]
                elif ballrect.left <= boardrect.right and ballrect.right > boardrect.right and speed[0] < 0:
                    speed[0] = -speed[0]
                elif ballrect.right >= boardrect.left and ballrect.left < boardrect.right and speed[0] > 0:
                    speed[0] = -speed[0]
            # 球与边界的撞击判断
            if (ballrect.left < 0 and speed[0] < 0) or (ballrect.right > width and speed[0] > 0):
                speed[0] = -speed[0]
            if ballrect.top < 0 and speed[1] < 0:
                speed[1] = -speed[1]
            for brick in brick_list:
                if ballrect.colliderect(brick):
                    if ballrect.left <= brick.right and ballrect.right > brick.right and speed[0] < 0:
                        speed[0] = -speed[0]
                    elif ballrect.right >= brick.left and ballrect.left < brick.left and speed[0] > 0:
                        speed[0] = -speed[0]
                    elif ballrect.top <= brick.bottom and ballrect.bottom > brick.bottom and speed[1] < 0:
                        speed[1] = -speed[1]
                    elif ballrect.bottom >= brick.top and ballrect.top < brick.top and speed[1] > 0:
                        speed[1] = -speed[1]
                    brick_color.pop(brick_list.index(brick))
                    brick_list.pop(brick_list.index(brick))
                    break
    
            # 屏幕的更新
            screen.fill(Black)
            # 小提示
            tip1surf, tip1rect = f1.render("<按空格键暂停游戏>", fgcolor=White, size=20)
            tip2surf, tip2rect = f1.render("<按ESC键退出游戏>", fgcolor=White, size=20)
            tip3surf, tip3rect = f1.render(
                "<按数字键1-5调速(默认为2)>", fgcolor=White, size=20)
            screen.blit(tip1surf, (0, 640))
            screen.blit(tip2surf, (0, 660))
            screen.blit(tip3surf, (0, 680))
            # 砖、球、板的绘制
            for brick in brick_list:
                pygame.draw.rect(
                    screen, brick_color[brick_list.index(brick)], brick)
            screen.blit(ball, ballrect)
            screen.blit(board, boardrect)
            # 游戏结束的判断
            if ballrect.bottom > height:
                f1surf, f1rect = f1.render("GAME OVER", fgcolor=Red, size=100)
                screen.blit(f1surf, (450, 300))
                flag = 1
                pause = 1
            if not brick_list:
                f1surf, f1rect = f1.render("YOU WIN", fgcolor=Red, size=100)
                screen.blit(f1surf, (500, 300))
                flag = 1
                pause = 1
            pygame.display.update()
            fclock.tick(fps)
        # 暂停循环
        while pause:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        sys.exit()
                    elif event.key == pygame.K_SPACE:
                        if not flag:
                            pause = 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151

    并为其命名Dog打砖块1.0

    当时游戏十分简陋,没有BGM,也没有什么游戏性;从代码上来说,当时没有学习类与对象,对pygame的熟悉程度也不足,有很多现成方法没有使用。

    但是当时我是很高兴的,毕竟游戏可以运行了嘛。

    让我们看看当时我的试玩视频:

    萌新复现经典游戏打砖块


    打砖块1.1版本,全新出炉

    游戏诞生的喜悦,使我改变了最开始只是简单复现的计划,我打算写进去更多的东西,更完整地复现功能,最好还能有点自己的想法

    当天我就更新了下一个版本,代码量从150增加到240

    这里我就不贴代码了,更新的东西虽然不多,但是我还是试着写了更新日志:
    1.1版本更新日志

    1. 更新了少量bug
    2. 提高了默认速度
    3. 增加了音效与得分系统
    4. 新增两场BOSS战

    这里的BOSS战是我自己想的,打不动的砖块实在是没有什么意思,于是这个版本我更新了两场BOSS战,我们终于可以打BOSS(其实目前只是会动的大砖块)了。

    其中音效素材来源于网络,BOSS的美术素材出自游戏泰拉瑞亚,让我们看看1.1版本的试玩视频:

    打砖块1.1版本,全新出炉


    打砖块1.2!!!BOSS技能

    原有的版本还是太空洞了,无论是不动的砖块还是会动的砖块,它们只能挨打,根本没有游戏难度,同时,传统打砖块在打掉砖块后可能会掉落道具,这一点我之前没有实现。

    我打算实现道具,并为第一个BOSS加上技能,同时为游戏添加BGM,最后为了给我其他没学过Python的同学测评,我将其编译成了.exe文件。

    第一个BOSS是一个飞碟,我希望它能够发射激光,对玩家造成一定的干扰,触碰激光会使挡板宽度减小。

    这个版本添加了四种道具:

    1. +道具:拾取后加长挡板宽度
    2. -道具:拾取后减小挡板宽度
    3. S道具:拾取后加快球的速度
    4. A道具:拾取后增加一点攻击力

    于是,我连肝两天,更新了1.2版本,下面是更新日志:
    打砖块1.2更新日志

    1. 增加道具系统,实现部分道具功能,打砖块会随机掉落
    2. 优化BOSS行为,使之更加正常,降低了BOSS血量
    3. 对BOSS的技能进行了补全
    4. 得分现在不再与速度挂钩,删除了调速器
    5. 添加了BGM
    6. 修复了已知bug
    7. 编译为exe可执行文件,脱离了对python环境的依赖

    代码量从240增加到了410.

    同时这个版本,是我没能通关的第一个版本,所以我录视频的时候,为游戏写了一段代码,让挡板能够自己接球:

    打砖块1.2版本补充视频,程序自玩,摆脱菜鸡作者的下饭操作


    打砖块1.3版本更新,更多模式,更美观的界面

    随着游戏性的提升,越来越多的朋友也参与测评了我的游戏,这个版本我为游戏设计了一个动态的开始界面,背景是随机BOSS与自动挡板的运动。

    我还更新了3个模式提供给不同人群:

    • 无尽模式:只要还有球,游戏就不会结束,提供给大佬刷分。
    • 娱乐模式:提高道具爆率,并减少道具种类,使道具更集中在某几种上,提供给娱乐玩家。
    • 自动模式:挡板跟球运动,自动过关,提供给手残的我。

    值得一提的是,这3个模式可以同时打开。

    除此之外,我完善了第二个BOSS,将它的攻击方式设置为主动将球顶出去,同时它在血量低于一半的时候会进入第二阶段,速度会更快,同时受伤会放出粒子,挡板触碰后会为BOSS提供血量回复.

    增加了商店,可以用得分来换取一定加成:

    • 消耗2000得分增加1速度
    • 消耗3000得分加宽挡板80
    • 消耗4000得分增加1攻击力

    增加了新的道具道具,拾取后会生成一个额外的球。

    还有其他各个方面的优化······

    下面是1.3版本的更新日志:
    1.3版本更新日志

    1. 挡板宽度现在不会小于其厚度了
    2. 由窗口变为全屏模式了
    3. 优化了碰撞反馈,采用了更精确的碰撞模型(完全弹性碰撞)
    4. 修改了部分BOSS的血量和行为,完善了奥库瑞姆的第二阶段
    5. 增加了新道具,“〇”,拾取后会生成一个额外的球
    6. 得分现在可以换取部分加成
    7. 优化了开始界面,使之更加有趣
    8. 加入了无尽模式、娱乐模式、自动模式

    这个版本的代码量从上个版本的410增加到了870

    这也是目前这个游戏的最新版本,让我们看看最后的视频吧:

    打砖块1.3版本更新,更多模式,更美观的界面

    最后在这里放一个游戏最新版本的下载链接,感兴趣的朋友可以下载下来体验一下:
    https://download.csdn.net/download/qq_63585949/86510795?spm=1001.2014.3001.5503


    尾声

    这个游戏今后可能不会更新了,笔者挺过那段无聊的时期之后,就去自学了 C#Unity ,用Python写游戏的想法可能不会再有了。

    以后更多的是Python其他方面的应用了,我会一直努力学习下去的。

    这篇博客,纪念我逝去的青春。

  • 相关阅读:
    德纳 Dana EDI 项目案例
    Raft协议浅析
    axios 请求合集
    数字藏品系统开发,基于区块链智能合约技术
    用rpm -e --nodeps进行批量删除
    数据结构 红黄树 学习笔记
    Postgresql源码(71)子事务数据结构与DDL分析
    全景叙事定位 Towards Real-Time Panoptic Narrative Grounding by an End-to-End Grounding Network 论文阅读笔记
    基于 Docker 快速使用远程(云)数据库
    智安网络|从区块链到社交网络:解析去中心化的意义与应用
  • 原文地址:https://blog.csdn.net/qq_63585949/article/details/126732675