当前位置: 首页 > news >正文

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深度学习了,以后从业也基本与游戏无缘了,还是有些可惜。最后还是祝各位能永远热爱你所热爱的!

相关文章:

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

前言&#xff1a; 大二小学期python课上基于pygame做的一个游戏小demo&#xff0c;当时老师花了一天讲解了下python基础语法后&#xff08;也是整个大学四年唯一学习python的时间&#xff09;&#xff0c;便让我们自学网课一周然后交项目&#xff0c;所以做的非常仓促&#xff…...

Git标签

Git标签 1. 添加标签 使用 tag 命令可以给某次 commit 提交的版本打上标签&#xff0c;相当于这个 commit id 的别名&#xff0c;在实践中&#xff0c;会使用 v1.0 之类的标签提示这是正式版的第一个版本。 git tag v1.0 [commit id]缺省输入 commit id会给最新的一次提交打…...

USB学习【6】USB传输错误的处理

1.前言 我们从物理层到信号层&#xff0c;到协议层&#xff0c;他们分别在不同的层面完成不同的功能。 总结一下&#xff1a; 物理层实现了高低电平的检测。 信号层更进一步&#xff0c;通过一些方法&#xff0c;实现了二进制的传输。 协议层&#xff0c;因为可以二进制传输了…...

深入解析 Vision Transformer (ViT) 与其在计算机视觉中的应用

在近年来&#xff0c;深度学习尤其在计算机视觉领域取得了巨大的进展&#xff0c;而 Vision Transformer&#xff08;ViT&#xff09;作为一种新的视觉模型&#xff0c;它的表现甚至在许多任务中超过了传统的卷积神经网络&#xff08;CNN&#xff09;&#xff0c;如 ResNet。在…...

《Go小技巧易错点100例》第三十一篇

本期分享&#xff1a; 1.Go struct内存对齐 2.使用空结构体(struct{})节省内存 Go struct内存对齐 在计算机系统中&#xff0c;CPU 访问内存时并不是逐字节读取的&#xff0c;而是以特定大小的块&#xff08;通常为 4/8 字节&#xff09;为单位进行读取。当数据的内存地址正…...

全栈项目实战:Vue3+Node.js开发博客系统

全栈项目实战&#xff1a;Vue3Node.js开发博客系统 一、项目架构设计 1. 技术栈选型 前端技术栈&#xff1a; Vue 3 Composition APITypeScriptPinia状态管理Vue Router 4Element Plus UI组件库Vite构建工具 后端技术栈&#xff1a; Node.js (Express/Koa)MongoDB (Mong…...

查看YOLO版本的三种方法

查看YOLO版本的三种方法&#xff1a; 一、通过命令行直接查询 使用Python交互式查询&#xff1a; from ultralytics import __version__ print(__version__) # 示例输出: 11.0.5二、检查PyTorch环境兼容性 import torch, ultralytics print(f"PyTorch: {torch.__versi…...

基于Docker的Bitwarden的私有本地部署

基于Docker的Bitwarden的私有本地部署 文章目录 基于Docker的Bitwarden的私有本地部署 本文首发地址 https://h89.cn/archives/355.html bitwarden 默认连接的是国外服务器 https://bitwarden.com/ &#xff0c;连接不是很稳定&#xff0c;也没有安全感&#xff0c;所以我选择了…...

点和体素哪个好

3D 深度学习中基于体素和基于点云的方法哪种更优&#xff1f;-腾讯云开发者社区-腾讯云 https://zhuanlan.zhihu.com/p/372497398 GitHub - open-mmlab/OpenPCDet: OpenPCDet Toolbox for LiDAR-based 3D Object Detection....

C++ STL编程 vector空间预留、vector高效删除、vector数据排序、vector代码练习

vector空间预留&#xff0c;作用是避免申请每次申请内存&#xff0c;提高运行效率。 对应的接口是 vector.reverse() vector的高效删除&#xff0c;对应的代码见下&#xff0c;一个时间复杂度是n&#xff0c;一个时间复杂度是1 #include<iostream> #include<vector…...

