PyGame游戏开发(含源码+演示视频+开结题报告+设计文档)

news2025/5/14 8:52:12

前言:

        大二小学期python课上基于pygame做的一个游戏小demo,当时老师花了一天讲解了下python基础语法后(也是整个大学四年唯一学习python的时间),便让我们自学网课一周然后交项目,所以做的非常仓促(当时没有面向对象概念,以及功能拆分的思想,所以所有代码全堆在一个文件了),也算是自己做的第一个游戏,做完还是有些成就感的,不过很难崩的是结题演示的时候好多同学居然能做出植物大战僵尸这种难度的游戏,(除去看网课去掉二十几个小时基本每天我都在写代码找素材才能做一个相对完整的demo),虽然后来确实在网上看到有用pygame做植物大战僵尸的源码安慰自己他们可能有所参考,不过还是有挺强挫败感的,好在老师人美心善,最后成绩90+,前20%。最近计划重装旧电脑时,还是计划整理下自己的项目,也算是自己大学四年的青春,如果是biter可以关注下,说不定就有你的课设分享。

最后提交内容链接:

Release origin · wlf728050719/BallGamehttps://github.com/wlf728050719/BallGame/releases/tag/1.0.0从release/origin下载BallGame.zip解压即可(含源码+演示视频+开结题报告+设计文档),不建议直接从code下代码,后续可能会基于这个game用强化学习或深度学习设计下人机对战,如果只是完成课设为目标大可不必,不过可以star下关注后续。


环境配置:

只需要安装pygame即可

这是旧电脑没使用anoconda的环境,python3.10.7   pygame 2.1.2

这是新电脑使用的anoconda的环境配置 python3.11 pygame 2.6.0

两种配置都能运行,(虽然感觉使用任意版本的python和pygame应该都能正常运行,不过为了严谨还是写下配置)


代码:

显然直接粘贴代码会缺少资源文件无法运行,不过还是把代码放上来,帮助大家了解pygame设计游戏的基本流程。(虽然无论从变量命名还是逻辑设计都能感受到当时的不成熟)

import random
import sys
import pygame

pygame.init()
size = width, height = 400, 600  # 初始化屏幕

speed: list[int] = [0, 0]  # 小球运动速度
speed1 = [0, 0]  # 挡板向上移动速度
speed2 = [0, 0]  # 挡板向下移动速度
speed3 = [0, 0]  # 障碍物0移动速度
speed4 = [0, 0]  # 障碍物1移动速度
speed5 = [0, 0]  # 障碍物2移动速度
speed6 = [0, 0]  # 障碍物3移动速度


speedx = [0, 0]  # 缓存各对象速度
speed1x = [0, 0]
speed2x = [0, 0]
speed3x = [0, 0]
speed4x = [0, 0]
speed5x = [0, 0]
speed6x = [0, 0]

active: int = 0  # 游戏运行参数 0:游戏第一次开始等待 1:游戏运行 2:游戏暂停 3:游戏结束重新开始等待
case = 0    # 缓冲参数初始化

WHITE = 255, 255, 255  # 字体颜色
m: int = 0  # 当前帧数
z =0

c = 0  # 初始化道具效果随机数
last = 0  # 上一次碰撞板子
gamemap = 1   # 游戏地图序号
speedmode = 1  # 速度模式
myfont = pygame.font.Font(None, 30)  # 设置字体以及大小
long_press = {'up': False, 'down': False}  # 实现连续移动
long_press2 = {'up': False, 'down': False}
bg = pygame.image.load("resources/img/page/game.png")  # 设置背景图片

score1 = 0  # 设置初始得分
score2 = 0

mi = True
screen = pygame.display.set_mode(size, pygame.FULLSCREEN)  # 全屏
a = screen.get_width()  # 获取屏幕宽度
b = screen.get_height()  # 获取屏幕高度
pygame.display.set_caption("双人弹球")  # 标题名
fps: int = 100  # 刷新速度
# 生成 surface对象以及rect对象
ball = pygame.image.load("resources/img/component/ball/ball_0.png")    # 小球运动动图
ballrect = ball.get_rect()
ball1 = pygame.image.load("resources/img/component/ball/ball_1.png")
ball2 = pygame.image.load("resources/img/component/ball/ball_2.png")
ball3 = pygame.image.load("resources/img/component/ball/ball_3.png")
ball4= pygame.image.load("resources/img/component/ball/ball_4.png")

win1 = pygame.image.load("resources/img/component/win/player1_win.png")
win2 = pygame.image.load("resources/img/component/win/player2_win.png")
start = pygame.image.load("resources/img/page/start.png")
banzi1 = pygame.image.load("resources/img/component/player/player.png")
banzi1rect = banzi1.get_rect()
banzi2 = pygame.image.load("resources/img/component/player/player.png")
banzi2rect = banzi2.get_rect()
redball = pygame.image.load("resources/img/component/red_prop/red_prop_1.png")
redballrect = redball.get_rect()

