学习 Python 之 Pygame 开发魂斗罗(十六)

news2025/1/20 5:49:53

学习 Python 之 Pygame 开发魂斗罗(十六)

    • 完成最终的魂斗罗
      • 1. 创建Sound类
      • 2. 添加背景音乐
      • 3. 添加玩家发射子弹音效
      • 4. 增加击中boss要害音效
      • 5. 击中敌人音效
      • 6. 加入进场动画
      • 7. 解决玩家掉出地图死亡问题
      • 8. 完善玩家游戏失败函数
      • 9. 总结

完成最终的魂斗罗

在上次的博客学习 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. 总结

至此,魂斗罗整体就算完成了,由于博主没有通过的地图和爆炸的音效,这里没办法加入

大家接下来可以扩展,博主没有完善游戏结束和游戏胜利的界面,如果后面我找到了对应的素材,我会加入到游戏里,并且会发一个博客

坦克大战开发了一个星期完成了,比起坦克大战,魂斗罗写了大概一个半月了,其实可以很早可以完成,博主之前在准备考研复试,比较忙,这段时间算是没什么事情了,想着不能半途而废,把魂斗罗完成一下。

最后感谢各位小伙伴的学习和支持。

整体代码和素材我都会放到网盘,需要的小伙伴可以自己去拿哦。

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

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

相关文章

道达天际首次亮相军博会,“天网融合”引爆全场

4月23日,第十届中国指挥控制大会暨第八届中国(北京)军事智能技术装备博览会(军博会)落下帷幕。北京道达天际科技股份有限公司(简称道达天际)携DAODAJ2天网情报产品体系首次亮相,全面展示天网融合技术、产品、行业解决方案等成果,最新技术应用备受现场观众瞩目,“天网融合”创新…

性能优化对于Android程序员的重要性,看完你就明白

前言 相信我们都使用过Android手机&#xff0c;然后在使用的过程中经常会遇到手机卡顿&#xff0c;应用闪退&#xff0c;画面不流畅等问题&#xff1b;正因为如此&#xff0c;就导致用户体验非常差&#xff0c;最后选择不再使用Android手机。对此&#xff0c;很多公司对Androi…

【软考备战·希赛网每日一练】2023年4月27日

文章目录 一、今日成绩二、错题总结第一题第二题第三题第四题 三、知识查缺 题目及解析来源&#xff1a;2023年04月27日软件设计师每日一练 一、今日成绩 二、错题总结 第一题 解析&#xff1a; ADSL Modem 上网拨号方式有3种&#xff0c;即 专线方式&#xff08;静态IP&#…

半导体运动台基于dsp+fpga+ad+endac的高速数据采集FPGA设计(二)

4 系统 FPGA 程序的设计 4.1 设计方法及逻辑设计概述 4.1.1 开发环境与设计流程 Quartus II 是 Altera 公司综合开发工具&#xff0c;它集成了 FPGA/CPLD 开发过程中所设计 的所有工具和第三方软件接口&#xff0c;支持多时钟分析&#xff0c; LogicLock 基于块的…

Linux内核阅读自学精简教程目录(必读)

学习Linux内核需要一定的计算机基础知识&#xff0c;包括操作系统&#xff0c;计算机网络等。 以下是学习Linux内核的步骤&#xff1a; 了解Linux内核的基本概念和架构&#xff0c;学习Linux内核源代码的组成和结构。学习C语言和汇编语言&#xff0c;这是深入理解Linux内核的…

ssh设置别名 ,登录

1. ssh设置别名&#xff1b; 可以使用alias命令来给ssh命令起别名&#xff0c;例如&#xff1a; alias mysshssh这样就可以使用myssh命令来代替ssh命令了。如果想要永久生效&#xff0c;可以将上述命令加入到~/.bashrc文件中。 &#xff0c;如果没有 ~/.bashrc 此文件&#…

第十八章 迭代器模式

文章目录 前言一、迭代器模式基本介绍二、迭代器模式应用实例完整代码Department 系ComputerCollegeIterator 计算机学院迭代器InfoColleageIterator 信息工程学院迭代器College 学院接口ComputerCollege 计算机学院InfoCollege 信息工程学院OutPutImpl 操作迭代器Clint 测试 三…

一个恶意下载器的逆向分析

Die查壳, 发现没有加壳, 是使用VC编写的64位程序 丢入VT用杀毒引擎和沙箱扫, 爆红基本可以确定其属于恶意软件: 查看其PE节区发现其包含了资源节, 内部可能藏有隐藏模块 查看一下这个程序导入的dll中发现了如下特别的地方 并且其还使用了LoadLibrary和GetProcAddre…

使用aardio写一个基于pyocd的单片机下载器

