IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python基础(进阶篇)+飞机大战游戏项目【原创真实个人记录】 -> 正文阅读

[Python知识库]python基础(进阶篇)+飞机大战游戏项目【原创真实个人记录】

链接: python基础(上篇).

链接: python基础(下篇).

链接: python基础这(模块篇).

面向对象编程(下)进阶

私有化属性

# 概述:
# 前面学习面向对象对象过程中,修改类属性都是直接通过类名修改的。如果有些
# 重要属性不想让别人随便修改,或者防止意外修改,该怎么办呢?

# 为了更好的保存属性安全,即不能随意修改,将属性定义为私有属性,添加一个可调用的方法去访问


#使用私有化属性的场景:
# 1.把特定的一个属性隐藏起来,不想让类的外部进行直接调用。
# 2.保护属性,不想让属性的值随意的改变。
# 3.保护这个属性 不想让派生类(子类)去继承


class Person:
    __hobby='跳舞'#类属性在外部也不能访问
    def __init__(self):
        self.__name='李四'  #加两个下划线,将此属性私有化之后,就不能在类外部直接访问了
        self.age=30
        pass
#     在类的内部是可以访问的
    def __str__(self):
        '''
        私有化的属性在内部可以使用
        :return:
        '''
        return '{}的年龄是{},爱{}'.format(self.__name,self.age,self.__hobby)#People.__hobby也可以

x1=Person()
# print(x1.__name)
# 打印错误结果:
# # AttributeError: 'Person' object has no attribute '__name'
print(x1)
#打印结果:
# 李四的年龄是30

class student(Person):
    def printInfo(self):
        print(self.__name)#在此访问父类中的私有属性 ,也是不可以的
    pass

stu=student()
# print(stu.__name)
# 打印结果:
# AttributeError: 'student' object has no attribute '__name'
# 说明子类的继承之后也是不能在外部直接调用私有属性的


# 小结:
# 1.私有化的[实例]属性  不能在外部直接访问 可以在类的内部随意使用
# 2.子类不能继承父类的私有化属性[只能继承父类公共的属性和行为]
# 3.在属性名的前面直接加讲个下划线就可以变为私有化属性了.
 # 修改私有属性
#     def changeValue(self):
#         Person.__hobby='唱歌'

私有化方法

class animal:
    def __eat(self):
        print('吃东西')
        pass
    def run(self):
        self.__eat()#在此调用私有化方法
        print('飞快的跑')
        pass
    pass
class Bird(animal):
    pass

b1=Bird()
# print(Bird.__eat())

# 打印结果:
# AttributeError: type object 'Bird' has no attribute '__eat'

#在方法名称前面加两个下划线,为私有方法
b1.run()

# 打印结果:
# 吃东西
# 飞快的跑
# 特点同私有化属性


# 特性:
# 私有化方法一般是类内部调用,子类不能继承,外部不能调用.
#
# 单下划线,双下划线,头尾下划线说明:

# _xxx 前面加一个下划线,以单下划线开头的表示的是protected类型的变量即保护类
# 型只能允许其本身与子类进行访问,不能使用from xxx impor *的方式导入
#
# _xx_ 前后两个下划线 ,魔术方法,一般是python自由,开发者不要创建这类型的方法.
#
# xxx_后面单下划线,避免属性名与python关键字冲突.

关于私有化属性的property属性

# 在访问私有化变量的时候,一般写两个方法,一个访问,一个修改,由方法控制访问。

# 这样的话给调用者的感觉就是调用了一个方法,并不是访问属性。我们怎么做到让调用者直接访问属性的方式,而且我们又能控制的方式提供给调用者?

# python中有一个被称为属性函数(property)的小概念,它可以派上用场,可以让调用者使用起来更快捷便利。


# 说白了是一种优化简便调用私有部分属性和修改私有部分属性的一种方式方法

# class Person(object):
#     def __init__(self):
#         self.__age=18#定义一个私有化属性
#         pass
#     def get_age(self):
#         return self.__age
#     def set_age(self,age):
#         if age<0:
#             print('年龄不能小于0')
#             pass
#         else:
#             self.__age=age
#             pass
#         pass
    #定义一个类属性,实现通过直接访问属性的形式去访问私有化属性
    # age=property(get_age,set_age)