barrier = pygame.image.load("resources/img/component/barrier/barrier_v.png")
barrierrect = barrier.get_rect()
barrier1 = pygame.image.load("resources/img/component/barrier/barrier_v.png")
barrier1rect = barrier1.get_rect()
barrier2 = pygame.image.load("resources/img/component/barrier/barrier_h.png")
barrier2rect = barrier2.get_rect()
barrier3 = pygame.image.load("resources/img/component/barrier/barrier_h.png")
barrier3rect = barrier3.get_rect()

jiantouleft = pygame.image.load("resources/img/component/tip/left.png")
jiantouright = pygame.image.load("resources/img/component/tip/right.png")
xuanzhong = pygame.image.load("resources/img/component/tip/selected.png")
map1 = pygame.image.load("resources/img/component/map/map1.png")
map2 = pygame.image.load("resources/img/component/map/map2.png")
map3= pygame.image.load("resources/img/component/map/map3.png")


banzi2rect = banzi2rect.move(a - 8, 500)  # 确认各对象初始位置
banzi1rect = banzi1rect.move(0, 500)
redballrect = redballrect.move(100, 100)
ballrect = ballrect.move(a / 2, 10)
fclock = pygame.time.Clock()  # 计时

pygame.mixer.init()  # 初始化音频文件

music = pygame.mixer.music.load("resources/audio/bgm/main_bgm_1.mp3")      # 加载音乐文件
pygame.mixer.music.set_volume(0.01)  # 控制背景音乐声音大小
pygame.mixer.music.play()  # 开始播放音乐流
bang = pygame.mixer.Sound("resources/audio/sound_effect/hit.wav")
pop = pygame.mixer.Sound("resources/audio/sound_effect/pop.wav")
shao = pygame.mixer.Sound("resources/audio/sound_effect/whistle.wav")
huanhu = pygame.mixer.Sound("resources/audio/sound_effect/cheer.wav")
anjian = pygame.mixer.Sound("resources/audio/sound_effect/click.wav")