Android架构模式推荐及分析和MVC架构模式制作一个简单的底部tab切换

目录 主流架构模式对比 适用场景 MVP‌&#xff1a;团队协作开发,需要高可测试性的项目 MVC架构模式制作一个简单的底部tab切换 &#xff08;Model-View-Controller&#xff09;结构 代码 效果 主流架构模式对比 ‌对比维度‌‌MVC‌ ‌MVP‌ ‌MVVM‌ ‌MVI‌ ‌学习…...

【PVE】ProxmoxVE8虚拟机,存储管理(host磁盘扩容,qcow2/vmdk导入vm,vm磁盘导出与迁移等)

【PVE】ProxmoxVE8虚拟机&#xff0c;存储管理&#xff08;host磁盘扩容&#xff0c;qcow2/vmdk导入vm&#xff0c;vm磁盘导出与迁移等&#xff09; 文章目录 1、host 磁盘扩容2、qcow2/vmdk导入vm3、vm 磁盘导出与迁移 1、host 磁盘扩容 如何给host扩容磁盘&#xff0c;如增加…...

【JEECG 组件扩展】JSwitch开关组件扩展单个多选框样式

功能说明&#xff1a; 基于JeecgBoot开源框架&#xff0c;JSwitch开关组件扩展&#xff0c;支持单个多选样式。 效果展示&#xff1a; 使用示例&#xff1a; {field: JSwitch,component: JSwitch,label: JSwitch,},{field: JSwitchCheckBox,component: JSwitch,label: JSwitch…...

卷积神经网络-从零开始构建一个卷积神经网络

目录 一、什么是卷积神经网络CNN 1.1、核心概念 1.2、卷积层 二、什么是卷积计算 2.1、卷积计算的例子: 2.2、点积 2.3、卷积与点积的关系 2.4、Padding(填充) 2.4.1、Padding的主要作用 1、控制输出特征图尺寸 2、保留边缘信息 3. 支持深层网络训练 2.4.2、Str…...

Linux 常用命令集合

以下是一份 Linux 常用命令集合&#xff0c;涵盖文件操作、系统管理、网络管理、权限管理、进程管理等常见任务&#xff0c;并附上代码示例&#xff1a; 1. 文件与目录操作 命令作用示例ls列出目录内容ls -l&#xff08;详细列表&#xff09; ls -a&#xff08;显示隐藏文件&a…...

STM32f103 标准库 零基础学习之按键点灯(不涉及中断)

注意&#xff0c;此次代码不涉及中断&#xff0c;不涉及中断&#xff0c;不涉及中断 目录 1.初始化LED 2.初始化按键 3.粗略的延时函数 4.判断引脚电平 5.通过异或反转电平 开始 │ ├── 初始化LED&#xff08;GPIOA Pin1 推挽输出&#xff09; ├── 初始化按键&…...

【c++】【数据结构】二叉搜索树详解

目录 二叉搜索树的定义二叉搜索树的模拟实现查找函数循环版递归版 插入函数循环版递归版 删除函数循环版递归版 二叉搜索树的定义 二叉搜索树是一种特别的二叉树&#xff0c;是二叉树的搜索特化版。学过排序的都知道&#xff0c;在数组有序的情况下二分查找可以以极高的频率找…...

高精地图数据错误的侵权责任认定与应对之道

首席数据官高鹏律师团队 在自动驾驶与智慧交通快速发展的今天&#xff0c;高精地图作为核心基础设施&#xff0c;其数据准确性直接关系到公共安全。然而&#xff0c;技术并非完美&#xff0c;一旦因地图数据错误导致事故或损失&#xff0c;比如当自动驾驶汽车因高精地图数据错…...

Python训练营打卡——DAY22(2025.5.11)

复习日 学习参考如何使用kaggle平台&#xff0c;写下使用注意点&#xff0c;并对下述比赛提交代码 泰坦尼克号——来自灾难的机器学习 数据来源&#xff1a; kaggle泰坦里克号人员生还预测 挑战 泰坦尼克号沉没是历史上最臭名昭著的海难之一。 1912年4月15日&#xff0c;在被普…...

