pygame飞机大战

news2025/1/6 22:32:43

飞机大战

  • 1.main类
  • 2.配置类
  • 3.游戏主类
  • 4.游戏资源类
  • 5.资源下载
  • 6.游戏效果

1.main类

启动游戏。

from MainWindow import MainWindow
if __name__ == '__main__':
    app=MainWindow()
    app.run()

2.配置类

该类主要存放游戏的各种设置参数。

#窗口尺寸
import random
import pygame
WINDOW=pygame.Rect(0,0,512,768)#图片资源大小刚好是512*768
#窗口名字
WINDOW_NAME="飞机大战v1.0"

#地图索引
MAP_INDEX=random.randint(1,5)

#英雄子弹类型
HERO_BULLET_INDEX=1
#敌人子弹类型
ENEMY_BULLET_INDEX=3

#敌机事件
ENEMY_EVENT=pygame.USEREVENT#pygame用户事件(整型),有多个事件可以在后面+1以区分

#英雄子弹事件
BULLET_EVENT=pygame.USEREVENT+1#+1区分事件
#敌机子弹事件
BULLET_ENEMY_EVENT=pygame.USEREVENT+2#+2区分事件

#英雄移动速度
HERO_MOVE_SPEED=4
#英雄子弹移动速度
HERO_BULLET_MOVE_SPEED=4

3.游戏主类

游戏主类主要由游戏窗口创建、精灵和精灵组的创建、游戏启动函数(1.碰撞检测、2.事件处理、3.精灵组更新、4.窗口刷新)等构成。