# p1=Person()
# print(p1.age)
# 打印结果:
# 18
## 此时可以访问私有化属性了
# p1.age=25
# print(p1.age)
# 打印结果:
# 18
# 25
# 也可以直接对私有化属性进行修改了



#装饰器的方法:
class Person(object):
    def __init__(self):
        self.__age=18#定义一个私有化属性
        pass
    @property #用装饰器修饰 添加属性标签 提供一个getter方法
    def age(self):
        return self.__age
    @age.setter   #提供一个setter方法
    def age(self,age):#修改私有属性
        if age<0:
            print('年龄不能小于0')
            pass
        else:
            self.__age=age
            pass
        pass
p1=Person()
print(p1.age)

p1.age=25
print(p1.age)


#同样也可以更改私有属性
#装饰器也是一种比较简洁方便的更改私有属性的一种方式

动态添加属性和方法

# 动态添加属性
# class Student:
#     def __init__(self,name,age):
#         self.name=name
#         self.age=age
#     def __str__(self):
#         return '{}今年{}岁'.format(self.name,self.age)
#     pass
# wy=Student('王钰',14)
# print(wy)
# #添加属性
# wy.weight=80
# print(wy.weight)
# print('------------创建另外一个属性-------------')

# zm=Student('张明',20)
# print(zm.weight)
# 打印结果:
# 'Student' object has no attribute 'weight'
# 显然是新的实例对象没有新添加的weight属性

# print('------------给类对象添加属性-------------')

# Student.school='北京邮电大学'  #动态类属性
# print(wy.school)





# 动态添加实例方法方法:
import types #导入添加方法的库
def dynamicSort(self):
    print('{}的体重是{}kg,在{}读大学'.format(self.name,self.weight,Student.school))
# 绑定类方法
@classmethod
def classTest(cls):
    print('这是一个类方法')
    pass
# 静态方法
@staticmethod
def staticMethond():
    print('这是一个静态方法')
    pass


class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __str__(self):
        return '{}今年{}岁'.format(self.name,self.age)
    pass
# 绑定类方法:
Student.TestMethod=classTest
Student.TestMethod()
print('-----------------类方法结束----------------')
Student.staticMethod=staticMethond
Student.staticMethod()
print('------------------静态方法结束--------------')
wy=Student('王钰',14)
#添加属性
wy.weight=50
wy.PrintInfo=types.MethodType(dynamicSort,wy)
Student.school='北京邮电大学'  #动态类属性
print('---------------执行动态方法的绑定-----------------------')
wy.PrintInfo()
zm=Student('张明',20)
# zm.PrintInfo()
#至此,我们也同样可以认为,动态方法的绑定是依附于对应的实例对象,别的对象实例是无法调用此函数

new和单例模式

# 概述:
# __new__方法的作用是,创建并返回一个实例对象,如果__new__只调用了一次,就会得到一个对象。
# 继承自object的新式类才有new这一魔法方法
#
#
# 注意事项:
# 1.__new__放法的作用是在一个对象实例化的时候所调用的第一个方法。
#
# 2.__new__至少必须要有一个参数cls,代表要实例化类,此参数在实例化时由python解释器
# 自动提供,其他的参数是用来直接传递给__init__方法
#
# 3.__new__决定是否要使用该__init__方法,因为__new__可以调用其他类的构造方法或
# 者直接返回别的实例对象来作为本类的实例,如果__new__没有返回实例对象,则__init__不会被调用
#
# 4.在__new__ 方法中,不能调用自己的__new__方法,即:return cls.__new__(cls),否则会
# 报错


class animal:
    def __init__(self):
        self.color='红色'
        pass
    #在python中,如果不重写__new__默认结构如下:
    def __new__(cls,*args,**kwargs):
        return super().__new__(cls,*args,**kwargs)#super为父类
    pass
tigger=animal()#实例化的过程会自动调用 __new__去创建实例
#在新式类中 __new__ 才是真正的实例化的方法,为提供外壳制造出实力框架,然后调用该框架内的构造方法__init__进行丰满操作





# 单例模式
# 是一种常用的软件设计模式,确保某一个类只有一个实例存在
# 如果希望在整个系统中,某个类只能出现一个实例的时候,那么这个单例对象就满足要求

#创建一个单例对象 基于__new__去实现的