【计算机视觉】OpenCV实战项目 :Image_Cartooning_Web_App:基于深度学习的图像卡通化

Image_Cartooning_Web_App&#xff1a;基于深度学习的图像卡通化Web应用深度解析 1. 项目概述2. 技术原理与模型架构2.1 核心算法2.2 系统架构 3. 实战部署指南3.1 环境配置3.2 模型部署3.3 处理流程示例 4. 常见问题与解决方案4.1 模型加载失败4.2 显存溢出4.3 边缘伪影 5. 关…...

王道计算机网络知识点总结

计算机网络知识点总结 一、计算机网络体系结构 &#xff08;一&#xff09;计算机网络概述 计算机网络概念&#xff1a;互连的、自治的计算机系统的集合&#xff0c;目的是资源共享&#xff0c;组成包括多台自治计算机&#xff0c;规则是网络协议。 计算机网络的组成&#…...

Java学习笔记(对象)

一、对象本质 状态&#xff08;State&#xff09;&#xff1a;通过成员变量&#xff08;Field&#xff09;描述 行为&#xff08;Behavior&#xff09;&#xff1a;通过成员方法&#xff08;Method&#xff09;实现 class Person {String name;int age;void eat() {System.o…...

并发笔记-给数据上锁(二)

文章目录 核心挑战 (The CRUX)29.1 并发计数器 (Concurrent Counters)1. 简单非并发计数器 (Figure 29.1)2. 同步计数器&#xff08;单锁版本 - Coarse-Grained Lock, Figure 29.2&#xff09;3. 可伸缩计数&#xff1a;近似/懒惰计数器 (Approximate/Sloppy Counter, Figure 2…...

Three.js + React 实战系列 - 页脚区域 Footer 组件 ✨

对个人主页设计和实现感兴趣的朋友可以订阅我的专栏哦&#xff01;&#xff01;谢谢大家&#xff01;&#xff01;&#xff01; 为个人主页画上完美句号&#xff1a;设计一个美观实用的页脚组件 在完成 Hero、About、Projects、Contact 等模块后&#xff0c;我们为整个页面添上…...

基于Flask、Bootstrap及深度学习的水库智能监测分析平台

基于Flask、Bootstrap及深度学习的水库智能监测分析平台 项目介绍 本项目是基于Flask框架构建的水库智能监测分析平台&#xff0c;集水库数据管理、实时监测预警、可视化分析和智能预测功能于一体。 预测水位的预警级别&#xff1a;蓝色预警没有超过正常水位且接近正常水位1米…...

JavaSE核心知识点02面向对象编程02-08(异常处理)

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 JavaSE核心知识点02面向对象编程02-08&#…...

7系列 之 SelectIO 资源

背景 《ug471_7Series_SelectIO.pdf》介绍了Xilinx 7 系列 SelectIO 的输入/输出特性及逻辑资源的相关内容。 第 1 章《SelectIO Resources》介绍了输出驱动器和输入接收器的电气特性&#xff0c;并通过大量实例解析了各类标准接口的实现。 第 2 章《SelectIO Logic Resource…...

【目标检测系列】YOLOV1解读

目标检测系列文章 目录 目标检测系列文章&#x1f4c4; 论文标题&#x1f9e0; 论文逻辑梳理1. 引言部分梳理 (动机与思想) &#x1f4dd; 三句话总结&#x1f50d; 方法逻辑梳理&#x1f680; 关键创新点&#x1f517; 方法流程图关键疑问解答Q1: 关于 YOLOv1 中的 "conf…...

GIF图像技术介绍

以下是对GIF格式的详细介绍,涵盖其定义、发展历程、技术特性、应用场景及与其他格式的对比: 一、GIF的定义与起源 GIF(Graphics Interchange Format,图形交换格式)由美国CompuServe公司于1987年推出,旨在解决早期互联网带宽不足的问题。其开发者Steve Wilhite采用LZW无损…...

【TI MSPM0】CCS工程管理