while True:
    if pygame.mixer.music.get_busy() == False:  # 检查是否正在播放音乐
        pygame.mixer.music.play()  # 开始播放音乐流
    for i in pygame.event.get():
        if i.type == pygame.QUIT:    # 退出
            sys.exit()

        elif i.type == pygame.KEYDOWN:  # 挡板连续移动
            if i.key == pygame.K_UP:
                long_press['up'] = True
            if i.key == pygame.K_DOWN:
                long_press['down'] = True
            if i.key == pygame.K_w:
                long_press2['up'] = True
            if i.key == pygame.K_s:
                long_press2['down'] = True

            if i.key == pygame.K_h:   # 选择速度模式
                if active == 0:
                    speedmode = 3
                    anjian.play()
            if i.key == pygame.K_m:
                if active == 0:
                    speedmode = 2
                    anjian.play()
            if i.key == pygame.K_l:
                if active == 0:
                    speedmode = 1
                    anjian.play()

            if i.key == pygame.K_RETURN:  # 按下回车开始游戏
                if active != 1:
                    anjian.play()
                if active == 0:
                    if speedmode == 1:
                        speed = [1, 1]  # 小球运动速度
                        speed1 = [0, -2]  # 挡板向上移动速度
                        speed2 = [0, 2]  # 挡板向下移动速度
                        speed3 = [0, 2]  # 障碍物0移动速度
                        speed4 = [0, -2]  # 障碍物1移动速度
                        speed5 = [2, 0]   # 障碍物2移动速度
                        speed6 = [-2, 0]  # 障碍物3移动速度
                    elif speedmode == 2:
                        speed = [2, 2]  # 小球运动速度
                        speed1 = [0, -3]  # 挡板向上移动速度
                        speed2 = [0, 3]  # 挡板向下移动速度
                        speed3 = [0, 3]  # 障碍物0移动速度
                        speed4 = [0, -3]  # 障碍物1移动速度
                        speed5 = [3, 0]  # 障碍物2移动速度
                        speed6 = [-3, 0]  # 障碍物3移动速度
                    elif speedmode == 3:
                        speed = [3, 3]  # 小球运动速度
                        speed1 = [0, -4]  # 挡板向上移动速度
                        speed2 = [0, 4]  # 挡板向下移动速度
                        speed3 = [0, 4]  # 障碍物0移动速度
                        speed4 = [0, -4]  # 障碍物1移动速度
                        speed5 = [4, 0]  # 障碍物2移动速度
                        speed6 = [-4, 0]  # 障碍物3移动速度
                    active = 1      # 进入游戏运行状态
                elif active == 3:
                    score1 = 0
                    score2 = 0
                    speed = [0, 0]
                    speed1 = [0, 0]
                    speed2 = [0, 0]
                    speed3 = [0, 0]
                    speed4 = [0, 0]
                    speed5 = [0, 0]
                    speed6 = [0, 0]
                    active = 0   # 游戏结束后回到开始界面

            if i.key == pygame.K_SPACE:    # 游戏运行时按下空格暂停,再次按下继续
                anjian.play()
                if active == 1:
                    speedx = speed.copy()
                    speed1x = speed1.copy()
                    speed2x = speed2.copy()
                    speed3x = speed3.copy()
                    speed4x = speed4.copy()
                    speed5x = speed5.copy()
                    speed6x = speed6.copy()
                    speed = [0, 0]
                    speed1 = [0, 0]
                    speed2 = [0, 0]
                    speed3 = [0, 0]
                    speed4 = [0, 0]
                    speed5 = [0, 0]
                    speed6 = [0, 0]
                    active = 2
                elif active == 2:
                    speed = speedx.copy()
                    speed1 = speed1x.copy()
                    speed2 = speed2x.copy()
                    speed3 = speed3x.copy()
                    speed4 = speed4x.copy()
                    speed5 = speed5x.copy()
                    speed6 = speed6x.copy()
                    active = 1

            if i.key == pygame.K_1 or i.key == pygame.K_KP1:  # 选择地图
                if active == 0:
                    anjian.play()
                    gamemap = 1
            if i.key == pygame.K_2 or i.key == pygame.K_KP2:
                if active == 0:
                    anjian.play()
                    gamemap = 2
            if i.key == pygame.K_3 or i.key == pygame.K_KP3:
                if active == 0:
                    anjian.play()
                    gamemap = 3

            elif i.key == pygame.K_ESCAPE:
                sys.exit()
        if i.type == pygame.KEYUP:
            if i.key == pygame.K_UP:
                long_press['up'] = False
            if i.key == pygame.K_DOWN:
                long_press['down'] = False
            if i.key == pygame.K_w:
                long_press2['up'] = False
            if i.key == pygame.K_s:
                long_press2['down'] = False

    if long_press['up']:
        banzi2rect = banzi2rect.move(speed1)
    if long_press['down']:
        banzi2rect = banzi2rect.move(speed2)
    if long_press2['up']:
        banzi1rect = banzi1rect.move(speed1)
    if long_press2['down']:
        banzi1rect = banzi1rect.move(speed2)

    if banzi1rect.top < 0:   # 限制挡板高度
        banzi1rect.top = 0
    if banzi1rect.bottom > height:
        banzi1rect.bottom = height
    if banzi2rect.top < 0:
        banzi2rect.top = 0
    if banzi2rect.bottom > height:
        banzi2rect.bottom = height

    if active == 0:      # 初始化地图
        if gamemap == 1:       # 地图1
            barrierrect.x = a / 2 - 100
            barrierrect.y = b / 2
            barrier1rect.x = a / 2 + 100
            barrier1rect.y = b / 2
        if gamemap == 2:       # 地图2
            barrier2rect.x = 200
            barrier2rect.y = 200
            barrier3rect.x = 550
            barrier3rect.y = 400
        if gamemap == 3:
            barrierrect.x = a / 2 - 100
            barrierrect.y = b / 2
            barrier1rect.x = a / 2 + 100
            barrier1rect.y = b / 2
            barrier2rect.x = 200
            barrier2rect.y = 200
            barrier3rect.x = 550
            barrier3rect.y = 400

    if active == 1:    # 设置不同地图障碍物运行规律以及球与障碍物碰撞效果
        if gamemap == 1:
            barrierrect = barrierrect.move(speed3)  # 障碍物上下移动
            barrier1rect = barrier1rect.move(speed4)
            if barrierrect.top < 0 or barrierrect.bottom > b:
                speed3[1] = -speed3[1]
            if barrier1rect.top < 0 or barrier1rect.bottom > b:
                speed4[1] = -speed4[1]
            f = ballrect.colliderect(barrierrect)
            v = ballrect.colliderect(barrier1rect)
            if f:
                if speed[0] > 0:
                    ballrect.right = barrierrect.left
                    bang.play()
                    speed[0] = - speed[0]
                elif speed[0] < 0:
                    ballrect.left = barrierrect.right
                    bang.play()
                    speed[0] = - speed[0]
            if v:
                if speed[0] > 0:
                    ballrect.right = barrier1rect.left
                    bang.play()
                    speed[0] = - speed[0]
                elif speed[0] < 0:
                    ballrect.left = barrier1rect.right
                    bang.play()
                    speed[0] = - speed[0]



        if gamemap == 2:
            barrier2rect = barrier2rect.move(speed5)  # 障碍物左右移动
            barrier3rect = barrier3rect.move(speed6)
            if barrier2rect.left < 200 or barrier2rect.right > 600:
                speed5[0] = -speed5[0]
            if barrier3rect.left < 200 or barrier3rect.right > 600:
                speed6[0] = -speed6[0]
            f1 = ballrect.colliderect(barrier2rect)
            v1 = ballrect.colliderect(barrier3rect)
            if f1:
                if speed[1] > 0:
                    ballrect.bottom = barrier2rect.top
                    bang.play()
                    speed[1] = - speed[1]
                elif speed[1] < 0:
                    ballrect.top = barrier2rect.bottom
                    bang.play()
                    speed[1] = - speed[1]
            if v1:
                if speed[1] > 0:
                    ballrect.bottom = barrier3rect.top
                    bang.play()
                    speed[1] = - speed[1]
                elif speed[1] < 0:
                    ballrect.top = barrier3rect.bottom
                    bang.play()
                    speed[1] = - speed[1]

        if gamemap == 3:
            barrierrect = barrierrect.move(speed3)  # 障碍物上下移动
            barrier1rect = barrier1rect.move(speed4)
            barrier2rect = barrier2rect.move(speed5)  # 障碍物左右移动
            barrier3rect = barrier3rect.move(speed6)
            if barrierrect.top < 0 or barrierrect.bottom > b:
                speed3[1] = -speed3[1]
            if barrier1rect.top < 0 or barrier1rect.bottom > b:
                speed4[1] = -speed4[1]
            if barrier2rect.left < 200 or barrier2rect.right > 600:
                speed5[0] = -speed5[0]
            if barrier3rect.left < 200 or barrier3rect.right > 600:
                speed6[0] = -speed6[0]
            f = ballrect.colliderect(barrierrect)
            v = ballrect.colliderect(barrier1rect)
            f1 = ballrect.colliderect(barrier2rect)
            v1 = ballrect.colliderect(barrier3rect)
            if f:
                if speed[0] > 0:
                    ballrect.right = barrierrect.left
                    bang.play()
                    speed[0] = - speed[0]
                elif speed[0] < 0:
                    ballrect.left = barrierrect.right
                    bang.play()
                    speed[0] = - speed[0]
            if v:
                if speed[0] > 0:
                    ballrect.right = barrier1rect.left
                    bang.play()
                    speed[0] = - speed[0]
                elif speed[0] < 0:
                    ballrect.left = barrier1rect.right
                    bang.play()
                    speed[0] = - speed[0]
            if f1:
                if speed[1]>0:
                    ballrect.bottom=barrier2rect.top
                    bang.play()
                    speed[1] = - speed[1]
                elif speed[1]<0:
                    ballrect.top = barrier2rect.bottom
                    bang.play()
                    speed[1] = - speed[1]
            if v1:
                if speed[1] > 0:
                    ballrect.bottom = barrier3rect.top
                    bang.play()
                    speed[1] = - speed[1]
                elif speed[1] < 0:
                    ballrect.top = barrier3rect.bottom
                    bang.play()
                    speed[1] = - speed[1]

    screen.blit(bg, (0, 0))   # 绘制背景
    if active == 0:             # 绘制开始界面
        screen.blit(start, (0, 0))

        if speedmode == 1:         # 绘制选中速度效果
            screen.blit(xuanzhong, (52, 335))
        elif speedmode == 2:
            screen.blit(xuanzhong, (201, 335))
        elif speedmode == 3:
            screen.blit(xuanzhong, (346, 335))

        if gamemap == 1:         # 绘制选中地图效果
            screen.blit(xuanzhong, (49, 459))
            screen.blit(map1, (475, 316))
        elif gamemap == 2:
            screen.blit(xuanzhong, (201, 459))
            screen.blit(map2, (475, 316))
        elif gamemap == 3:
            screen.blit(xuanzhong, (346, 459))
            screen.blit(map3, (475, 316))

    if ballrect.right < 0:  # 小球得分判定
        score2 = score2 + 1
    if ballrect.left > a:
        score1 = score1 + 1
    wenzi1 = str(score1)
    wenzi2 = str(score2)
    textImage1 = myfont.render("playerA:" + wenzi1, True, WHITE)
    textImage2 = myfont.render("playerB:" + wenzi2, True, WHITE)

    m = m + 1  # 记录帧数

    if ballrect.right < 0 or ballrect.left > a:  # 小球出界后重新发球

        ballrect.top = 10
        ballrect.left = a / 2+10
        last = 0
        speed = [0, 0]
        z = random.randint(1, 2)
        if active != 3:
            shao.play()
        case = 1
    if m % 400 != 0 and case == 1:  # 预告小球发球方向
        if z == 1:
            screen.blit(jiantouright, (450, 300))
        if z == 2:
            screen.blit(jiantouleft, (310, 300))
    if m % 400 == 0 and case == 1:  # 小球出界后缓冲后并以随机速度及方向发出
        case = 0
        bang.play()
        if z == 1:
            if speedmode == 1:
                speed[0] = random.randint(1, 2)
                speed[1] = random.randint(1, 2)
            elif speedmode == 2:
                speed[0] = random.randint(2, 3)
                speed[1] = random.randint(2, 3)
            elif speedmode == 3:
                speed[0] = random.randint(3, 4)
                speed[1] = random.randint(3, 4)

        elif z == 2:
            if speedmode == 1:
                speed[0] = random.randint(-2, -1)
                speed[1] = random.randint(1, 2)
            elif speedmode == 2:
                speed[0] = random.randint(-3, -2)
                speed[1] = random.randint(2, 3)
            elif speedmode == 3:
                speed[0] = random.randint(-4, -3)
                speed[1] = random.randint(3, 4)

    ballrect = ballrect.move(speed)  # 小球运动
    if ballrect.top < 0 or ballrect.bottom > height:  # 小球上下运动反弹
        speed[1] = - speed[1]
        bang.play()

    # 球与两边挡板撞击效果
    t = ballrect.colliderect(banzi1rect)
    k = ballrect.colliderect(banzi2rect)
    if t:
        ballrect.left = banzi1rect.right
        speed[0] = - speed[0]
        last = 1
        bang.play()

    if k:
        ballrect.right = banzi2rect.left
        speed[0] = - speed[0]
        last = 2
        bang.play()

    f = ballrect.colliderect(redballrect)  # 红色小球被吃掉效果
    if f == True:
        mi = False
        pop.play()
    if mi == False:
        redballrect.left = 2 * a
        redballrect.top = 2 * b  # 小球被吃掉后移出屏幕产生消失效果
        c = random.randint(1, 2)  # 生成随机数c,产生相应效果

    if c == 1:  # 道具效果1:让球上一次碰撞挡板一方加分
        if last == 1:
            score1 = score1 + 5
        if last == 2:
            score2 = score2 + 5

    if c == 2:   # 道具效果2:让球速度最大
        if speed[0] > 0:
            speed[0] = 4
        if speed[0] < 0:
            speed[0] = -4
        if speed[1] > 0:
            speed[1] = 4
        if speed[1] < 0:
            speed[1] = -4

    c = 0  # 重置道具效果

    if m % 2000 == 0:  # 小球位置随机
        x = random.randint(200, 300)
        y = random.randint(200, 300)
        redballrect.left = x
        redballrect.top = y

    if int(m / 1000) % 2 == 0 and active == 1:  # 红色小球周期性出现
        mi = True
        screen.blit(redball, redballrect)
    else:
        redballrect.left = 2 * a
        redballrect.top = 2 * b


    if active == 1 or active == 2:
        if m % 5 == 0:    # 实现小球滚动
            screen.blit(ball, ballrect)
        elif m % 5 == 1:
            screen.blit(ball1, ballrect)
        elif m % 5 == 2:
            screen.blit(ball2, ballrect)
        elif m % 5== 3:
            screen.blit(ball3, ballrect)
        elif m % 5 == 4:
            screen.blit(ball4, ballrect)
        if gamemap == 1:
            screen.blit(barrier, barrierrect)
            screen.blit(barrier1, barrier1rect)
        if gamemap == 2:
            screen.blit(barrier2, barrier2rect)
            screen.blit(barrier3, barrier3rect)
        if gamemap == 3:
            screen.blit(barrier, barrierrect)
            screen.blit(barrier1, barrier1rect)
            screen.blit(barrier2, barrier2rect)
            screen.blit(barrier3, barrier3rect)

        screen.blit(banzi1, banzi1rect)
        screen.blit(banzi2, banzi2rect)
        screen.blit(textImage1, (100, 100))  # 显示字体,确定出现位置
        screen.blit(textImage2, (a - 200, 100))

    if score1 >= 5:  # 游戏结束判定 绘制结束图像
        screen.blit(win1,(300,200))
        active = 3
    if score2 >= 5:
        screen.blit(win2, (300, 200))
        active = 3
    if active == 3:   # 一方获胜暂停游戏
        speed = [0, 0]
        speed1 = [0, 0]
        speed2 = [0, 0]
        speed3 = [0, 0]
        speed4 = [0, 0]
    pygame.display.update()
    fclock.tick(fps)

