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

前言:

        大二小学期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 pygamepygame.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 =0c = 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 = 0mi = 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'] = Trueif i.key == pygame.K_DOWN:long_press['down'] = Trueif i.key == pygame.K_w:long_press2['up'] = Trueif i.key == pygame.K_s:long_press2['down'] = Trueif i.key == pygame.K_h:   # 选择速度模式if active == 0:speedmode = 3anjian.play()if i.key == pygame.K_m:if active == 0:speedmode = 2anjian.play()if i.key == pygame.K_l:if active == 0:speedmode = 1anjian.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 = 0score2 = 0speed = [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 = 2elif active == 2:speed = speedx.copy()speed1 = speed1x.copy()speed2 = speed2x.copy()speed3 = speed3x.copy()speed4 = speed4x.copy()speed5 = speed5x.copy()speed6 = speed6x.copy()active = 1if i.key == pygame.K_1 or i.key == pygame.K_KP1:  # 选择地图if active == 0:anjian.play()gamemap = 1if i.key == pygame.K_2 or i.key == pygame.K_KP2:if active == 0:anjian.play()gamemap = 2if i.key == pygame.K_3 or i.key == pygame.K_KP3:if active == 0:anjian.play()gamemap = 3elif i.key == pygame.K_ESCAPE:sys.exit()if i.type == pygame.KEYUP:if i.key == pygame.K_UP:long_press['up'] = Falseif i.key == pygame.K_DOWN:long_press['down'] = Falseif i.key == pygame.K_w:long_press2['up'] = Falseif i.key == pygame.K_s:long_press2['down'] = Falseif 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 = 0if banzi1rect.bottom > height:banzi1rect.bottom = heightif banzi2rect.top < 0:banzi2rect.top = 0if banzi2rect.bottom > height:banzi2rect.bottom = heightif active == 0:      # 初始化地图if gamemap == 1:       # 地图1barrierrect.x = a / 2 - 100barrierrect.y = b / 2barrier1rect.x = a / 2 + 100barrier1rect.y = b / 2if gamemap == 2:       # 地图2barrier2rect.x = 200barrier2rect.y = 200barrier3rect.x = 550barrier3rect.y = 400if gamemap == 3:barrierrect.x = a / 2 - 100barrierrect.y = b / 2barrier1rect.x = a / 2 + 100barrier1rect.y = b / 2barrier2rect.x = 200barrier2rect.y = 200barrier3rect.x = 550barrier3rect.y = 400if 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.leftbang.play()speed[0] = - speed[0]elif speed[0] < 0:ballrect.left = barrierrect.rightbang.play()speed[0] = - speed[0]if v:if speed[0] > 0:ballrect.right = barrier1rect.leftbang.play()speed[0] = - speed[0]elif speed[0] < 0:ballrect.left = barrier1rect.rightbang.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.topbang.play()speed[1] = - speed[1]elif speed[1] < 0:ballrect.top = barrier2rect.bottombang.play()speed[1] = - speed[1]if v1:if speed[1] > 0:ballrect.bottom = barrier3rect.topbang.play()speed[1] = - speed[1]elif speed[1] < 0:ballrect.top = barrier3rect.bottombang.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.leftbang.play()speed[0] = - speed[0]elif speed[0] < 0:ballrect.left = barrierrect.rightbang.play()speed[0] = - speed[0]if v:if speed[0] > 0:ballrect.right = barrier1rect.leftbang.play()speed[0] = - speed[0]elif speed[0] < 0:ballrect.left = barrier1rect.rightbang.play()speed[0] = - speed[0]if f1:if speed[1]>0:ballrect.bottom=barrier2rect.topbang.play()speed[1] = - speed[1]elif speed[1]<0:ballrect.top = barrier2rect.bottombang.play()speed[1] = - speed[1]if v1:if speed[1] > 0:ballrect.bottom = barrier3rect.topbang.play()speed[1] = - speed[1]elif speed[1] < 0:ballrect.top = barrier3rect.bottombang.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 + 1if ballrect.left > a:score1 = score1 + 1wenzi1 = 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 = 10ballrect.left = a / 2+10last = 0speed = [0, 0]z = random.randint(1, 2)if active != 3:shao.play()case = 1if 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 = 0bang.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.rightspeed[0] = - speed[0]last = 1bang.play()if k:ballrect.right = banzi2rect.leftspeed[0] = - speed[0]last = 2bang.play()f = ballrect.colliderect(redballrect)  # 红色小球被吃掉效果if f == True:mi = Falsepop.play()if mi == False:redballrect.left = 2 * aredballrect.top = 2 * b  # 小球被吃掉后移出屏幕产生消失效果c = random.randint(1, 2)  # 生成随机数c,产生相应效果if c == 1:  # 道具效果1:让球上一次碰撞挡板一方加分if last == 1:score1 = score1 + 5if last == 2:score2 = score2 + 5if c == 2:   # 道具效果2:让球速度最大if speed[0] > 0:speed[0] = 4if speed[0] < 0:speed[0] = -4if speed[1] > 0:speed[1] = 4if speed[1] < 0:speed[1] = -4c = 0  # 重置道具效果if m % 2000 == 0:  # 小球位置随机x = random.randint(200, 300)y = random.randint(200, 300)redballrect.left = xredballrect.top = yif int(m / 1000) % 2 == 0 and active == 1:  # 红色小球周期性出现mi = Truescreen.blit(redball, redballrect)else:redballrect.left = 2 * aredballrect.top = 2 * bif 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 = 3if score2 >= 5:screen.blit(win2, (300, 200))active = 3if 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后提出各自意见修复。