一、关于WORKSPACE 1.导入工程路径 导入工程时&#xff0c;实际是将工程从原路径复制到了Workspace路径下&#xff08;默认是在C盘user路径下&#xff09; 2.工程保存备份 关于工程的保存&#xff0c;可以右击文件夹&#xff0c;点击Reveal打开文件夹 将对应的文件夹进行复…...

牛客周赛 Round 92-题解

牛客周赛 Round 92-题解 A-小红的签到题 code #include<iostream> #include<string> using namespace std; string s; int main() {int n;cin >> n;cout << "a_";for (int i 0; i < n - 2; i )cout << b;return 0; }B-小红的模…...

iVX 图形化编程平台:结合 AI 原生开发的革新与实践

一、技术架构&#xff1a;重构 AI 与编程的交互逻辑 1. 信息密度革命&#xff1a;从线性代码到图形化语义单元 传统文本编程存在显著的信息密度瓶颈。以 "按钮点击→条件判断→调用接口→弹窗反馈" 流程为例&#xff0c;Python 实现需定义函数、处理缩进并编写 30 …...

微服务架构中如何保证服务间通讯的安全

在微服务架构中,保证服务间通信的安全至关重要。服务间的通信通常是通过HTTP、gRPC、消息队列等方式实现的,而这些通信链路可能面临多种安全风险。为了应对这些风险,可以采取多种措施来保证通信安全。 常见的服务间通信风险 1.数据泄露:在服务间通信过程中,敏感数据可能会…...

长短期记忆网络(LSTM)深度解析:从理论到实践的全方位指南

一、LSTM基础理论:超越传统RNN的记忆架构 1.1 RNN的长期依赖问题 传统循环神经网络(RNN)在处理长序列时面临的根本挑战是梯度消失/爆炸问题。当序列长度超过10-20个时间步时,RNN难以学习到早期时间步的信息。数学上,这源于反向传播过程中梯度的链式法则: 复制 下载 ∂…...

FramePack AI图片生成视频 v1.1 整合包

今天&#xff0c;我兴奋地要为大家介绍一款革命性的AI工具——FramePack&#xff0c;这是一个让人眼前一亮的图生视频整合包。想象一下&#xff0c;在2025年5月11日的今天&#xff0c;哪怕你的电脑显存仅有6G&#xff0c;你也可以轻松创造艺术&#xff01; FramePack的神奇之处…...

在 C++中,指针数组与数组指针的区别

1. 指针数组:本质上是一个数组,数组中的每个元素都是一个指针。也就是说,这个数组存储的是多个指针变量,这些指针可以指向不同的对象(比如不同的变量、数组等) 。 2. 数组指针:本质上是一个指针,这个指针指向一个数组。即它指向的是数组的首地址,通过这个指针可以操作…...

Ubuntu 24服务器部署abp vnext应用程序的完整教程

一、服务器配置 1、安装Nginx 2、安装.NetCore SDK 或.NetCore 运行时 以上两步参考 《UbuntuNginxSupervisord部署.net core web应用程序_nginx部署netcore-CSDN博客》 二、abp vnext程序部署 1、程序发布 使用VS进行发布 2、程序上传 使用winSCP工具 3、openiddict…...

Ingrees 控制器与 Ingress 资源的区别

在 Kubernetes 中&#xff0c;单纯的 Ingress 资源定义文件&#xff08;YAML&#xff09;本身不会直接创建 Pod。Ingress 的作用是定义路由规则&#xff08;如将外部流量路由到集群内的服务&#xff09;&#xff0c;而实际处理流量的 Pod 是由 Ingress 控制器&#xff08;如 Ng…...

动态路由实现原理及前端控制与后端控制的核心差异

在 Web 开发领域&#xff0c;动态路由是构建灵活、高效应用的关键技术之一。它能够根据不同的条件和请求&#xff0c;动态地决定页面的跳转和数据的加载&#xff0c;极大提升用户体验。本文将深入剖析动态路由的实现原理&#xff0c;并详细探讨前端控制和后端控制两种模式的最大…...

stm32 WDG看门狗