# class DataBassClass(object):
#     def __new__(cls, *args, **kwargs):
#         # cls._instance=cls.__new__(cls) 不能使用自身的new方法
#         cls._instance=super().__new__(cls,*args,**kwargs)
#         return cls._instance
#     pass
# db1=DataBassClass()
# print(id(db1))
# db2=DataBassClass()
# print(id(db2))
# 打印结果:
# 2076635823408
# 2076635823360
# 可见,这两个实例化对象的地址是不一样的,显然不是单个实例对象


# 那我们增加一个if判断语句,进行单例模式的构造
class DataBassClass(object):
    def __new__(cls, *args, **kwargs):
        # cls._instance=cls.__new__(cls) 不能使用自身的new方法
        if not hasattr(cls,'_instance'):#判断如果不存在实例化对象的代码
            cls._instance=super().__new__(cls,*args,**kwargs)
        return cls._instance
    pass
db1=DataBassClass()
print(id(db1))
db2=DataBassClass()
print(id(db2))
#打印结果:
# 2242430303536
# 2242430303536
# 地址一样,说明只有一个实例化对象
class Db(DataBassClass):
    pass
D1=Db()
print(id(D1))
# 打印结果
# 1622695869696
# 1622695869696
# 1622695869696

__slots__属性

# 概述
# python是动态语言,在运行的时候可以动态添加属性。入伏哦要限制在运行的
# 时候给类添加属性,python允许在定义class的时候,定义一个特殊的__slots__变量,来限制class实例能添加的属性
#
# 只有在__slots__变量中的属性才能被添加,没有在__slits__变量中的属性会添加失败。可以防止其他人在调用类的时候胡乱添加属性或方法。
# __slots__属性子类不会继承,只有在当前类中有效


# 作用:
#限制要添加的实例属性
# 节约内存空间
class Student(object):
    __slots__ = ('name','age','score')
    def __str__(self):
        return '{}..{}..{}'.format(self.name,self.age,self.score)
xw=Student()
xw.name='小王'
xw.age=20
xw.score=100
print(xw)
# print(xw.__dict__)#所有可以用的属性都在这里储存  不同slot限定的话不足的地方就是占用的内存空间大
#可以看到在定义了slot 变量之后 student类的实例已经不能随意创建不在Slot定义的属性了
#同时还可以看到实例当中也不再有__dict__


#在继承关系当中使用 __slots__
class test(Student):
    pass
wpc=test()
wpc.pro='计算机科学与技术'
print(wpc.pro)
#当子类未生名__slots时,那么是不会继承父类的__slots__,此时子类可以随意的属性赋值的
#子类声明了 __slots__时,继承父类的__slots__,也是子类__slots__的范围是为父类的加上子类 的属性范围
# 即:
#   __slots__=('pro')

错误方法与异常处理


# 语法格式

#     可能出现错误的代码块
# except:
#     出错之后执行的代码块
# else:
#     没有出错的代码块
# finally:
#     不管有没有出错都执行的代码块


# try...except语句
# 将可能出错的代码放到try里面,except可以指定类型捕获异常。
# except里面的代码是捕获到异常时执行,将错误捕获,这样程序就不会因为一段代码包异常而导致整个程序崩溃

# except在捕获错误异常的时候 只要根据具体的错误类型来捕获的
# 用一个块 可以捕获多个不同类型的异常
try:
    print(b)
    # li=[1,2,34]
    # print(li[10])#通过下标去访问列表
    # a=10/0
    pass
# except NameError as msg:
#     print(msg)
#     pass
# except IndexError as msg:
#     print(msg)
#     pass
# except ZeroDivisionError as msg:
#     print(msg)
#这些except能捕获相应的错误类型 并给出提示

#一个万能的捕获错误类型的代码

except Exception as result:
    print(result)
    # 在此尽量的去捕获获得到的错误
# print('初次接触异常处理')
# print('sfj aosfjaspf')
# 那是否是我们写越多的try except 去捕获错误越好呢?

def A(s):
    return 10/int(s)
def B(s):
    return A(s)*2
def main():
    try:
        B("0")
        pass
    except Exception as msg:
        print(msg)
        pass
    pass

main()
#不需要在每个可能出现错误的地方捕获,只要在合适的层次捕获错误就可以了 这样的话就大大减少我们写try--except 的麻烦