印象比较深的一个bug是道具球被吃掉时,要么会持续触发道具效果以及会一直渲染在画面中,当时冥思苦想很久最后想出将它移动到屏幕外面,当时简直感觉自己是天才,虽然现在感觉好像没啥。不过好像大多数bug都是没解决的时候很难,解决后感觉这么简单为啥会难住自己这么久。


设计文档:(压缩包里有完整doc文件,这里仅做展示)

(关于分工部分,其实整个项目都是独立开发的,为了老师那边不出问题还是平均分的工,当然这里不是说另外一位同学是摆子,只是他在另外一个小组课设有很大投入,但我在那个项目就单纯做做美工,最终也是90+,所以相当于等价交换了,如果你的课设需要有分工的话可以参考我的划分)以及如果觉得游戏设计文档过于简单,可以参考我大三unity项目的设计文档。

基于Unity3D的游戏开发项目(包含源码与演示视频)_汪洛飞-CSDN博客https://blog.csdn.net/wlf2030/article/details/144664436?spm=1001.2014.3001.5501

整体目标设计:

本游戏在“壁球”游戏上进行改良,扩充为双人对抗类游戏,玩家双方分别使用键盘的“W”“S”以及上下键分别控制屏幕最左侧和最右侧的挡板拦截壁球并进行反弹,屏幕上下边缘以及屏幕中对称排列的挡板会将壁球反弹,屏幕特定区域会定时随机位置出现道具小球,当壁球碰撞到道具小球时会根据道具效果,改变小球的速度以及方向,或者增加壁球上一次碰撞方得分。增加开始与一轮游戏结束界面,玩家能够自由选择游戏难度以及游戏地图,添加小球运动动画效果,添加游戏背景音乐以及音效具有暂停功能,小球出界后不会直接游戏结束,会重新发球,并预告发球方向,直到一方目标达到预设得分玩家在一轮游戏结束后能够选择返回开始界面继续游玩,或者直接退出。