import pygame
from Config import *
from GameSprite import *
class MainWindow:
    def __init__(self):
        pygame.init()
        #游戏窗口初始化
        self.window=pygame.display.set_mode([WINDOW.width,WINDOW.height])
        pygame.display.set_caption(WINDOW_NAME)
        #背景音乐
        pygame.mixer.music.load("./source/music/bg.wav")
        pygame.mixer.music.set_volume(0.1)
        pygame.mixer.music.play(-1)
        #爆炸音效
        self.bomb=pygame.mixer.Sound("./source/music/bomb.wav")
        self.bomb.set_volume(0.2)
        #游戏分数
        self.kill_enemys=0
        self.hp=100

        #FPS时钟
        self.clock=pygame.time.Clock()
        #激活敌机定时器,参数:事件、间隔时间ms
        pygame.time.set_timer(ENEMY_EVENT,500)
        # 激活英雄子弹定时器,参数:事件、间隔时间ms
        pygame.time.set_timer(BULLET_EVENT,500)
        pygame.time.set_timer(BULLET_ENEMY_EVENT,2000)
        #创建精灵组
        self.create_sprite_group()

    #精灵组创建
    def create_sprite_group(self):
        #地图精灵组
        map1=GameMap()
        map2=GameMap(True)
        self.map_group=pygame.sprite.Group(map1,map2)
        #英雄精灵
        self.hero=Hero()
        self.hero_group=pygame.sprite.Group(self.hero)
        #敌机精灵组
        self.enemy_group=pygame.sprite.Group()
        #英雄子弹精灵组
        self.bullet_group=pygame.sprite.Group()
        #敌机子弹精灵组
        self.bullet_enemy_group=pygame.sprite.Group()
        #爆炸动画精灵组
        self.bomb_group=pygame.sprite.Group()

    # 碰撞检测
    def collie_check(self):
        #1.英雄子弹与敌机
        for bullet1 in self.bullet_group:
            #第一个参数是精灵、第二个参数是精灵组、第三个参数为是否删除与该精灵碰撞的所有精灵;返回值为与第一个参数碰撞的所有精灵列表
            eys=pygame.sprite.spritecollide(bullet1,self.enemy_group,True)#判断子弹精灵是否与敌机精灵组有碰撞,有则杀死所有敌机
            #表示有碰撞
            if len(eys)>0:
                self.bomb.play()#发生碰撞,播放爆炸音效
                self.kill_enemys+=1#记录杀死的敌机数量
                bullet1.kill()#杀死发生碰撞的子弹精灵
                bomb_enemy=Bomb(eys[0])#将发生碰撞的敌传入爆炸类,方便使用爆炸的具体位置
                self.bomb_group.add(bomb_enemy)#加入爆炸精灵组

        #2.敌机子弹与英雄
        bullet2=pygame.sprite.spritecollide(self.hero,self.bullet_enemy_group,True)
        if len(bullet2)>0:
            self.bomb.play()#发生碰撞,播放爆炸音效
            self.hp-=1#英雄与敌机子弹接触,自身HP值-1

        #敌机与英雄
        enemys=pygame.sprite.spritecollide(self.hero,self.enemy_group,True)
        if len(enemys)>0:
            self.bomb.play()#发生碰撞,播放爆炸音效
            self.hp-=2#英雄与敌机接触,自身HP值-2
            bomb_enemy2 = Bomb(enemys[0])#将发生碰撞的敌传入爆炸类,方便使用爆炸的具体位置
            self.bomb_group.add(bomb_enemy2)#加入爆炸精灵组
            pass
    # 更新精灵组位置并绘制
    def sprite_group_update_draw(self):
        #地图精灵组更新
        self.map_group.update()
        self.map_group.draw(self.window)
        #英雄精灵组更新
        self.hero_group.update()
        self.hero_group.draw(self.window)
        #敌机精灵组更新
        self.enemy_group.update()
        self.enemy_group.draw(self.window)
        #英雄子弹精灵组
        self.bullet_group.update()
        self.bullet_group.draw(self.window)
        #敌机子弹精灵组
        self.bullet_enemy_group.update()
        self.bullet_enemy_group.draw(self.window)
        #爆炸精灵组
        self.bomb_group.update()
        self.bomb_group.draw(self.window)
        #绘制数据 #游戏数据
        font=pygame.font.Font("./source/fonts/SimHei.ttf")#pygame不能直接绘制中文,先导入字体文件
        text=f"得分:{self.kill_enemys}  HP:{self.hp} "#编辑需要绘制的字符串
        self.text=font.render(text,True,(255,255,255))#渲染的文字,抗锯齿,颜色
        self.window.blit(self.text,[WINDOW.width/2,20])#blit()函数绘制,将text当做图片处理
        #英雄生命值为0退出游戏
        if self.hp==0:
            pygame.quit()

    # 事件处理
    def handle_events(self):
        #pygame.event.get()获取当前时间帧的所有事件,返回一个事件列表,可以对此列表遍历
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                pygame.quit()
            #用户事件1,固定时间生成敌机(时间可以在窗口初始化代码中修改)
            if event.type==pygame.USEREVENT:
                self.enemy=Enemy()
                self.enemy_group.add(self.enemy)
            #用户事件2,固定时间生成敌机子弹(时间可以在窗口初始化代码中修改)
            if event.type==pygame.USEREVENT+2:
                #固定时间生成敌机子弹,需要遍历敌机精灵组,获取所有已经存在的敌机精灵,在对应的位置上绘制敌机子弹
                for enemy_sprite in self.enemy_group:
                    self.bullet_enemy = Bullet(enemy_sprite.speed + 1,True)
                    self.bullet_enemy.rect.centerx = enemy_sprite.rect.centerx
                    self.bullet_enemy.rect.y =enemy_sprite.rect.bottom
                    #将敌机子弹精灵添加到敌机子弹精灵组
                    self.bullet_enemy_group.add(self.bullet_enemy)
            #用户事件3,固定时间生成英雄子弹(时间可以在窗口初始化代码中修改)
            if event.type==pygame.USEREVENT+1:
                self.bullet_hero=Bullet(-HERO_BULLET_MOVE_SPEED)#英雄子弹飞行方向与敌机子弹飞行方向相反
                #根据英雄的当前位置来设置英雄子弹的位置
                self.bullet_hero.rect.centerx=self.hero.rect.centerx
                self.bullet_hero.rect.y=self.hero.rect.y-self.bullet_hero.rect.height
                # 将英雄飞机子弹精灵添加到英雄子弹精灵组
                self.bullet_group.add(self.bullet_hero)


        #pygame.key.get_pressed()获取当前时间帧的所有键盘事件并返回一个列表,遍历列表控制英雄上下左右移动
        keys_event=pygame.key.get_pressed()
        if keys_event[pygame.K_a] or keys_event[pygame.K_LEFT]:
            self.hero.x_speed=-HERO_MOVE_SPEED
        elif keys_event[pygame.K_d] or keys_event[pygame.K_RIGHT]:
            self.hero.x_speed=HERO_MOVE_SPEED
        else:
            self.hero.x_speed = 0
        if keys_event[pygame.K_w] or keys_event[pygame.K_UP]:
            self.hero.y_speed=-HERO_MOVE_SPEED
        elif keys_event[pygame.K_s] or keys_event[pygame.K_DOWN]:
            self.hero.y_speed=HERO_MOVE_SPEED
        else:
            self.hero.y_speed=0

    #游戏主框架
    def run(self):

        while True:
            #碰撞检测
            self.collie_check()
            #事件处理
            self.handle_events()
            #更新精灵组
            self.sprite_group_update_draw()
            #窗口刷新
            pygame.display.update()
            self.clock.tick(60)#FPS