#异常的抛出机制
#如果在运行时发生异常 解释器会查找相应的异常捕获类型
#如果在当前函数里面没有找到的话 它会讲异常传递给上层的调用函数,看能否处理
#如果在最外层没找到的话,解释器就会退出,程序就会死掉


#try-except-else
try:
    print (aa)
    pass
except Exception as msg:
    print(msg)
else:
    print('当Try里面的代码 没有出现异常的情况下 我才会执行')


# try-except-finally
try:
    pass
except Exception as msg:
    print(msg)
    pass
finally:
    print('释放文件的资源、数据库链接时资源等等')
    print('不管有没有错都执行的代码块')










# 自定义异常
class ToolongMyException(Exception):
    def __init__(self,length):
        '''

        :param length:长度
        '''
        self.length=length
        pass
    def __str__(self):
        return '您输入的姓名数据长度是'+str(self.length)+'超过长度了..'
def name_Test():
    name=input('请输入名字')
    try:
        if len(name)>5:
            raise ToolongMyException(len(name))#抛出异常
        else:
            print(name)
    except ToolongMyException as result:
        print(result)
        pass
    finally:
        print('执行完毕了....')
name_Test()

面向对象编程的作业

# 1、python中new方法作用是什么?
#
# 答:用来创建实例对象,只有继承了object的话,才能有这个方法
#
# 2、什么是单例模式?单例模式适用于什么场景?
#
# 答:要求一个类有且只有一个实例,并且提供了一个全局的访问点
# 场景:日志插入logger的操作,网站计数器,权限验证模式,window资源管理器,系统回收站,数据库连接池
#
# 3、私有化方法于私有化属性在子类中能否继承?
#
# 答:不能
#
# 4、在python中什么是异常?
#
# 答:异常就是程序在执行的过程中发生的错误。
#
# 5、python中如何处理异常的?
#
# 答:分别根据异常的类型去处理
#
# 6、python中异常处理语句的一般格式
#
# 答:
# try:
# #正常操作
# except:
# #。。。
# else:
# #。。。
# finally:
# #。。。
#
# 7、__slot__属性的作用
#
# 答:限制属性的随意输入,
# 节省内存空间
#
# 8、私有化属性的作用?
#
# 答:保护数据,封装性的体现
#
# 9、在类的外面是否能修改私有属性?
#
# 答:不可以直接修改的,通过方法实现,还可以通过借助属性函数 property去实现

# 10、如果一个类中,只有指定的属性或者方法能被外部修改,那么该如何限制外部修改。

# 答:堆属性进行私有化的设定


# 1、编写一段代码以完成下面的要求
# 定义一个Person类,类中要有初始化的方法,方法中要有人的姓名,年龄两个私有化属
# 提供获取用户信息的函数。
# 提供获取私有属性的方法
# 提供可以设置私有属性的方法
# 设置年龄范围在(0-120)的方法,如果不在这个范围,不能设置成功。
class Person:
    def __init__(self):
        self.__name='王钰'
        self.__age=14

    def __str__(self):
        return '{}的年龄是{}'.format(self.__name,self.__age)
    def getName(self):
        return self.__name
    def getAge(self):
        return self.__age
    def setName(self,name):
        self.__name=name
    def setAGE(self,age):
        if age>120:
            print('设置失败,超出年龄范围')
        else:
            self.__age=age





# 2、请写一个单例模式
# class Test(object):
#     def __new__(cls, *args, **kwargs):
#         # cls._instance=cls.__new__(cls) 不能使用自身的new方法
#         if not hasattr(cls,'_instance'):#判断如果不存在实例化对象的代码
#             cls._instance=super().__new__(cls,*args,**kwargs)
#         return cls._instance
#     pass
# 3、创建一个类,并定义两个私有化属性,提供一个获取属性的方法,和设置属性的方法。利用property属性给调用者提供属性方式的调用获取和设置私有化属性的方法
class Student:
    def __init__(self):
        self.__name='王钰'
        self.__score=90
    @property
    def name(self):
        return self.__name
    @name.setter
    def name(self,name):
        self.__name=name
    @property
    def score(self):
        return self.__score
    @score.setter
    def score(self,score):
        self.__score=score
        pass
    def __str__(self):
        return self.name
    def __call__(self, *args, **kwargs):
        # print(self.__name+'的得分是:'+(str)self.__score)
        print('{}的得分是:{}'.format(self.name,self.score))
        pass
    #__Call__将实例对象以函数的形式去调用,返回的就是这个call函数所返回的内容

    pass