分工说明:

游戏基本框架讨论后共同搭建,游戏文件共享,并标明注释,便于个人测试。

游戏主要功能各自提出自己看法,讨论并测试后编写

个人完成部分功能后向另外成员解释代码含义,发现bug后提出各自意见修复。

xxx:                                  汪洛飞:

游戏方案及类型提出                        碰撞检测

挡板连续移动                              碰撞检测改进

碰撞检测                                  道具小球消失

道具小球消失                              道具小球消失改进

得分记录及文本显示                        小球发球预告

小球道具效果,音效播放                    页面跳转及难度设置

                                          图片,音乐素材

(以上有相同部分表示两人对同一功能有不同的方法或共同参与设计)

代码总体框架:

初始化各种参数,生成surface对象,rect对象。

根据游戏运行参数的不同对不同事件做出相应的处理,包括地图参数以及速度参数的生成

根据地图参数初始化地图,以及地图中障碍物的碰撞效果

绘制开始页面时选中效果

小球得分判定

小球出界后发球以及预告

小球上下边界以及两边挡板反弹效果

道具小球被吃掉以及产生道具效果

小球动图效果以及得分文本显示

游戏结束判定

第三方库介绍:

本游戏仅使用pygame,sys,random库,未引用其他第三方库

运行环境配置以及运行指导说明:

