Python学习 day10-2021.3.8(飞机大战游戏)


Python入门课程系列:


1. Pygame

Pygame介绍:Pygame是一个利用SDL库写的游戏库,SDL库全名Simple DirectMedia Layer,是用C写的,不过也可以用C++进行开发,Pygame就是Python中使用它的一个库
官网教程:http://www.pygame.org/docs/
官网安装指南:https://www.pygame.org/wiki/GettingStarted#Pygame%20Installation
Pygame模块一览表:

模块名 功能 模块名 功能
pygame.cdrom 访问光驱 pygame.movie 播放视频
pygame.cursors 加载光标 pygame.music 播放音频
pygame.display 访问显示设备 pygame.overlay 访问高级视频叠加
pygame.draw 绘制形状、线和点 pygame 就是我们在学的这个东西了……
pygame.event 管理事件 pygame.rect 管理矩形区域
pygame.font 使用字体 pygame.sndarray 操作声音数据
pygame.image 加载和存储图片 pygame.sprite 操作移动图像
pygame.joystick 使用游戏手柄或者类似的东西 pygame.surface 管理图像和屏幕
pygame.key 读取键盘按键 pygame.surfarray 管理点阵图像数据
pygame.mixer 声音 pygame.time 管理时间和帧信息
pygame.mouse 鼠标 pygame.transform 缩放和移动图像

在电脑安装好pygame后,打开pycharm安装pygame模块


如果在pycharm中安装不成功,出现Command "python setup.py egg_info" failed with code 1 in xxx\xxx\xxx的报错,说明pycharm和pygame版本不同步,处理方法:1. 确保在系统层面的python环境里面已经安装了pygame(pip install pygame);2. 可以把已经安装好的pygame模块的文件夹拷贝到pycharm所创建项目中venv虚拟环境里面。

2. 思路

需求的描述:

存在4个对象:
我方飞机、敌方飞机、我方子弹、敌方子弹。
功能:
背景音乐的添加
我方飞机可以移动【根据按键来控制的】
敌方飞机也可以移动【随机的自动移动】
双方飞机都可以发射子弹
步骤:
1.创建一个窗口
2.创建一个我方飞机 根据方向键左右的移动
3.给我方飞机添加发射子弹的功能【按下空格键发射】
4.创建一个敌机
5.敌机可以自由移动
6.敌机可以发射子弹
准备背景音乐和素材图片(战机、敌机、战机子弹、敌机子弹)

控制玩具飞机-面向对象⚠️

实现步骤与原理:
实现步骤原理跟面向过程是一样的,不同的是代码的组织方式不一样:
1)创建一个飞机类,实现左移、右移、显示三个功能
2)创建一个键盘控制函数,实现键盘的左、右、空格键的功能
3)创建主函数,实现创建窗口、背景图片、背景音乐、并实现所有的逻辑

玩家飞机发射子弹⚠️

实现原理
1)每次按回车键就会有一颗子弹射出,起始位置就是从飞机的停靠位置
2)子弹超出窗口就会消失,并且删除掉子弹(否则子弹越来越多,界面会越来越卡)
3)每一颗子弹就代表一张图片
4)子弹从发射开始 ,慢慢往上移动直到消失。