4.游戏资源类

游戏资源类主要包括各种游戏相关元素精灵、主要有基础精灵类、敌机精灵类、子弹精灵类、英雄飞机精灵类、爆炸动画精灵类等。

import  pygame
from Config import *
import random
#精灵类————基类,定义了基本的导入图片操作,以及图片垂直移动操作
class GameSprite(pygame.sprite.Sprite):
    def __init__(self,image_url,speed=0):
        super().__init__()
        self.image=pygame.image.load(image_url)
        self.rect=self.image.get_rect()
        self.speed=speed
    def update(self, *args, **kwargs):
        self.rect.y+=self.speed
#游戏地图类,地图由两张完全一样的图片拼接构成,其中两张图片的起始和末尾要无缝衔接
#第一张图片起始位置与窗口完全重合,第二张图片的起始位置在第一张图片的上方
class GameMap(GameSprite):
    #is_1表示是否是第二张图片
    def __init__(self,is_1=False):
        #地图给了5张,保证地图索引在1~5,否则随机给一个1~5
        self.map_index=MAP_INDEX if 1<=MAP_INDEX<=5 else random.randint(1,5)
        map_filename=f"./source/map/map-{self.map_index}.jpg"
        super().__init__(map_filename,2)
        if is_1:
            self.rect.y=-WINDOW.height#第二张图片的起始位置在第一张图片的上方
    def update(self):
        #更新图像的位置
        super().update()
        #如果地图图片完全运动到了窗口最下方,就将这张图片的位置移动到窗口的最上方,作为新的起始位置
        if self.rect.y>=WINDOW.height:
            self.rect.y=-WINDOW.height
#英雄飞机类,初始化定义比较简单
class Hero(GameSprite):
    def __init__(self):
        super().__init__("./source/plane/hero.png")
        #定义英雄飞机出生在窗口中的具体位置
        self.rect.centerx=WINDOW.centerx
        self.rect.y=WINDOW.height-120
        #初始移动速度为0,静止状态
        self.x_speed=0
        self.y_speed=0
    def update(self, *args, **kwargs):
        #水平方向移动
        self.rect.x+=self.x_speed
        #垂直方向移动
        self.rect.y+=self.y_speed
        #判断上、下、左、右四个边界条件,如果移动到了边界,让飞机停在原位
        if self.rect.x<=0:
            self.rect.x=0
        if self.rect.x>=WINDOW.width-self.rect.width:
            self.rect.x=WINDOW.width-self.rect.width
        if self.rect.y<=0:
            self.rect.y=0
        if self.rect.y>=WINDOW.height-self.rect.height:
            self.rect.y=WINDOW.height-self.rect.height