xw=Student()
xw()#将实例对象以函数的形式调用
print(xw)
xw.name='李四'
xw.score=90
xw()



# 4、创建一个animal类,实例化一个cat对象,请给cat对象动态绑定一个run方法,给类绑定一个类属性color,给类绑定一个类方法打印字符串'ok'
import types
def run(self):
    print('奔跑')
    pass

@classmethod
def printing(cls):
    print('ok')


class animal:
    pass
cat=animal()
cat.run=types.MethodType(run,cat)
animal.printing=printing
cat.printing()
animal.color='红色'

面向对象编程的究极案例,飞机大战游戏

# plane pro 需求描述:
#
# 存在四个对象:
# 我放飞机、敌方飞机、我方子弹、敌方子弹
#
# 功能:
# 背景音乐的添加
#
# 我方飞机可以移动【根据按键来控制移动】
# 对方飞机也可以随机移动
#
# 双方飞机都可以发射子弹
#
# 步骤:
# 1.创建一个窗口
# 2.创建一个我方飞机 根据方向左右移动
# 3.给我方飞机添加发射子弹的功能【按下空格键去发送】
# 4.创建一个敌人飞机
# 5.敌人飞机可以自由移动
# 6.敌人飞机可以自动的发射子弹



pygame库安装

安装pygame时直接打开cmd 输入pip intall pygame安装即可

在创建Pycharm project工程时,在terminal中找到local

输入pip list试一试是否安装成功pygame,如果没有,再试试命令pip intall pygame

如果发现有错误

那么复制cmd中你pygame所安装的地址

拷贝到你所建立的pycharm项目中lib文件及下面。

具体代码

代码

import pygame#引用第三方的模块
from pygame.locals import *
import random
import time





class player(object):
    def __init__(self,screen):
        # 设置飞机的初始位置
        self.x=250
        self.y=550
        # 设置要显示内容的窗口
        self.screen=screen
        # 载入飞机的图片
        self.imageName='./sucai/player_plane.png'
        self.image=pygame.image.load(self.imageName)
        self.bulletList=[]#定义发射子弹的列表
        pass
    def leftMove(self):
        if self.x>0:
            self.x-=25
        pass
    def rightMove(self):
        if self.x<450:
            self.x+=25
            pass
        pass
    def display(self):
        self.screen.blit(self.image,(self.x,self.y))
        #完善子弹的显示逻辑
        needDeltItemList=[]#需要删除的子弹列表,如果不删除会占用大量内存资源
        for item in self.bulletList:
            if item.judge():
                needDeltItemList.append(item)
                pass
            pass
        #重新遍历一下
        for i in needDeltItemList:
            self.bulletList.remove(i)#逐个删除子弹内容
        pass
        for bullet in self.bulletList:
            bullet.disPlay()#显示子弹的位置
            bullet.moveUp()#让这个子弹进行移动,下次再显示的时候就能看到子弹移动过后的位置
    # 发射子弹
    def sheBullet(self):
        # 创建一个子弹对象
        newBUllet=Bullet(self.x,self.y,self.screen)
        self.bulletList.append(newBUllet)
        pass

#创建子弹类
class Bullet:
    def __init__(self,x,y,screen):
        self.x=x+23
        self.y=y+40
        self.screen=screen
        self.image=pygame.image.load('./sucai/player_bullet.png')
        pass

    def disPlay(self):
        self.screen.blit(self.image,(self.x,self.y))
        pass
    def moveUp(self):
        self.y-=0.1
        pass
    def judge(self):
        #判断子弹是否越界
        if self.y<0:
            return True
        else:
            return False
        pass