本游戏背景图为800*600像素大小,显示器大小不得小于此。

游戏帧率默认设为100,若显示器无法稳定满足此帧率请自行在代码第49行修改fps数值,(此数值不建议小于60,否则会产生较差视觉效果以及游戏体验)

软件运行截图:

(以下图片均为实机演示,非图片编辑软件修改)

完成度自我评价:

个人认为游戏开发已经十分完整,增加许多功能,已经大大超过游戏设计预期,同时游戏引导人性化,与玩家交互性高。

个人工作:

1.

if m % 5 == 0:    # 实现小球滚动
    screen.blit(ball, ballrect)
elif m % 5 == 1:
    screen.blit(ball1, ballrect)
elif m % 5 == 2:
    screen.blit(ball2, ballrect)
elif m % 5== 3:
    screen.blit(ball3, ballrect)
elif m % 5 == 4:
    screen.blit(ball4, ballrect)

由于pygame不支持播放gif形式图片,使用在不同帧数的情况下,在小球上绘制不同的图片从而达到动图效果的方法

2:

f = ballrect.colliderect(barrierrect)
v = ballrect.colliderect(barrier1rect)
if f:
    if speed[0] > 0:
        ballrect.right = barrierrect.left
        bang.play()
        speed[0] = - speed[0]
    elif speed[0] < 0:
        ballrect.left = barrierrect.right
        bang.play()
        speed[0] = - speed[0]

改进前没有ballrect.right = barrierrect.left部分,导致小球在某些特殊情况下会出现黏在挡板上震动的效果,对游戏体验影响较大

3:

if ballrect.right < 0 or ballrect.left > a:  # 小球出界后重新发球
    ballrect.top = 10
    ballrect.left = a / 2+10
    last = 0
    speed = [0, 0]
    z = random.randint(1, 2)
    if active != 3:
        shao.play()
    case = 1
if m % 400 != 0 and case == 1:  # 预告小球发球方向
    if z == 1:
        screen.blit(jiantouright, (450, 300))
    if z == 2:
        screen.blit(jiantouleft, (310, 300))
if m % 400 == 0 and case == 1:  # 小球出界后缓冲后并以随机速度及方向发出
    case = 0
    bang.play()
    if z == 1:
        if speedmode == 1:
            speed[0] = random.randint(1, 2)
            speed[1] = random.randint(1, 2)

在小球出界后,用帧数是否整除400来进行时间的计算,,先生成随机数后再绘制预告图片,并增加参数case防止预告图片持续显示,时间条件满足后根据生成随机数以及对应的速度模式发球。

4:

f = ballrect.colliderect(redballrect)  # 红色小球被吃掉效果
if f == True:
    mi = False
    pop.play()
if mi == False:
    redballrect.left = 2 * a
    redballrect.top = 2 * b  # 小球被吃掉后移出屏幕产生消失效果
    c = random.randint(1, 2)  # 生成随机数c,产生相应效果

....................................

...................................

...................................

..................................(道具具体效果代码)

if int(m / 1000) % 2 == 0 and active == 1:  # 红色小球周期性出现
    mi = True
    screen.blit(redball, redballrect)
else:
    redballrect.left = 2 * a
    redballrect.top = 2 * b