1 新建工程 最开始本来是打算调用pyocd 的python api的&#xff0c;但是一个是内嵌包一直安装出问题&#xff0c;一个是考虑到本地pack不想重复安装和管理&#xff0c;于是就转做pyocd的前端了&#xff0c;也就是直接调用pyocd&#xff0c;根据返回数据解析&#xff0c;然后执…

NumPy之矩阵、向量、线性代数等的操作

NumPy之矩阵、向量、线性代数 NumPy矩阵和向量矩阵向量创建向量创建矩阵访问元素转置矩阵矩阵加减乘除矩阵向量乘法矩阵求逆矩阵的迹向量点积向量范数 NumPy线性代数计算矩阵乘积计算矩阵的逆解线性方程组 NumPy矩阵和向量 矩阵 在NumPy中&#xff0c;矩阵可以看作是一个二维数…

【Django】Django ORM Cookbook--20230427

英文版http://books.agiliq.com/projects/django-orm-cookbook/en/latest/ 中文版https://django-orm-cookbook-zh-cn.readthedocs.io/zh_CN/latest/query.html 查询和筛选 1. 如何查看Django ORM查询集的原生SQL&#xff1f; >>> queryset Event.objects.all() &…

JVM内存模型和结构

JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;JVM是一个虚构出来的计算机&#xff0c;有着自己完善的硬件架构&#xff0c;如处理器、堆栈等。 为什么需要JVM&#xff1f; Java语言使用Java虚拟机屏蔽了与具体平台相关的信息&#xff0c;使…

QT笔记——第三方开源库停靠窗口类似QDockWidget

我们想要一个类似于Visual Studio 2019的dockwidget 停靠窗口 一个开源库&#xff1a;类似于Visual Studio 2019 dockwidget 的开源库 下载&#xff0c;解压下来 使用vs qt 插件打开src文件夹下的 src.pro 生成如下&#xff1a; 我们来运行它的例子&#xff1a; 使用vs qt …

【Vue工程】001-Vite 创建 Vue-TypeScript 项目

【Vue工程】001-Vite 创建 Vue-TypeScript 项目 文章目录 【Vue工程】001-Vite 创建 Vue-TypeScript 项目一、环境二、创建项目1、pnpm 创建 Vite 项目2、设置项目名3、选择vue4、选择 TypeScript5、创建完成6、安装与启动7、访问 http://localhost:5173/8、默认生成的项目结构…

LeetCode0718.最长重复子数组 Go语言AC笔记

时间复杂度&#xff1a;O(n)&#xff0c;空间复杂度&#xff1a;O(n) 解题思路 动态规划思想。令dp[i][j]表示两数组以nums1[i]和nums2[j]为起始元素的公共前缀最大长度&#xff0c;所以如果nums1[i]和nums2[j]元素相同&#xff0c;那么dp[i][j]dp[i1][j1]&#xff0c;否则dp[…

Baumer工业相机堡盟工业相机如何联合BGAPI SDK和OpenCVSharp合并偏振相机4个角度的图像并显示(C#)

Baumer工业相机堡盟工业相机如何联合BGAPI SDK和OpenCVSharp合并偏振相机4个角度的图像并显示&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机偏振相机的技术背景代码案例分享1&#xff1a;引用合适的类文件2&#xff1a;回调函数里联合BGAPI SDK和OpenCVSharp合并偏…

Leetcode刷题日志2.0

目录 前言&#xff1a; 1.数字的补数 2.最大连续 1 的个数 3.下一个更大元素 I 4.斐波那契数 5.提莫攻击 6.557. 反转字符串中的单词 III 前言&#xff1a; 今天就分享一下最近刷到的leetcode习题吧 &#xff0c;编程语言&#xff1a;Python3。废话不多说&#xff0…

【备战蓝桥杯国赛-国赛真题】2022

思路 题目的一是就是从1~2022这2022个数中挑选十个数&#xff0c;使其的总和为2022&#xff0c;如果做过背包问题&#xff0c;那么思路就很好出来了&#xff0c;每个数无非就是选与不选&#xff0c;每个数有他们的权值&#xff0c;权值就等于它们本身的值&#xff0c;抽象成背…

java调用百度的接口获取起始位置的距离

需求:校验收货地址是否超出配送范围 重要: 做该需求的思路就是通过卖家和卖家具体的地址信息,来获取到二者的经纬度, 此时可以使用百度的 "地理编码服务",即可获取对应的经纬度 第二步,就是通过二者的经纬度,按照百度接口的要求,发送,即可获取到包含二者距离的JSON串…

循环语句for

for循环 循环和遍历的概念 循环&#xff08;Loop&#xff09;和遍历&#xff08;Traversal&#xff09;是两个在计算机编程中经常使用的概念。 循环是一种重复执行一段代码的结构。通过循环&#xff0c;可以在满足一定条件的情况下&#xff0c;多次执行相同的代码。循环语句…