目录 stm32 WDG看门狗一、WDG基础知识1&#xff09;WDG&#xff08;Watchdog&#xff09;看门狗简介 二、IWDG独立看门狗1&#xff09;IWDG键寄存器2&#xff09;IWDG超时时间 三、WWDG窗口看门狗1&#xff09;WWDG框图2&#xff09;WWDG工作特性3&#xff09;WWDG超时时间4&am…...

MySQL索引详解(下)(SQL性能分析,索引使用)

索引是MySQL性能优化的核心&#xff0c;但如何精准分析查询瓶颈、合理设计索引&#xff0c;是开发者必须掌握的技能。本文结合实战案例&#xff0c;系统讲解SQL性能分析工具链与索引使用技巧&#xff0c;帮助读者构建高性能数据库系统。 一、SQL性能分析&#xff1a;从宏观到微…...

添加文字标签

上节我们学会了如何在地图中标记位置,那么可不可以为地图添加文字注释呢?答案是肯定的,我们依旧以广州塔为例. //添加文字标签和广告牌var label viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(113.3191,23.109,100),label:{text:"广州塔",font:&…...

数据并行基础概念知识

架构分为PS与ring-allreduce&#xff1b;方法主要是zero系列zeroDP123、ZeroR 、Zero-offerload、Zero-Infinite、Zero 相关博客介绍的很清楚&#xff0c;在这里总结一下 图解系列很通透&#xff0c;通俗易懂1 更详细的介绍后面几种方式&#xff0c;提供动图链接2 提供混合精度…...

Linux系列(3)----用户和用户组管理、系统管理

声明&#xff1a; 本文参考 ❤️肝下25万字的《决战Linux到精通》笔记&#xff0c;你的Linux水平将从入门到入魔❤️【建议收藏】_linux笔记 小小明-CSDN博客 不理解的命令需要自己操作一遍 方可理解 不知道怎么租用服务器并链接的看这个文章 如何租用服务器并通过ssh连接…...

【沉浸式求职学习day36】【初识Maven】

沉浸式求职学习 Maven1. Maven项目架构管理工具2.下载安装Maven3.利用Tomcat和Maven进入一个网站 Maven 为什么要学习这个技术&#xff1f; 在Java Web开发中&#xff0c;需要使用大量的jar包&#xff0c;我们手动去导入&#xff0c;这种操作很麻烦&#xff0c;PASS&#xff01…...

Nipype 简单使用教程

Nipype 简单使用教程 基础教程**一、Nipype 核心概念与工作流构建****1. 基本组件****2. 工作流构建步骤** **二、常用接口命令速查表****1. FSL 接口****2. FreeSurfer 接口****3. ANTS 接口****4. 数据处理接口** **三、高级特性与最佳实践****1. 条件执行&#xff08;基于输…...

DA14585墨水屏学习(2)

一、user_svc2_wr_ind_handler函数 void user_svc2_wr_ind_handler(ke_msg_id_t const msgid,struct custs1_val_write_ind const *param,ke_task_id_t const dest_id,ke_task_id_t const src_id) {// sprintf(buf2,"HEX %d :",param->length);arch_printf("…...

【LeetCode Hot100 | 每日刷题】排序数组

912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给你一个整数数组 nums&#xff0c;请你将该数组升序排列。 你必须在 不使用任何内置函数 的情况下解决问题&#xff0c;时间复杂度为 O(nlog(n))&#xff0c;并且空间复杂度尽可能小。 示例 1&…...

leetcode热题100——day26

21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 AC代码 # Definition for singly-linked list. # class ListNode(object): # def __init__(self, val0, nextNone): # self.val val # …...

Python httpx库终极指南

一、发展历程与技术定位 1.1 历史演进 起源&#xff1a;httpx 由 Encode 团队开发&#xff0c;于 2019 年首次发布&#xff0c;目标是提供一个现代化的 HTTP 客户端&#xff0c;支持同步和异步操作&#xff0c;并兼容 HTTP/1.1 和 HTTP/2。背景&#xff1a; requests 库虽然功…...