您现在的位置是:首页 >技术交流 >学习 Python 之 Pygame 开发魂斗罗(十六)网站首页技术交流
学习 Python 之 Pygame 开发魂斗罗(十六)
学习 Python 之 Pygame 开发魂斗罗(十六)
完成最终的魂斗罗
在上次的博客学习 Python 之 Pygame 开发魂斗罗(十五)中,我们加入了boss,至此,魂斗罗的主体部分已经完成了,接下来就是在其他地方加入一点敌人,设置进场动画,胜利动画,失败动画和音效了,在这篇博客中,我们加入音效和加入进场动画。
下面是图片的素材和源码,我把源码也放到了网盘
链接:https://pan.baidu.com/s/1X7tESkes_O6nbPxfpHD6hQ?pwd=hdly
提取码:hdly
1. 创建Sound类
import pygame
class Sound:
def __init__(self, filename):
self.filename = filename
pygame.mixer.init()
self.sound = pygame.mixer.Sound(self.filename)
def play(self, loops = 0):
self.sound.play(loops)
def stop(self):
self.sound.stop()
def setVolume(self):
self.sound.set_volume(0.2)
return self
把该类导入到需要播放音效的类
2. 添加背景音乐
在主类的构造函数中加入如下代码,并且在run()函数中播放背景音乐
# 加载音乐
self.backgroundMusic = Sound('../Sound/1.mp3')
注意不要加入到循环中了
3. 添加玩家发射子弹音效
来到玩家1类,找到fire()函数,修改代码
def fire(self, currentTime, playerBulletList):
self.isFiring = True
# 潜水状态下不能开火
if not (self.isInWater and self.isSquating):
if len(playerBulletList) < PLAYER_BULLET_NUMBER:
if currentTime - self.fireLastTimer > 150:
Sound('../Sound/commonFire.mp3').play()
playerBulletList.append(Bullet(self))
self.fireLastTimer = currentTime
4. 增加击中boss要害音效
来到子弹类,修改collideEnemy()函数
5. 击中敌人音效
还是在子弹类的collideEnemy()函数中加入代码
def collideEnemy(self, enemyList, explodeList):
for enemy in enemyList:
if pygame.sprite.collide_rect(self, enemy):
if enemy.type == 3 or enemy.type == 4:
enemy.life -= 1
Sound('../Sound/hitWeakness.mp3').play()
if enemy.life <= 0:
self.isDestroy = True
enemy.isDestroy = True
explodeList.append(Explode(enemy, ExplodeVariety.BRIDGE))
else:
Sound('../Sound/enemyDie.mp3').play()
self.isDestroy = True
enemy.isDestroy = True
explodeList.append(Explode(enemy))
由于博主没有其他的音效,只能添加这部分了,如果大家自己找到了音效,可以加入,让游戏变得更完整
6. 加入进场动画
在主类中加入加载进场动画函数
def loadApproachAnimation(self):
# 读取进场图片
approach = pygame.image.load('../Image/Map/1/Background/First(Approach).png')
approachRect = self.background.get_rect()
approach = pygame.transform.scale(
approach,
(int(approachRect.width * 1),
int(approachRect.height * 1))
)
approachRect.x = 0
# 设置进场图片移动速度
cameraAdaption = 3
# 记录当前时间
currentTime = 0
# 创建一张黑色的图片,用来盖住选择图标
image = pygame.Surface((50, 50)).convert()
image.fill((0, 0, 0))
# 记录是否播放音效,播放了就要画了
isPlayed = False
showTime = pygame.time.get_ticks()
lastingTime = pygame.time.get_ticks()
keys = ''
while 1:
MainGame.window.blit(approach, approachRect)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
# 上上下下左右左右BABA A是跳跃键,B是射击键
if event.key == pygame.K_w:
keys += 'w'
elif event.key == pygame.K_s:
keys += 's'
elif event.key == pygame.K_j:
keys += 'b'
elif event.key == pygame.K_k:
keys += 'a'
elif event.key == pygame.K_RETURN:
if not isPlayed:
approachRect.x = -1435
Sound('../Sound/start.mp3').play()
currentTime = time.time()
isPlayed = True
# 让背景向右走这么多距离
if approachRect.x > -1435:
approachRect.x -= cameraAdaption
if isPlayed:
# 设置图标一闪一闪的
if abs(lastingTime - pygame.time.get_ticks()) > 400:
if 1200 > abs(showTime - pygame.time.get_ticks()) > 0:
MainGame.window.blit(image, (190, 390))
else:
showTime = pygame.time.get_ticks()
lastingTime = pygame.time.get_ticks()
# 更新窗口
pygame.display.update()
# 设置帧率
self.clock.tick(self.fps)
fps = self.clock.get_fps()
caption = '魂斗罗 - {:.2f}'.format(fps)
pygame.display.set_caption(caption)
# 如果时间超过60,就开始加载第一关
if 100 > abs(time.time() - currentTime) * 10 > 60:
print(keys)
if keys == 'wwssbaba':
initPlayer1(30)
break
这里需要解释几处
# 当按键按下,直接结束进场动画,播放音乐,让图标还是闪烁,一定时间后进入第一关
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
# 上上下下左右左右BABA A是跳跃键,B是射击键
if event.key == pygame.K_w:
keys += 'w'
elif event.key == pygame.K_s:
keys += 's'
elif event.key == pygame.K_j:
keys += 'b'
elif event.key == pygame.K_k:
keys += 'a'
elif event.key == pygame.K_RETURN:
if not isPlayed:
approachRect.x = -1435
Sound('../Sound/start.mp3').play()
currentTime = time.time()
isPlayed = True
这部分是让玩家按下回车后直接播放音乐,并且直接来到玩家选择界面(如下图),如果按下了上上下下左右左右BABA时,玩家就会30条名
if isPlayed:
# 设置图标一闪一闪的
if abs(lastingTime - pygame.time.get_ticks()) > 400:
if 1200 > abs(showTime - pygame.time.get_ticks()) > 0:
MainGame.window.blit(image, (190, 390))
else:
showTime = pygame.time.get_ticks()
lastingTime = pygame.time.get_ticks()
这部分是让图标闪烁的,整体思想就是创建一块黑布(纯黑图片),一段时间把原来的图标盖住,一段时间不盖住,上面的代码就是实现这个功能,abs(lastingTime - pygame.time.get_ticks()) > 400 这个代码是不盖住的,lastingTime 是不盖住的时间,如果超过了400,就进入if语句体,让黑布显示出来,盖住图标,盖住的时间是1200 ,如果大于1200 了,就不盖住了。
注意导入模块,否则会出现如下报错
主类新增runGame()函数
def runGame(self):
self.loadApproachAnimation()
self.run()
该函数是游戏的运行函数
修改main()函数
我们运行一下游戏,看看效果
可以看到界面慢慢移动,如果按下任意键,就会播放声音,播放完后过几秒会进入第一关
7. 解决玩家掉出地图死亡问题
在当前的游戏中,玩家掉落到山崖后,没有死亡,我们需要修改一下
来到主类的updatePlayerPosition()函数
增加如下代码
if tempPlayer.rect.y > 610:
if MainGame.player1.damage(1):
initPlayer1(MainGame.player1.life)
这段代码就是如果玩家的y坐标大于610,就算玩家死亡,重新加载玩家
8. 完善玩家游戏失败函数
把主类的isEnd属性变成类属性
增加endGame()函数
def endGame():
MainGame.isEnd = True
这里需要修改一下逻辑,来到updateEnemyPosition()函数
把原来的endGame函数改为victory,表示玩家胜利了
我们先暂时定义一下这个函数
def victory():
pass
之后继续修改endGame()函数逻辑
现在运行游戏,看看玩家没有生命了游戏会不会退出
发现是可以的
9. 总结
至此,魂斗罗整体就算完成了,由于博主没有通过的地图和爆炸的音效,这里没办法加入
大家接下来可以扩展,博主没有完善游戏结束和游戏胜利的界面,如果后面我找到了对应的素材,我会加入到游戏里,并且会发一个博客
坦克大战开发了一个星期完成了,比起坦克大战,魂斗罗写了大概一个半月了,其实可以很早可以完成,博主之前在准备考研复试,比较忙,这段时间算是没什么事情了,想着不能半途而废,把魂斗罗完成一下。
最后感谢各位小伙伴的学习和支持。
整体代码和素材我都会放到网盘,需要的小伙伴可以自己去拿哦。