def key_control(playerObject):
    '''
    通过定义普通的函数 来实现键盘的检测
    :param playerObject:控制检测的对象
    :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')
                playerObject.leftMove()#调用函数实现左移
                pass
            elif event.type==K_d or event.key==K_RIGHT:
                print('right')
                playerObject.rightMove()#调用函数实现右移
                pass
            elif event.key==K_SPACE:
                print('k_SPACE')
                playerObject.sheBullet()
# 创建拜登
class enemy:
    def __init__(self,screen):
        #默认设计一个方向,左右的来移动
        self.dirction='right'
        # 设置飞机的初始位置
        self.x=0
        self.y=0
        # 设置要显示内容的窗口
        self.screen=screen
        # 载入飞机的图片
        self.image=pygame.image.load('./sucai/enemy_plane.png')
        self.bulletList=[]#定义发射子弹的列表
        pass
    def disPlay(self):
        '''
        显示敌机以及位置的信息
        :return:
        '''
        self.screen.blit(self.image,(self.x,self.y))
        #完善子弹的显示逻辑
        needDeltItemList=[]#需要删除的子弹列表,如果不删除会占用大量内存资源
        for item in self.bulletList:
            if item.judge():
                needDeltItemList.append(item)
                pass
            pass
        #重新遍历一下
        for i in needDeltItemList:
            self.bulletList.remove(i)#逐个删除子弹内容
        pass
        for bullet in self.bulletList:
            bullet.disPlay()#显示子弹的位置
            bullet.moveUp()#让这个子弹进行移动,下次再显示的时候就能看到子弹移动过后的位置

    def shoot(self):
        '''
        敌机随机的发射子弹
        :return:
        '''
        num=random.randint(1,255)
        if num==3:
            newBullet=enemyBullet(self.x,self.y,self.screen)
            self.bulletList.append(newBullet)
        pass
    def move(self):
        if self.dirction=='right':
            self.x+=0.1
        elif self.dirction=='left':
            self.x-=0.1
        if self.x>500-20:
            self.dirction='left'
        elif self.x<0:
            self.dirction='right'
            pass
        pass

    pass

# 敌机子弹类
class enemyBullet:
    def __init__(self,x,y,screen):
        self.x=x+23
        self.y=y+40
        self.screen=screen
        self.image=pygame.image.load('./sucai/enemy_bullet.png')
        pass

    def disPlay(self):
        self.screen.blit(self.image,(self.x,self.y))
        pass
    def moveUp(self):
        self.y+=0.1
        pass
    def judge(self):
        #判断子弹是否越界
        if self.y>550:
            return True
        else:
            return False
        pass



def main():
    #首先创建一个窗口 用来显示内容
    screen=pygame.display.set_mode((500,600))
    #设定一个背景图片对象
    background=pygame.image.load('./sucai/backgroud.webp')
    #设置一个标题title
    pygame.display.set_caption('特朗普大战拜登')


    #添加背景音乐
    pygame.mixer.init()
    pygame.mixer.music.load('./sucai/backgroud_music.mp3')
    pygame.mixer.music.set_volume(0.2)
    pygame.mixer.music.play(-1)#循环次数  -1表示无限循环

    #创建一个飞机对象
    hero=player(screen)

    baideng=enemy(screen)

    #设置要显示的内容
    while True:
        screen.blit(background,(0,0))
        #显示玩家飞机的图片
        hero.display()
        baideng.disPlay()
        baideng.move()#敌机移动
        baideng.shoot()#敌机随即发射子弹

        #获取键盘事件

        key_control(hero)

        #更新显示内容
        pygame.display.update()
        # 创建一个拜登
        # time.sleep(1)#休眠一秒钟在循环   #太慢了
        # pygame.time.Clock().tick(500)  #一秒钟15次

    pass
# if __name__=='main':
	main()

代码优化之后

import pygame#引用第三方的模块
from pygame.locals import *
import random
import time

#抽象出来一个人物的类
class BassPlane(object):
    def __init__(self,screen,imagePath):
        '''
        初始化基类函数
        :param screen:主窗体函数
        :param imagePath: 加载的图片
        '''
        self.screen=screen
        self.image=pygame.image.load(imagePath)
        self.bulletList=[]#存储所有的子弹
        pass
    def disPlay(self):
        self.screen.blit(self.image,(self.x,self.y))
        #完善子弹的显示逻辑
        needDeltItemList=[]#需要删除的子弹列表,如果不删除会占用大量内存资源
        for item in self.bulletList:
            if item.judge():
                needDeltItemList.append(item)
                pass
            pass
        #重新遍历一下
        for i in needDeltItemList:
            self.bulletList.remove(i)#逐个删除子弹内容
        pass
        for bullet in self.bulletList:
            bullet.disPlay()#显示子弹的位置
            bullet.move()#让这个子弹进行移动,下次再显示的时候就能看到子弹移动过后的位置

class commomBullet(object):
    '''
    公共子弹类
    '''
    def __init__(self,x,y,screen,bulletType):
        self.type=bulletType
        self.screen=screen
        if self.type=='Player':
            self.x=x+26
            self.y=y-40
            self.imagePath='./sucai/player_bullet.png'
        elif self.type=='enemy':
            self.x=x+20
            self.y=y+45
            self.imagePath='./sucai/enemy_bullet.png'
        self.image=pygame.image.load(self.imagePath)
        pass
    def move(self):
        '''
        子弹的移动
        :return:
        '''
        if self.type=='Player':
            self.y-=0.1
        elif self.type=='enemy':
            self.y+=0.1
            pass
        pass
    def disPlay(self):
        self.screen.blit(self.image,(self.x,self.y))
    def judge(self):
        if self.y>550 or self.y<0:
            return True
        else:
            return False
        pass



    pass




class player(BassPlane):
    def __init__(self,screen):
        '''
        初始化函数
        :param screen:
        '''
        # 设置飞机的初始位置
        super().__init__(screen,'./sucai/player_plane.png')
        self.x=250
        self.y=550

    def leftMove(self):
        if self.x>0:
            self.x-=25
        pass
    def rightMove(self):
        if self.x<450:
            self.x+=25
            pass
        pass
    def sheBullet(self):
        # 创建一个子弹对象
        newBUllet=commomBullet(self.x,self.y,self.screen,'Player')
        self.bulletList.append(newBUllet)
        pass

def key_control(playerObject):
    '''
    通过定义普通的函数 来实现键盘的检测
    :param playerObject:控制检测的对象
    :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')
                playerObject.leftMove()#调用函数实现左移
                pass
            elif event.type==K_d or event.key==K_RIGHT:
                print('right')
                playerObject.rightMove()#调用函数实现右移
                pass
            elif event.key==K_SPACE:
                print('k_SPACE')
                playerObject.sheBullet()