#敌机类
class Enemy(GameSprite):
    def __init__(self):
        #敌机有7中飞机,随机生成
        self.enemy_url=f"./source/plane/enemy-{random.randint(1,7)}.png"
        #敌机的垂直速度也是随机生成(1,3)
        super().__init__(self.enemy_url,random.randint(1,3))
        #敌机的初始水平位置需要随机生成,范围就是(0,WINDOW.width-self.rect.width)
        self.rect.x=random.randint(0,WINDOW.width-self.rect.width)
        #敌机的垂直位置y是固定值,保证敌机出现的位置在窗口之外
        self.rect.y=-self.rect.height
        #敌机水平方向的移动速度随机生成
        self.x_speed=random.randint(-1,1)
    def update(self, *args, **kwargs):
        #调用父类的update()函数
        super().update()
        #父类函数不够用的情况下,直接补充
        self.rect.x+=self.x_speed#水平移动
        #如果到达左右边界则反向运动
        if self.rect.x<=0 or self.rect.x>=WINDOW.width-self.rect.width:
            self.x_speed=-self.x_speed
        #敌机出了窗口底部则杀死此敌机精灵
        if self.rect.y>WINDOW.height:
            self.kill()
#子弹类(英雄飞机子弹和敌机子弹)
class Bullet(GameSprite):
    #is_enemy表示是否是敌机,敌机和英雄飞机使用的子弹图片不同
    def __init__(self,speed,is_enemy=False):
        if is_enemy:
            self.bullet_index=ENEMY_BULLET_INDEX
        else:
            self.bullet_index = HERO_BULLET_INDEX
        bullet_filename = f"./source/bullet/bullet_{self.bullet_index}.png"
        self.speed=speed
        super().__init__(bullet_filename,self.speed)
        #由于敌机和英雄飞机是相对运动,资源图片都是正向的,所以如果是敌机子弹,则需要对子弹图片做旋转180°操作
        if is_enemy:
            ##flip(翻转的图片、是否绕x轴翻转、是否绕y轴翻转)
            self.image=pygame.transform.flip(self.image,False,True)

    def update(self, *args, **kwargs):
        #垂直方向移动
        super().update()
        #超出屏幕则杀死此精灵
        if self.rect.y<-self.rect.height or self.rect.y>WINDOW.height+self.rect.height:
            self.kill()
#爆炸动画类
class Bomb(pygame.sprite.Sprite):
    def __init__(self,sprite1):
        super().__init__()
        #导入所有动画的图片
        self.images=[pygame.image.load(f"./source/bomb/bomb-{bomb_index}.png") for bomb_index in range(1,8)]
        self.sprite1=sprite1
        self.interval = 5 # 播放每一张图片的间隔 5帧
        self.interval_index = 0 #帧数计数器 初始值为0
        self.image_index=0#图片索引 初始值为0
        self.image = self.images[self.image_index]
        self.rect = self.image.get_rect()
        self.rect.x = self.sprite1.rect.x
        self.rect.y = self.sprite1.rect.y

    def update(self, *args, **kwargs):
        self.interval_index+=1#每一帧进入update()函数,帧计数器加1
        #当计数器到达设置值时,切换图片
        if self.interval_index>=self.interval:
            self.image=self.images[self.image_index]
           #帧计数器归零
            self.interval_index=0
            #切换图片
            self.image_index+=1
        #当所有图片都播放完毕之后杀死此精灵对象
        if self.image_index==len(self.images):
            self.kill()

5.资源下载

链接:资源
提取码:jixb

6.游戏效果

在这里插入图片描述

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

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

相关文章

应用架构模式