杨宜松:                                  汪洛飞:

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

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

碰撞检测                                  道具小球消失

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

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

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

                                          图片,音乐素材

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

代码总体框架:

初始化各种参数,生成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.leftbang.play()speed[0] = - speed[0]elif speed[0] < 0:ballrect.left = barrierrect.rightbang.play()speed[0] = - speed[0]

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

3:

if ballrect.right < 0 or ballrect.left > a:  # 小球出界后重新发球ballrect.top = 10ballrect.left = a / 2+10last = 0speed = [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 = 0bang.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 = Falsepop.play()
if mi == False:redballrect.left = 2 * aredballrect.top = 2 * b  # 小球被吃掉后移出屏幕产生消失效果c = random.randint(1, 2)  # 生成随机数c,产生相应效果............................................................................................................................................(道具具体效果代码)if int(m / 1000) % 2 == 0 and active == 1:  # 红色小球周期性出现mi = Truescreen.blit(redball, redballrect)
else:redballrect.left = 2 * aredballrect.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.mzph.cn/bicheng/80602.shtml

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

相关文章

使用 React 实现语音识别并转换功能

在现代 Web 开发中&#xff0c;语音识别技术的应用越来越广泛。它为用户提供了更加便捷、自然的交互方式&#xff0c;例如语音输入、语音指令等。本文将介绍如何使用 React 实现一个简单的语音识别并转换的功能。 功能概述 我们要实现的功能是一个语音识别测试页面&#xff0…

C++ 双峰高斯函数拟合

C 双峰高斯函数拟合 一维高斯函数二维高斯函数多维高斯函数一维双峰高斯函数代码实现 二维双峰高斯函数代码实现 多维多峰高斯函数 在数据分析与清洗中经常遇到这样的数据&#xff1a;数据不仅仅向单个中心靠拢&#xff0c;而是类似分段的向两个甚至多个中心靠拢。数据向单个中…

【RP2350】香瓜树莓派RP2350之LED

本文最后修改时间&#xff1a;2025年05月10日 01:57 一、本节简介 本节以树莓派pico2开发板为例&#xff0c;举例如何写一个LED驱动加进工程里。 二、实验平台 1、硬件平台 1&#xff09;树莓派pico2开发板 ①树莓派pico2开发板&#xff08;作为仿真器&#xff09; ②micr…

机器人运动控制原理浅析-UC Berkeley超视觉模态模型

加州伯克利发布的超视觉多感知模态融合(FuSe, Fuse Heterogeneous Sensory Data)模型&#xff0c;基于视觉、触觉、听觉、本体及语言等模态&#xff0c;利用自然语言跨模态对齐(Cross-Modal Grounding)优调视觉语言动作等通用模型&#xff0c;提高模型任务成功率。 总体框架 …

【Bootstrap V4系列】学习入门教程之 组件-媒体对象(Media object)

Bootstrap V4系列 学习入门教程之 组件-媒体对象&#xff08;Media object&#xff09; 媒体对象&#xff08;Media object&#xff09;一、Example二、Nesting 嵌套三、Alignment 对齐四、Order 顺序五、Media list 媒体列表 媒体对象&#xff08;Media object&#xff09; B…

解决VirtualBox中虚拟机(ubuntu)与主机(windows)之间互相复制粘贴(文本)

一.开始的设置 1.在VirtualBox中打开设置&#xff0c;常规中修改主机与虚拟机交互设置 2.虚拟机关闭状态下&#xff0c;存储中选中控制器SATA&#xff0c;勾选‘使用主机输入输出’ 3.选中操作系统对应的虚拟文件&#xff0c;.vdi文件&#xff0c;勾选右边的固态驱动器。 4.启…

java 多核,多线程,分布式 并发编程的现状 :从本身的jdk ,到 spring ,到其它第三方。

Java 在多核、多线程和高性能编程领域提供了丰富的现成框架和工具&#xff0c;既有标准库中的并发组件&#xff0c;也有第三方框架。以下是一些关键框架及其应用场景的总结&#xff1a;便于后面我们站在巨人的肩膀上&#xff0c;继续前行 一、Java 标准库中的多线程框架 Execut…

Nodejs核心机制

文章目录 前言 前言 结合 Node.js 的核心机制进行说明&#xff1a; 解释事件循环的各个阶段。 答案 Node.js 事件循环分为 6 个阶段&#xff0c;按顺序执行&#xff1a; Timers&#xff1a;执行 setTimeout 和 setInterval 的回调。 Pending I/O Callbacks&#xff1a;处理系…

C++笔记6:数字字面量后缀和前缀总结