import pygame #引用第三方模块
import random
import time
from pygame.locals import * #*表示要导入这个包所有的内容
'''
1. 实现飞机的显示,并且可以控制飞机的移动【面向对象】
'''
class HeroPlane(object):
    def __init__(self,screen):
        '''
        初始化函数
        :param screen: 主窗体对象
        '''
        #设定飞机的默认位置
        self.x=175
        self.y=615
        #设置要显示内容的窗口
        self.screen=screen
        #生成飞机的图片对象
        self.imageName='./雷霆战机/images/hero/hero04.png'
        self.image=pygame.image.load(self.imageName)
        #用来存放子弹的列表
        self.bulletList=[]
        pass
    def moveleft(self):
        '''
        左移
        :return:
        '''
        if self.x>0:
            self.x-=10
        pass
    def moveright(self,):
        '''
        右移
        :return:
        '''
        if self.x<490:
            self.x+=10
        pass
    def display(self):
        '''
        飞机在主窗口中的显示
        :return:
        '''
        self.screen.blit(self.image,(self.x,self.y))
        #完善子弹的显示逻辑
        needDelItemList=[]
        for item in self.bulletList:
            if item.judge():
                needDelItemList.append(item)
                pass
            pass
        #重新遍历一下
        for i in needDelItemList:
            self.bulletList.remove(i)
            pass
        for bullet in self.bulletList:
            bullet.display() #显示子弹的位置
            bullet.move() #让这个子弹进行移动 下次再显示的时候就会看到子弹在修改后的位置
        pass
    #发射子弹
    def sheBullet(self):
        #创建一个新的子弹对象
        newBullet=Bullet(self.x,self.y,self.screen)
        self.bulletList.append(newBullet)
        pass
    pass

#创建子弹类对象
class Bullet(object):
    def __init__(self,x,y,screen):
        '''

        :param x:
        :param y:
        :param screen:
        '''
        self.x=x+50
        self.y=y-10
        self.screen=screen
        self.image=pygame.image.load('./雷霆战机/images/bullet/img_bullet.png')
        pass
    def display(self):
        self.screen.blit(self.image,(self.x,self.y))
        pass
    def move(self):
        self.y-=5
        pass
    def judge(self):
        '''
        判断子弹是否越界
        :return:
        '''
        if self.y<0:
            return True
        else:
            return False
    pass

#创建敌机类
class EnemyPlane:
    def __init__(self,screen):
        #默认设置一个方向
        self.direction='right'
        # 设定飞机的默认位置
        self.x = 0
        self.y = 0
        # 设置要显示内容的窗口
        self.screen = screen
        self.bulletList=[]
        # 生成飞机的图片对象
        self.imageName = './雷霆战机/images/enemy/boss.png'
        self.image = pygame.image.load(self.imageName)
        pass
    def display(self):
        '''
        显示敌机以及子弹位置信息
        :return:
        '''
        self.screen.blit(self.image,(self.x,self.y))
        # 完善子弹的显示逻辑
        needDelItemList = []
        for item in self.bulletList:
            if item.judge():
                needDelItemList.append(item)
                pass
            pass
        # 重新遍历一下
        for i in needDelItemList:
            self.bulletList.remove(i)
            pass
        for bullet in self.bulletList:
            bullet.display()  # 显示子弹的位置
            bullet.move()  # 让这个子弹进行移动 下次再显示的时候就会看到子弹在修改后的位置
        pass
        pass
    def sheBullet(self):
        '''
        敌机随机发射子弹
        :return:
        '''
        num=random.randint(1,100)
        if num==3:
            newBullet=EnemyBullet(self.x,self.y,self.screen)
            self.bulletList.append(newBullet)
        pass
    def move(self):
        '''
        敌机移动,随机进行
        :return:
        '''
        if self.direction=='right':
            self.x+=1
            pass
        elif self.direction=='left':
            self.x-=1
            pass
        if self.x>260:
            self.direction='left'
            pass
        elif self.x<0:
            self.direction='right'
    pass

#敌机子弹类
class EnemyBullet(object):
    def __init__(self,x,y,screen):
        '''

        :param x:
        :param y:
        :param screen:
        '''
        self.x=x+90
        self.y=y+90
        self.screen=screen
        self.image=pygame.image.load('./雷霆战机/images/bullet/enemy_bullet.png')
        pass
    def display(self):
        self.screen.blit(self.image,(self.x,self.y))
        pass
    def move(self):
        self.y+=3
        pass
    def judge(self):
        '''
        判断子弹是否越界
        :return:
        '''
        if self.y>700:
            return True
        else:
            return False
    pass