道具小球与球碰撞后移出屏幕外产生被吃掉效果,并映入mi这一参数,当碰撞后为false,使道具球移出,用int(m/1000)%2==0作为时间判定语句,满足后使mi=true,小球重新回到屏幕

5:

active: int = 0  # 游戏运行参数 0:游戏第一次开始等待 1:游戏运行 2:游戏暂停 3:游戏结束重新开始等待

......

if i.key == pygame.K_1 or i.key == pygame.K_KP1:  # 选择地图
    if active == 0:
        anjian.play()
        gamemap = 1

.....................

if score1 >= 6:  # 游戏结束判定 绘制结束图像
    screen.blit(win1,(300,200))
    active = 3

....................
if active == 3:   # 一方获胜暂停游戏
    speed = [0, 0]
    speed1 = [0, 0]
    speed2 = [0, 0]
    speed3 = [0, 0]
    speed4 = [0, 0]

(由于游戏运行参数作为游戏状态判定的依据,在游戏代码中出现次数过多,且位于各个部分,现只展示代表性代码)

引入游戏运行参数,使游戏避免引用pgu库便产生多级页面效果,并根据玩家产生的事件改变参数的数值,从而产生页面的跳转效果,但分析后得知,此方法仅适用于页面较少的情况,页面过多会导致参数值太多,代码层次混乱,不建议大量使用。


开题PPT:(压缩包里有完整ppt文件,这里仅做展示)


结题PPT:(压缩包里有完整ppt文件,这里仅做展示)


演示视频:

因为以现在的眼光确实很简单就不上传到b站或博客了,需要可自行解压压缩包查看。


最后:

        兴趣确实是最好的老师,写这篇博客感觉像是和过去的自己对话,当时确实仍有满腔热血,能熬夜两三点写游戏代码,现在读研感觉无论找工作或是做学术都会有很大压力,以及从我的博客也能看出比较偏向java分布式以及python深度学习了,以后从业也基本与游戏无缘了,还是有些可惜。最后还是祝各位能永远热爱你所热爱的!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2375246.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

拒绝flash插件打劫!如何在vscode上玩4399小游戏

现在电脑上玩4399都需要flash插件了 这也导致了很多人无法玩到小时候的游戏 今天介绍一款插件 功能强大 即安即玩 首先打开vscode 点开小方框&#xff08;拓展&#xff09;搜索4399 认准4399 on vscode点击安装 安装完毕后 按下 Ctrl Shift P , 输入 4399 on VSCode 或…

learning ray之ray核心设计和架构

我们每天都在处理海量、多样且高速生成的数据&#xff0c;这对计算能力提出了前所未有的挑战。传统的单机计算模式在面对日益复杂的机器学习模型和大规模数据集时&#xff0c;往往显得力不从心。更重要的是&#xff0c;数据科学家们本应专注于模型训练、特征工程、超参数调优这…

C语言while循环的用法(非常详细,附带实例)

while 是 C 语言中的一种循环控制结构&#xff0c;用于在特定条件为真时重复执行一段代码。 while 循环的语法如下&#xff1a; while (条件表达式) { // 循环体&#xff1a;条件为真时执行的代码 } 条件表达式&#xff1a;返回真&#xff08;非 0&#xff09;或假&#x…

JavaScript进阶(九)

第三部分:JavaScript进阶 目录 第三部分:JavaScript进阶 一、作用域 1.1 局部作用域 1. 作用域 2. 局部作用域 函数作用域 块作用域 1.2 全局作用域 1.3 作用域链 1.4 JS垃圾回收机制 1. 什么是垃圾回收机制 2. 内存的声明周期 3. 垃圾回收的算法说明 引用计数…

数据结构与算法分析实验11 实现顺序查找表

实现顺序查找表 1.上机名称2.上机要求3.上机环境4.程序清单(写明运行结果及结果分析)4.1 程序清单4.1.1 头文件4.1.2 实现文件4.1.3 源文件 4.2 实现展效果示 上机体会 1.上机名称 实现顺序查找表 顺序查找表的基本概念 顺序查找表是一种线性数据结构&#xff0c;通常用于存储…

获取高德地图JS API的安全密钥和Key的方法

要使用高德地图JavaScript API&#xff0c;您需要获取API Key和安全密钥(securityJsCode)。以下是获取步骤&#xff1a; 1. 注册高德开放平台账号 首先访问高德开放平台&#xff0c;如果没有账号需要先注册。 2. 创建应用获取Key 登录后进入"控制台" 点击"应…

JAVA研发+前后端分离,ZKmall开源商城B2C商城如何保障系统性能?

在电商行业竞争白热化的当下&#xff0c;B2C 商城系统的性能表现成为决定用户留存与商业成败的关键因素。ZKmall 开源商城凭借 Java 研发与前后端分离架构的深度融合&#xff0c;构建起一套高效、稳定且具备强大扩展性的系统架构&#xff0c;从底层技术到上层应用全方位保障性能…

嵌入式自学第二十天(5.13)