设计模式 设计模式是指根据通用需求来设计解决方案的模板或蓝图&#xff0c;使用设计模式能够更加有效地解决设计过程中的常见问题。设计模式针对不同的问题域有不同的内涵&#xff0c;主要涉及业务、架构、程序设计等问题域&#xff0c;本文主要讨论架构设计模式。 业务设计模…

el-input输入框需要支持多输入,最后传输给后台的字段值以逗号分割

需求&#xff1a;一个输入框字段需要支持多次输入&#xff0c;最后传输给后台的字段值以逗号分割 解决方案&#xff1a;结合了el-tag组件的动态编辑标签 那块的代码 //子组件 <template><div class"input-multiple-box" idinputMultipleBox><div>…

【新教程】华为昇腾NPU的pytorch环境搭建

1 硬件配置 使用学校的集群&#xff0c;相关配置如下&#xff1a; CPU&#xff1a;鲲鹏920 NPU&#xff1a;昇腾910B 操作系统&#xff1a;openEuler 22.03 2 安装版本 根据昇腾官方gitee上的信息&#xff0c;Pytoch 2.1.0是长期支持版本&#xff0c;因此选择安装这一版本&a…

游戏引擎学习第72天

无论如何&#xff0c;我们今天有一些调试工作要做&#xff0c;因为昨天做了一些修改&#xff0c;结果没有时间进行调试和处理。我们知道自己还有一些需要解决的问题&#xff0c;却没有及时完成&#xff0c;所以我们想继续进行这些调试。对我们来说&#xff0c;拖延调试工作总是…

信号的产生、处理

一、信号的概念 信号是linux系统提供的一种&#xff0c;向指定进程发送特定事件的方式。收到信号的进程&#xff0c;要对信号做识别和处理。信号的产生是异步的&#xff0c;进程在工作过程中随时可能收到信号。 信号的种类分为以下这么多种&#xff08;用指令kill -l查看&…

Node.js应用程序遇到了内存溢出的问题

vue 项目 跑起来&#xff0c;一直报错&#xff0c;内存溢出 在 文件node_modules 里 .bin > vue-cli-service.cmd 在依赖包这个文件第一行加上这个 node --max-old-space-size102400 "%~dp0\..\vue\cli-service\bin\vue-cli-service.js" %* node --max-old-s…

openGauss与GaussDB系统架构对比

openGauss与GaussDB系统架构对比 系统架构对比openGauss架构GaussDB架构 GaussDB集群管理组件 系统架构对比 openGauss架构 openGauss是集中式数据库系统&#xff0c;业务数据存储在单个物理节点上&#xff0c;数据访问任务被推送到服务节点执行&#xff0c;通过服务器的高并…

深入理解计算机系统—虚拟内存(一)

一个系统中的进程是与其他进程共享 CPU 和主存资源的。然而&#xff0c;共享主存会形成特殊的挑战。随着对 CPU 需求的增长&#xff0c;进程以某种合理的平滑方式慢了下来。但是如果太多的进程需要太多的内存&#xff0c;那么它们中的一些就根本无法运行。 为了更加有效地管理内…

九、Vue 事件处理器

文章目录 前言一、基础事件绑定:v-on 指令二、方法调用:组织有序的交互逻辑三、事件修饰符阻止冒泡与默认事件捕获与自身触发单次触发与鼠标按键区分四、按键修饰符前言 在 Vue.js 的交互世界里,事件处理器起着举足轻重的作用,它让页面从静态展示迈向动态交互,精准捕捉用户…

Quartus In-System Sources and Probes Editor 的使用说明

文章目录 前言使用说明参考资料 前言 Quartus 提供了 In-System Sources and Probes Editor 调试工具&#xff0c;通过 JTAG 接口使用该工具可以驱动和采样内部节点的逻辑值。即通过 Sources 功能来驱动 FPGA 内部信号&#xff0c;通过 Probes 功能来探测内部节点的逻辑值。在…