# 创建拜登
class enemy(BassPlane):
    def __init__(self,screen):
        super().__init__(screen,'./sucai/enemy_plane.png')
        #默认设计一个方向,左右的来移动
        self.dirction='right'
        # 设置飞机的初始位置
        self.x=0
        self.y=0
        pass
    def shoot(self):
        '''
        敌机随机的发射子弹
        :return:
        '''
        num=random.randint(1,1000)
        if num==3:
            newBullet=commomBullet(self.x,self.y,self.screen,'enemy')
            self.bulletList.append(newBullet)
        pass
    def move(self):
        if self.dirction=='right':
            self.x+=0.1
        elif self.dirction=='left':
            self.x-=0.1
        if self.x>500-20:
            self.dirction='left'
        elif self.x<0:
            self.dirction='right'
            pass
        pass

    pass



def main():
    #首先创建一个窗口 用来显示内容
    screen=pygame.display.set_mode((500,600))
    #设定一个背景图片对象
    background=pygame.image.load('./sucai/backgroud.webp')
    #设置一个标题title
    pygame.display.set_caption('特朗普大战拜登')


    #添加背景音乐
    pygame.mixer.init()
    pygame.mixer.music.load('./sucai/backgroud_music.mp3')
    pygame.mixer.music.set_volume(0.2)
    pygame.mixer.music.play(-1)#循环次数  -1表示无限循环

    #创建一个飞机对象
    hero=player(screen)

    baideng=enemy(screen)

    #设置要显示的内容
    while True:
        screen.blit(background,(0,0))
        #显示玩家飞机的图片
        hero.disPlay()
        baideng.disPlay()
        baideng.move()#敌机移动
        baideng.shoot()#敌机随即发射子弹

        #获取键盘事件

        key_control(hero)

        #更新显示内容
        pygame.display.update()
        # 创建一个拜登
        # time.sleep(1)#休眠一秒钟在循环   #太慢了
        # pygame.time.Clock().tick(500)  #一秒钟15次

    pass
# if __name__=='main':

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-08-09 10:12:00  更:2021-08-09 10:12:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 1:23:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计