在C中&#xff0c;可以在数字字面量后面添加字母后缀&#xff08;或前缀&#xff09;来表示特定的数据类型。这些后缀能够明确指定字面量的类型&#xff0c;避免类型转换带来的潜在问题。以下是常见的几种类型后缀及其含义&#xff1a; 1. 整数后缀 u 或 U&#xff1a;表示 u…

50.辐射抗扰RS和传导抗扰CS测试环境和干扰特征分析

辐射抗扰RS和传到抗扰CS测试环境和干扰特征分析 1. 辐射抗扰RS2. 传导抗扰CS 1. 辐射抗扰RS 辐射抗扰RS考察对外界电磁场干扰得抗扰能力&#xff0c;测试频段为80MHz~2000MHz&#xff0c;用1KHz得正弦波进行调幅&#xff0c;在电波暗室内进行。测试标准&#xff1a;IEC 61000-…

Java多态详解

Java多态详解 什么是多态&#xff1f; 比如我们说&#xff1a;“驾驶一辆车”&#xff0c;有人开的是自行车&#xff0c;有人开的是摩托车&#xff0c;有人开的是汽车。虽然我们都说“开车”&#xff0c;但“怎么开”是由具体的车类型决定的&#xff1a;“开”是统一的动作&a…

问题及解决01-面板无法随着窗口的放大而放大

在MATLAB的App Designer中&#xff0c;默认情况下&#xff0c;组件的位置是固定的&#xff0c;不会随着父容器的大小变化而改变。问题图如下图所示。 解决&#xff1a; 为了让Panel面板能够随着UIFigure父容器一起缩放&#xff0c;需要使用布局管理器&#xff0c;我利用 MATLA…

【GESP真题解析】第 20 集 GESP 二级 2025 年 3 月编程题 2:时间跨越

大家好,我是莫小特。 这篇文章给大家分享 GESP 二级 2025 年 3 月编程题第 2 题:时间跨越。 题目链接 洛谷链接:B4260 时间跨越 一、完成输入 根据题意,输入包含五行,每行一个正整数,分别代表 y,m,d,h,k。 注意到数据范围:对于全部数据,保证有 2000≤y≤3000,1≤m≤…

GTS-400 系列运动控制器板卡介绍(二十一)---电子齿轮跟随

运动控制器函数库的使用 运动控制器驱动程序、dll 文件、例程、Demo 等相关文件请通过固高科技官网下载,网 址为:www.googoltech.com.cn/pro_view-3.html 1 Windows 系统下动态链接库的使用 在 Windows 系统下使用运动控制器,首先要安装驱动程序。在安装前需要提前下载运动…

软件工程之需求分析涉及的图与工具

需求分析与规格说明书是一项十分艰巨复杂的工作。用户与分析员之间需要沟通的内容非常的多&#xff0c;在双方交流信息的过程中很容易出现误解或遗漏&#xff0c;也可能存在二义性。如何才能更加准确的表达双方的意思&#xff0c;且清楚明了&#xff0c;绘制各类图形就显得非常…

蓝桥杯14届 数三角

问题描述 小明在二维坐标系中放置了 n 个点&#xff0c;他想在其中选出一个包含三个点的子集&#xff0c;这三个点能组成三角形。然而这样的方案太多了&#xff0c;他决定只选择那些可以组成等腰三角形的方案。请帮他计算出一共有多少种选法可以组成等腰三角形&#xff1f; 输…

在Fiddler中添加自定义HTTP方法列并高亮显示

在Fiddler中添加自定义HTTP方法列并高亮显示 Fiddler 是一款强大的 Web 调试代理工具&#xff0c;允许开发者检查和操作 HTTP 流量。一个常见需求是自定义 Web Sessions 列表&#xff0c;添加显示 HTTP 方法&#xff08;GET、POST 等&#xff09;的列&#xff0c;并通过颜色区…

数据库分库分表实战指南:从原理到落地

1. 为什么要分库分表&#xff1f; 1.1 单库瓶颈表现 存储瓶颈&#xff1a;单表数据超过5000万行&#xff0c;查询性能急剧下降性能瓶颈&#xff1a;单库QPS超过5000后响应延迟显著增加可用性风险&#xff1a;单点故障导致全系统不可用 1.2 突破性优势 --------------------…

Selenium的driver.get_url 和 手动输入网址, 并点击的操作,有什么不同?

我在搞爬取的时候&#xff0c;发现有些网站直接用driver.get(url) 跳转到目标特定的网址的时候&#xff0c;会被强制跳转到其他的网址上&#xff0c;但是如果是自己手动&#xff0c;在网址栏那里输入网址&#xff0c;并点回车&#xff0c;却能完成跳转。 这是在使用 Selenium …

Java【06】数组查找(二分查找)、排序(冒泡排序、简单选择排序)

1. 数组的操作 1.1 数组的反转 int[] arrs{3,5,7,8,9}; 编写程序&#xff0c;让arrs中的数据进行反转{9,8,7,5,3} 1.2数组的查找 ① 顺序查找 从头到尾一个一个的找&#xff01; ② 二分查找 对数组有一个要求&#xff1a;数组必须是有序(大小)的&#xff01; int num3; int[]…