def key_control(HeroObj):
    '''
    定义普通函数 用来实现键盘的检测
    :param HeroObj: 可控制检测的对象
    :return:
    '''
    # 获取键盘事件
    eventlist = pygame.event.get()
    for event in eventlist:
        if event.type == QUIT:
            print('退出')
            exit()
            pass
        elif event.type == KEYDOWN:
            if event.type == K_a or event.key == K_LEFT:
                print('left')
                HeroObj.moveleft() #调用函数实现左移
            elif event.type == K_d or event.key == K_RIGHT:
                print('right')
                HeroObj.moveright() #调用函数实现右移
            elif event.key == K_SPACE:
                print('K_SPACE')
                HeroObj.sheBullet()
    pass

def main():
    # 首先创建窗口对象
    screen=pygame.display.set_mode((450,700))
    #创建一个背景图片对象
    background=pygame.image.load('./雷霆战机/images/bg/bg1.jpg')
    #设置一个title
    pygame.display.set_caption('huihui飞机大战')
    #添加背景音乐
    pygame.mixer.init() #初始化这个函数
    pygame.mixer.music.load('./PlaneWar/sound/game_music.ogg')
    pygame.mixer.music.set_volume((0.2))
    pygame.mixer.music.play(-1) #表示无限循环

    #创建一个飞机对象
    hero=HeroPlane(screen)
    #创建一个敌机对象
    enemyplane=EnemyPlane(screen)
    #设定需要显示的内容
    while True:
        screen.blit(background,(0,0))
        # 显示玩家飞机图片
        hero.display()
        enemyplane.display() #显示敌机
        enemyplane.move() #敌机移动
        enemyplane.sheBullet() #敌机随机发射子弹
        #获取键盘事件
        key_control((hero))
        #更新显示内容
        pygame.display.update()
        # time.sleep(1) #休眠一秒钟
        pygame.time.Clock().tick(20) #一秒钟运行20次

    pass
if __name__=='__main__':
    main()
抽象基类⚠️
import pygame #引用第三方模块
import random
import time
from pygame.locals import * #*表示要导入这个包所有的内容
'''
1. 实现飞机的显示,并且可以控制飞机的移动【面向对象】
'''
'''
1:实现飞机的显示 并且可以控制飞机的移动【面向对象】
'''
#抽象一个飞机的基类
class BasePlane(object):
    def __init__(self,screen,imageName):
        '''
        初始化基类函数
        :param screen:主窗体对象
        :param imageName:加载的图片
        '''
        self.screen=screen
        self.image=pygame.image.load(imageName)
        self.bulletList=[] #存储所有的子弹
        pass
    def display(self):
        self.screen.blit(self.image, (self.x, self.y))
        # 完善子弹的显示逻辑
        needDelItemList = []
        for item in self.bulletList:
            if item.judge():
                needDelItemList.append(item)
                pass
            pass
        # 重新遍历一下
        for i in needDelItemList:
            self.bulletList.remove(i)
            pass
        for bullet in self.bulletList:
            bullet.display()  # 显示子弹的位置
            bullet.move()  # 让这个子弹进行移动 下次再显示的时候就会看到子弹在修改后的位置
        pass
    pass

class CommonBullet(object):
    '''
    公共的子弹类
    '''
    def __init__(self,x,y,screen,bulletTYpe):
        self.type=bulletTYpe
        self.screen=screen
        if self.type=='hero':
            self.x=x+50
            self.y=y-10
            self.imagePath='./雷霆战机/images/bullet/img_bullet.png'
        elif self.type=='enemy':
            self.x=x+90
            self.y=y+90
            self.imagePath='./雷霆战机/images/bullet/enemy_bullet.png'
            pass
        self.image=pygame.image.load(self.imagePath)
        pass
    def move(self):
        '''
        子弹的移动
        :return:
        '''
        if self.type=='hero':
            self.y-=5
        elif self.type=='enemy':
            self.y+=3
            pass
        pass
    def display(self):
        self.screen.blit(self.image,(self.x,self.y))
        pass
    def judge(self):
        '''
        判断子弹是否越界
        :return:
        '''
        if self.y>700 or self.x<0:
            return True
        else:
            return False
        pass
    pass