&#xff08;1&#xff09;线性表顺序存储的优缺点&#xff1a; 优点&#xff1a;无需为表中逻辑关系添加额外存储空间&#xff1b; 可以快速随机访问元素&#xff0c;时间复杂度O(1)。 缺点&#xff1a;插入删除需要移动元素O(n&#xff09;&#xff1b; 无法动态存储。 …

快速上手Linux nfs网络文件系统

一、nfs服务的安装与部属 1.安装软件 设置火墙 测试&#xff1a;在客户端上安装nfs-utils后 showmount 服务端IP 2.共享资源 测试&#xff1a; 参数&#xff08;参数写在共享策略文件的括号里&#xff09; 二、nfs客户端动态挂载机制 当客户端和服务器之间没有数据交互时&am…

26考研——中央处理器_异常和中断机制(5)

408答疑 文章目录 五、异常和中断机制异常和中断的基本概念异常和中断的分类异常的分类故障 (Fault)自陷 (Trap)终止 (Abort) 中断的分类可屏蔽中断不可屏蔽中断 异常和中断响应过程关中断保存断点和程序状态识别异常和中断并转到相应的处理程序 八、参考资料鲍鱼科技课件26王道…

数据库实验报告 SQL SERVER 2008的基本操作 1

实验报告&#xff08;第 1 次&#xff09; 实验名称 SQL SERVER 2008的基本操作 实验时间 9月14日1-2节 一、实验内容 数据库的基本操作:包括创建、修改、附加、分离和删除数据库等。 二、源程序及主要算法说明 本次实验不涉及程序和算法。 三、测…

Nature图形复现—两种快速绘制热图的方法

相信大家在科研过程中&#xff0c;会遇到热图&#xff0c;有时候会觉得热图理解起来比较困难&#xff0c;或者觉得绘制热图也比较困难。本期教程我们来深入了解热图、绘制热图。 热图是一种通过颜色深浅或色阶变化来直观展示数据分布、密度或数值大小的可视化工具。它在多个领域…

INFINI Console 纳管 Elasticsearch 9(一):指标监控、数据管理、DSL 语句执行

Elasticsearch v9.0 版本最近已发布&#xff0c;而 INFINI Console 作为一款开源的非常轻量级的多集群、跨版本的搜索基础设施统一管控平台&#xff0c;是否支持最新的 Elasticsearch v9.0 集群管理呢&#xff1f;本文以 INFINI Console v1.29.2 为例&#xff0c;从指标监控、数…

texlive 与 Texmaker 安装

一、安装 Texmaker 1、下载Texmaker 链接地址: Texmaker (free cross-platform latex editor) 点击 FREE DOWNLOAD &#xff0c;点击 Texmaker_6.0.1_Win_x64.msi &#xff0c;下载即可。 2、安装Texmaker 双击如下文件 若出现如下&#xff0c;点击更多信息 点击仍要运行 …

机试刷题:进制转换3

题目来源&#xff1a;N诺 一、题目描述 二、解题思路 过程模拟&#xff0c;先转换为十进制&#xff0c;再转换为N进制即可。 注意&#xff1a;转换的时候可能出现字母&#xff0c;注意字母的表示。 用string和char类型对数据进行存储要更方便。 #include <iostream>…

(顺序表、单链表、双链表)==>一篇解决!(Java版)

文章目录 一、线性表二、顺序表三、单链表四、双链表 一、线性表 线性表是最基本、最简单、也是最常用的一种数据结构。一个线性表是n个具有相同特性的数据元素的有限序列。 线性表的特征&#xff1a;数据元素之间具有一种“一对一”的逻辑关系。 线性表的分类&#xff1a; 线…

JPG与PDF格式转换器

该插件可实现JPG与PDF格式的互转。 MainForm.Designer.cs using System.Windows.Forms; namespace JpgToPdfConverter {partial class MainForm{private System.ComponentModel.IContainer components null;protected override void Dispose(bool disposing){if (disposing &…

手搓传染病模型(SEIARW)

在传染病传播的研究中&#xff0c;水传播途径是一个重要的考量因素。SEAIRW 模型&#xff08;易感者 S - 暴露者 E - 感染者 I - 无症状感染者 A - 康复者 R - 水中病原体 W&#xff09;综合考虑了人与人接触传播以及水传播的双重机制&#xff0c;为分析此类传染病提供了全面的…

【Mac 从 0 到 1 保姆级配置教程 15】- Python 环境一键安装与配置,就是这么的丝滑

文章目录 前言安装 Python 环境VSCode 配置Python 环境NeoVim 配置 Python 环境&#xff08;选看&#xff09;1. Python LSP 配置2. 打开 python 语言支持 最后参考资料系列教程 Mac 从 0 到 1 保姆级配置教程目录&#xff0c;点击即可跳转对应文章&#xff1a; 【Mac 从 0 到 …

【递归、搜索与回溯】专题一:递归(二)

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人递归&#xff0c;搜索与回溯算法的学习以及LeetCode刷题记录&#xff0c;按专题划分每题主要记录&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代码&#xff1b;&#xff08;2&#xff09;优质解法 优质代码…