springboot整合Quartz实现定时任务

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1.核心概念2.基础实现2.1引入依赖2.2创建具体逻辑类2.3配置类 总结 前言 在项目中我们会有许多要进行定时执行逻辑的业务场景&#xff0c;比如定期生成日报、定…

阿里云 ECS 服务器绑定多个公网IP

阿里云 ECS 服务器绑定多个公网IP 一、弹性公网IP绑定ECS服务器 单台ECS一般只能直接绑定一个弹性公网IP&#xff0c;但是可以绑定多张弹性网卡&#xff0c;如果把弹性公网IP绑定到弹性网卡上&#xff0c;那么单台ECS就能间接绑定多个弹性公网IP。但有的服务器系统镜像可能不…

线性代数考研笔记

行列式 背景 分子行列式&#xff1a;求哪个未知数&#xff0c;就把b1&#xff0c;b2放在对应的位置 分母行列式&#xff1a;系数对应写即可 全排列与逆序数 1 3 2&#xff1a;逆序数为1 奇排列 1 2 3&#xff1a;逆序数为0 偶排列 将 1 3 2 只需将3 2交换1次就可以还原原…

LLM - 使用 LLaMA-Factory 部署大模型 HTTP 多模态服务 (4)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/144881432 大模型的 HTTP 服务&#xff0c;通过网络接口&#xff0c;提供 AI 模型功能的服务&#xff0c;允许通过发送 HTTP 请求&#xff0c;交互…

数据库知识汇总2

一. 范式 定义&#xff1a;范式是符合某一种级别的关系模式的集合。 关系数据库中的关系必须满足一定的要求。满足不同程度要求的为不同范式&#xff1b; 一个低一级范式的关系模式&#xff0c;通过模式分解&#xff08;schema decomposition&#xff09;可以转换为若干个高一…

TP 钱包插件版本的使用

目前 TokenPocket 的几个平台中&#xff0c;以 ios 和 安卓版本最为常见&#xff0c;其实很少有人知道&#xff0c;浏览器上有一个插件版本的 Tp, 用电脑多的话&#xff0c;这也是一个挺好的选择。 最新版本现在支持Chrome、Brave 浏览器、Edge&#xff08;Firefox及Opera正在…

反向传播算法的偏置更新步骤

偏置的更新步骤 假设我们有一个三层神经网络&#xff08;输入层、隐藏层和输出层&#xff09;&#xff0c;并且每层的激活函数为 sigmoid 函数。我们需要更新隐藏层和输出层的偏置。以下是详细的步骤&#xff1a; 1. 计算误差项&#xff08;Error Term&#xff09; 输出层的…

(二)当人工智能是一个函数,函数形式怎么选择?ChatGPT的函数又是什么?

在上一篇文章中&#xff0c;我们通过二次函数的例子&#xff0c;讲解了如何训练人工智能。今天&#xff0c;让我们进一步探讨&#xff1a;面对不同的实际问题&#xff0c;应该如何选择合适的函数形式&#xff1f; 一、广告推荐系统中的函数选择 1. 业务目标 想象一下&#x…

Vue3 中的插槽

Vue3 中插槽的使用&#xff0c;插槽是 Vue 中的一个特别特性&#xff0c;插槽就是模版内容。例如<h1>标题 1</h1>标题 1 就是插槽&#xff0c;Vue 是无法识别模板内容的&#xff0c;只能通过属性进行传递。Slot 主要包括默认、具名和作用域。Slot开发起来难度不大&…

单元测试3.0+ @RunWith(JMockit.class)+mock+injectable+Expectations

Jmockit使用笔记_基本功能使用Tested_Injectable_Mocked_Expectations_jmockit.class-CSDN博客 静态变量直接赋值就好&#xff0c;没必要mock了 测试框架Jmockit集合junit使用 RunWith(JMockit.class) 写在测试案例类上的注解 Tested 在测试案例中,写在我们要测试的类上…