class HeroPlane(BasePlane):
    def __init__(self,screen):
        '''
        初始化函数
        :param screen: 主窗体对象
        '''
        super().__init__(screen,'./雷霆战机/images/hero/hero04.png')
        #设定飞机的默认位置
        self.x=175
        self.y=615
        pass
    def moveleft(self):
        '''
        左移
        :return:
        '''
        if self.x>0:
            self.x-=10
        pass
    def moveright(self,):
        '''
        右移
        :return:
        '''
        if self.x<490:
            self.x+=10
        pass
    #发射子弹
    def sheBullet(self):
        #创建一个新的子弹对象
        newBullet=CommonBullet(self.x,self.y,self.screen,'hero')
        self.bulletList.append(newBullet)
        pass
    pass

#创建敌机类
class EnemyPlane(BasePlane):
    def __init__(self,screen):
        super.__init__(screen,'./雷霆战机/images/enemy/boss.png')
        #默认设置一个方向
        self.direction='right'
        # 设定飞机的默认位置
        self.x = 0
        self.y = 0
        pass
    def sheBullet(self):
        '''
        敌机随机发射子弹
        :return:
        '''
        num=random.randint(1,100)
        if num==3:
            newBullet=CommonBullet(self.x,self.y,self.screen,'enemy')
            self.bulletList.append(newBullet)
        pass
    def move(self):
        '''
        敌机移动,随机进行
        :return:
        '''
        if self.direction=='right':
            self.x+=1
            pass
        elif self.direction=='left':
            self.x-=1
            pass
        if self.x>260:
            self.direction='left'
            pass
        elif self.x<0:
            self.direction='right'
    pass

def key_control(HeroObj):
    '''
    定义普通函数 用来实现键盘的检测
    :param HeroObj: 可控制检测的对象
    :return:
    '''
    # 获取键盘事件
    eventlist = pygame.event.get()
    for event in eventlist:
        if event.type == QUIT:
            print('退出')
            exit()
            pass
        elif event.type == KEYDOWN:
            if event.type == K_a or event.key == K_LEFT:
                print('left')
                HeroObj.moveleft() #调用函数实现左移
            elif event.type == K_d or event.key == K_RIGHT:
                print('right')
                HeroObj.moveright() #调用函数实现右移
            elif event.key == K_SPACE:
                print('K_SPACE')
                HeroObj.sheBullet()
    pass

def main():
    # 首先创建窗口对象
    screen=pygame.display.set_mode((450,700))
    #创建一个背景图片对象
    background=pygame.image.load('./雷霆战机/images/bg/bg1.jpg')
    #设置一个title
    pygame.display.set_caption('huihui飞机大战')
    #添加背景音乐
    pygame.mixer.init() #初始化这个函数
    pygame.mixer.music.load('./PlaneWar/sound/game_music.ogg')
    pygame.mixer.music.set_volume((0.2))
    pygame.mixer.music.play(-1) #表示无限循环

    #创建一个飞机对象
    hero=HeroPlane(screen)
    #创建一个敌机对象
    enemyplane=EnemyPlane(screen)
    #设定需要显示的内容
    while True:
        screen.blit(background,(0,0))
        # 显示玩家飞机图片
        hero.display()
        enemyplane.display() #显示敌机
        enemyplane.move() #敌机移动
        enemyplane.sheBullet() #敌机随机发射子弹
        #获取键盘事件
        key_control((hero))
        #更新显示内容
        pygame.display.update()
        # time.sleep(1) #休眠一秒钟
        pygame.time.Clock().tick(20) #一秒钟运行20次

    pass
if __name__=='__main__':
    main()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容