【Python实训项目】pygame制作【飞机大战】

目录


一、课程设计目的及应用背景

        根据课程要求,以及面向对象程序设计的编程思想,在Windows操作系统环境下,运用PyCharm编译程序,以Python语言为开发语言,最终实现飞机大战游戏相应的游戏操作功能。Python是一种跨平台的、开源的、免费的、解释型的高级编程语言。它具有丰富的、强大的库, 能够把其他语言制作的各种模块很轻松地联结在一起, 所以Python常被称为“胶水”语言。Python语言近几年发展势头迅猛, 应用领域也非常广泛, 在Web编程、图形处理、黑客编程、大数据处理、网络爬虫、科学计算和游戏编程等领域都能找到Python的应用。其中Pygame是Python的一个第三方库, 搭载了基于OpenGL的图形库和优质的音频库, 可以快速上手制作2D游戏的原型。Pygame的API比较偏底层, 开发人员在编程时具有很大的自由度, 同时具有了很强的可定制性。Python语言的研究和发明主要是为了便于学习和应用, 因此Python语言是开源的, 并且语法非常简单、容易编写和理解。本文通过对飞机大战游戏的设计与分析, 掌握Python语言在游戏开发领域的优势。

        飞机大战游戏设计开发课题是《面向对象程序设计(Python)》中面向对象程序设计的一次运用,主要设计原则如下:

        (1)简单性,在实现软件的功能的同时, 尽量让软件操作简单易懂;

        (2)针对性,基于Python软件, 实现飞机大战游戏的各种要求;

        (3)一致性,类型、变量和其他元素的命名规则保持一致;

        完成同样的功能应该尽量使用同样的元素;界面元素的外观风格、摆放位置在同一个界面和不同界面之间是一致的。可以使其基本类库Pygame的基本函数和功能模块的调用操作实现python语言在课程设计中的运用。

        通过对飞机大战游戏设计的实现,要求我们进一步理解和掌握课堂上所学各种基本类型的变量、数据类型、类、用户输入和文件操作实现面向对象的游戏开发,以及它们在程序中的使用方法;掌握Python软件设计的基本内容和设计方法,并培养学生进行规范化软件设计的能力;掌握使用各种计算机资料和有关参考资料,提高我们进行程序设计的基本能力,逐步熟悉程序设计的方法,并养成良好的编程习惯。

        本次设计为了使飞机大战游戏具有更加丰富的功能,基于面向对象和面向过程的方法,使用Python编程语言提供资源结构,以Pygame模块对游戏进行研发,提出了飞机大战游戏开发方案。通过各种优化调整,实现了飞机的飞行移动、击落,计分等功能,实现了飞机大战的开发,增加游戏体验。

二、课程设计内容

开发一款飞机大战游戏,要求:

(1)实现飞机的移动、子弹发射,对本次游戏有一个初步的编写及认识。
(2)飞机的持续按键移动和飞机自爆优化。
(3)进行基类的抽取,使代码更具有层次性和简化重复代码。
(4)对判断以及删除越界子弹、敌机发射子弹进行扩展优化。

三、课程设计代码实现

1. 创建子弹类

        该项目可采用面向对象编程思路进行设计,对于不同的对象可设计3个不同的类,分别是子弹类、玩家飞机类和敌机类。

        子弹类主要实现的功能是:显示子弹、子弹移动和处理子弹越界问题。

1)显示子弹

        首先需要确定显示子弹的位置,当按下空格键时,代表玩家飞机要发射一枚子弹,因此,需要在玩家飞机的顶部位置显示子弹。并且无论玩家飞机左右移动到什么位置,只要按下空格键,子弹生成的初始位置都位于玩家飞机的顶部。因此,子弹的初始位置与玩家飞机的位置相关。

        首先可定义一个表示子弹的类Bullet,在该类中定义一个构造方法用于初始化数据,然后定义一个用于显示子弹的方法,具体代码如下。

#子弹类
class Bullet(object):
    def __init__(self, screen_temp, x, y):  #构造方法 初始化子弹对象的属性
        self.x = x+40   #子弹起始X坐标
        self.y = y-20   #子弹起始Y坐标
        self.screen = screen_temp   #窗口
        self.image = pygame.image.load("./images/bullet.png")   #创建一个子弹图片
    def display(self):  #显示子弹图片的方法
        self.screen.blit(self.image, (self.x, self.y))  #将创建的子弹图片按设定的坐标贴到窗口中

 2)子弹移动

        在Bullet类中添加一个子弹移动的方法move,让子弹每移动一次,y值减10,具体代码如下。

#子弹移动方法
    def move(self): #子弹移动方法
        self.y-=10  #子弹Y坐标自减10

3)处理子弹越界问题

        在Bullet类中添加一个judge方法,用于判断子弹是否发射到屏幕以外,具体代码如下。

    def judge(self):    #判断子弹是否越界的方法
        if self.y<0:    #如果子弹的Y坐标小于0
            return True #返回true正确
        else:
            return False #返回false错误

2.创建玩家飞机类

        玩家飞机类中主要实现的功能是:显示玩家飞机、控制玩家飞机左右移动以及发射子弹。

1)显示玩家飞机

        在窗口中要显示玩家飞机,可以根据玩家飞机图片的名称创建图像,再把该图像显示到屏幕的设定位置。

        首先定义一个表示玩家飞机的类Aircraft_obj,在该类中定义一个构造方法用于初始化数据,然后定义一个用于显示飞机的方法。在该类中还需要玩家飞机控制发射子弹,因此,在构造方法中还需要添加一个列表,用于存储玩家飞机发射的所有子弹,并且一旦遍历这个列表,就会将子弹显示到飞机对象的上方。具体代码如下。

#飞机类
class Aircraft_obj(object):
    def __init__(self, screen_temp):    #构造方法 初始化飞机对象的属性
        self.x = 190    #飞起起始X坐标
        self.y = 708    #飞机起始Y坐标
        self.screen = screen_temp   #窗口
        self.image = pygame.image.load("./images/hero1.png")    #创建一个飞机图
        self.bullet_list = []#存储发射出去的子弹对象引用
    def display(self):  #显示飞机图片的方法(这里包括了显示子弹的图片)
        self.screen.blit(self.image, (self.x, self.y))  #将创建的飞机图片按设定的坐标贴到窗口中
        #显示飞机发射的所有子弹
        for bullet in self.bullet_list:
            bullet.display()    #显示子弹
            bullet.move()   #移动子弹
            if bullet.judge():#判断子弹是否越界
                self.bullet_list.remove(bullet) #将子弹从bullet_list中删除

2)控制玩家飞机左右移动

        玩家飞机具有向左移动和向右移动的功能,这两个功能可以通过在方法中改变坐标的x值进行实现。还需要控制飞机不能移出窗口。具体代码如下。  

  def move_left(self):    #飞机左移方法
        if self.x < 10:     #X坐标小于10(移动距离)
            pass            #不做任何事
        else:
            self.x -= 10    #X坐标自减少10
    def move_right(self):   #飞机右移方法
        if self.x > 480-100-10: #X坐标大于(窗口宽度-飞机宽度-移动距离)的值
            pass            #不做任何事
        else:               
            self.x += 10    #坐标自增加10

3)控制玩家飞机发射子弹

        在玩家飞机类中创建fire()方法,将所有玩家飞机发射的子弹存储到飞机对象的属性列表中,具体代码如下。

   #存储发射子弹的方法
    def fire(self):
        self.bullet_list.append(Bullet(self.screen, self.x, self.y))    #将发射的子弹对象存储到bullet_list中

3. 创建敌机类

        敌机类中主要实现的功能是:显示敌机、敌机左右移动以及敌机被击中并爆炸。

1)初始化敌机

        跟玩家飞机类似,可定义一个表示敌机的类EnemyPlane。同样,敌机应该有默认的位置、呈现图像的窗口、敌机图片、在放爆炸图片的列表等属性,具体代码如下。

#敌机类

class EnemyPlane(object):
    def __init__(self, screen_temp):    #构造方法 初始化敌机对象的属性
        self.x = 0  #敌机的起始X坐标
        self.y = 0  #敌机的起始Y坐标
        self.screen = screen_temp   #窗口
        self.image = pygame.image.load("./images/enemy0.png")    #创建一个敌机图片
        self.direction = "right"    #用来存储飞机移动方向,默认向右移动
        #爆炸效果用的属性
        self.hit = False #表示是否要爆炸
        self.bomb_lists = [] #用来存储爆炸时需要的图片
        self.__crate_images() #调用这个方法向bomb_lists中添加图片
        self.image_num = 0#用来记录while循环的次数,当次数达到一定值时才显示一张爆炸的图,然后清空,当这个次数再次达到时,再显示下一个爆炸效果的图片
        self.image_index = 0#用来记录当前要显示的爆炸效果的图片的序号

2)敌机左右移动

        当程序启动后,敌机开始在窗口的项部做直线运行,直到碰到屏幕的边缘后向反方向做真线运行。

        可以为EnemyPlane(敌机)类添加一个移动敌机的方法move,在该方法中根据飞机移动的方向改变x对应的坐标值,再根据x的值限定敌机移动的范围,只要超过屏幕的宽度范围,就改变飞机运行的方向,具体代码如下。

    def move(self): #敌机移动方法
        if self.hit == True:
            pass
        else:
            if self.direction=="right":     #如果是向右移动
                self.x += 5     #X坐标自增加5
            elif self.direction=="left":    #如果是向左移动
                self.x -= 5     #X坐标自减少5
            if self.x>480-50:   #如果X坐标大于窗口减去敌机宽度的值
                self.direction = "left" #移动方向改为左
            elif self.x<0:      #如果X坐标小于0
                self.direction = "right"    #移动方向改为右

3)敌机爆炸

        敌机被子弹击中后会爆炸,爆炸过程中所需要用到的图片保存在bomb lists列表中,此处可定义一个方法用于添加图片到列表中,具体代码如下。

   def __crate_images(self):   #将爆炸需要的图片添加到self.bomb_lists中
        self.bomb_lists.append(pygame.image.load("./images/enemy0_down1.png"))
        self.bomb_lists.append(pygame.image.load("./images/enemy0_down2.png"))
        self.bomb_lists.append(pygame.image.load("./images/enemy0_down3.png"))
        self.bomb_lists.append(pygame.image.load("./images/enemy0_down4.png"))

        接下来定义一个判断爆炸的方法,只要满足以下3个条件中的任意一个即可实现爆炸:

        (1)子弹横坐标在敌机横坐标的区域中,并且子弹y坐标小于敌机图片的高度;

        (2)子弹最右侧坐标等于敌机最左侧坐标,并且子弹y坐标小于敌机图片的高度:

        (3)子弹最左侧尘标等于敌机最右侧坐标,并且子弹y坐标小于敌机图片的高度。具体代码如下

   #判断爆炸的方法,x1表示子弹最左侧的X坐标,x2表示子弹最右侧的X坐标,y表示子弹当前的Y坐标
   def  blast(self,x1,x2,y):   
  #判断子弹能命中敌机的三种情况,满足任意一种即可让敌机爆炸,51是敌机图片的宽度,39是敌机图片的高度
  #1.子弹横坐标在敌机横坐标的区域中,并且子弹Y坐标小于敌机图片的高度
 #2.子弹最右侧坐标等于敌机最左侧坐标,并且子弹Y坐标小于敌机图片的高度
  #3.子弹最左侧坐标等于敌机最右侧坐标,并且子弹Y坐标小于敌机图片的高度
  if ((x1>=self.x and x2<=self.x+51) or x2==self.x or x1==self.x+51) and y<39:
   self.hit = True

        显示敌机的方法与显示玩家飞机有所不同,需要判断是否已经被击中,如果已被击中,需要显示爆炸的图片后退出程序,如果没有被击中,显示敌机图片,具体代码如下。

    def display(self):  #显示敌机的方法
         #如果被击中,就显示爆炸效果,否则显示普通的飞机效果
        if self.hit == True:    #如果满足爆炸条件,就显示爆炸的图片
            self.screen.blit(self.bomb_lists[self.image_index], (self.x, self.y))
            self.image_num+=1   #这是统计循环次数,为了使玩家看清爆炸效果
            if self.image_num == 7: #如果循环次数达到7次
                self.image_num=0    #将循环次数改为0次
                self.image_index+=1 #图片显示序号+1,换为另一张图
            if self.image_index>3:  #这里爆炸图片一共是四张,所以是图片序号大于三次
                time.sleep(1)       #暂停一秒
                exit()  #调用exit让游戏退出
        else:   #否则显示正常的敌机图片
            self.screen.blit(self.image,(self.x, self.y))

4.检查键盘输入

        如果想要获取键盘和鼠标产生的事件,就需要使用for循环遍历事件列表,取出每个事件与eventtype《事件类型)进行比较。如果event.type的值为QUIT,表示用户按下关闭按钮,此时就要退出程序:如果event.type的值为KEYDOWN,表示用户使用了键盘,需要判断按下的是哪个键,然后进行键盘事件的处理。具体代码如下。

#处理鼠标和键盘事件的方法
def key_control(aircraft_temp):
    #获取当前等待处理的事件,使用for循环来遍历里面的事件
    for event in pygame.event.get():
        #判断是否点击了退出按钮
        if event.type == QUIT:
            print("exit")   #输出“exit”
            exit()  #退出窗口
        #判断是不是键盘按下事件
        elif event.type == KEYDOWN:
            #检测按键是不是a或者left
            if event.key == K_a or event.key == K_LEFT:
                print('left')   #输出“left”
                aircraft_temp.move_left()   #执行飞机左移方法
            #检测按键是不是d或者right
            elif event.key == K_d or event.key == K_RIGHT:
                print('right')  #输出“right”
                aircraft_temp.move_right()  #执行飞机右移方法
            #检测按键是不是空格键
            elif event.key == K_SPACE:
                print('space')  #输出“space”
                aircraft_temp.fire()    #执行飞机类中存储子弹的方法

5.创建主模块

        飞机大战的整个场景需要一个窗口作为载体,显示游戏中的画面。这里准备了一张图片用作游戏界面的背景,并在窗口中进行显示。

        在主模块中,需要创建玩家飞机对象和敌机对象、显示各个对象、判断敌机是否被击中、调用敌机移动方法让敌机移动、调用事件处理函数进行事件处理。具体代码如下。

import pygame                       #导入pygame模块
from pygame.locals import *             #导入pygame.locals模块
import time                         #导入time模块
def main():
    #1. 创建窗口
    pygame.init()
    screen = pygame.display.set_mode((480,852),0,32)
    #2. 创建一个背景图片
    background = pygame.image.load("./images/background.png")
    #3. 创建一个飞机对象
    aircraft = Aircraft_obj(screen)
     #4. 创建一个敌机对象
    enemy = EnemyPlane(screen)
    while True:
        screen.blit(background, (0,0))  #把背景复制到窗口的0,0处开始贴进去
        aircraft.display()  #执行飞机类中显示飞机的方法
        for bullet in aircraft.bullet_list: #循环飞机对象中存储的子弹信息
            x1 = bullet.x       #子弹当前X坐标
            x2 = bullet.x + 22  #子弹当前X坐标+子弹图片的宽
            y1 = bullet.y       #子弹当前Y坐标
            enemy.blast(x1,x2,y1)    #判断子弹的坐标区域有没有与敌机相交
        enemy.display()     #执行敌机类中显示敌机的方法
        enemy.move()        #调用敌机的移动方法
        pygame.display.update() #更新需要显示的内容到窗口
        key_control(aircraft)   #处理飞机对象的相关事件
        time.sleep(0.01)    #暂停0.01秒
main()

四、测试结果

五、思考、心得和改进以及不明白的问题

        本次课题研究是基于兴趣爱好的一次实践,兴趣爱好给予了我很大的动力,这也使我在遇到各种问题时,总能通过多种渠道找到解决方案。虽然是第一次使用Python开发游戏,在一边进行学习,一边进行游戏开发和设计过程中,遇到了很多问题,也走了不少弯路,但锻炼了自我解决问题的能力。这次课题研究不仅让我对Python有了进一步的了解,而且还大大提高了编程能力,锻炼了自己的逻辑思维和整体设计的能力,收获颇多。

        通过这次课题研究,我意识到完整的软件开发思路是非常重要的,它关系到我们开发过程能否顺利实现。在项目开始之前,必须有软件工程的系统化的知识体系,不仅如此,还应包括软件结构位置、代码编写和模块划分和整体布局,只有做完这些步骤,才能逐步开发出想要实现的功能。这样定能达到事半功倍的效果。

        整个软件按照计划大致实现了游戏的具体功能,虽然游戏能正常运行,不过因所学知识及开发周期有限,还有很多需要改进的地方,有待于日后进一步的改进和完善。这个游戏的实现,我是跟着网上的教学思路学着做的,我觉得实现这个飞机大战的也运用到了很多知识,通过这次实验,我对Python的理解也更加深刻。我觉得这个游戏的实现还是有一些不足的,例如没有实现多种子弹,随机道具拾取等等。

附录 所有代码如下:

# -*- coding:utf-8 -*-
import pygame                       #导入pygame模块
from pygame.locals import *             #导入pygame.locals模块
import time                         #导入time模块


#子弹类
class Bullet(object):
    def __init__(self, screen_temp, x, y):  #构造方法 初始化子弹对象的属性
        self.x = x+40   #子弹起始X坐标
        self.y = y-20   #子弹起始Y坐标
        self.screen = screen_temp   #窗口
        self.image = pygame.image.load("./images/bullet.png")   #创建一个子弹图片

    def display(self):  #显示子弹图片的方法
        self.screen.blit(self.image, (self.x, self.y))  #将创建的子弹图片按设定的坐标贴到窗口中

    def move(self): #子弹移动方法
        self.y-=10  #子弹Y坐标自减10

    def judge(self):    #判断子弹是否越界的方法
        if self.y<0:    #如果子弹的Y坐标小于0
            return True #返回true正确
        else:
            return False #返回false错误

#飞机类
class Aircraft_obj(object):
    def __init__(self, screen_temp):    #构造方法 初始化飞机对象的属性
        self.x = 190    #飞起起始X坐标
        self.y = 708    #飞机起始Y坐标
        self.screen = screen_temp   #窗口
        self.image = pygame.image.load("./images/hero1.png")    #创建一个飞机图
        self.bullet_list = []#存储发射出去的子弹对象引用

    def display(self):  #显示飞机图片的方法(这里包括了显示子弹的图片)
        self.screen.blit(self.image, (self.x, self.y))  #将创建的飞机图片按设定的坐标贴到窗口中
        
        #显示飞机发射的所有子弹
        for bullet in self.bullet_list:
            bullet.display()    #显示子弹
            bullet.move()   #移动子弹
            if bullet.judge():#判断子弹是否越界
                self.bullet_list.remove(bullet) #将子弹从bullet_list中删除

    def move_left(self):    #飞机左移方法
        if self.x < 10:     #X坐标小于10(移动距离)
            pass            #不做任何事
        else:
            self.x -= 10    #X坐标自减少10

    def move_right(self):   #飞机右移方法
        if self.x > 480-100-10: #X坐标大于(窗口宽度-飞机宽度-移动距离)的值
            pass            #不做任何事
        else:               
            self.x += 10    #坐标自增加10
    #存储发射子弹的方法
    def fire(self): 
        self.bullet_list.append(Bullet(self.screen, self.x, self.y))    #将发射的子弹对象存储到bullet_list中


#敌机类
class EnemyPlane(object):
    def __init__(self, screen_temp):    #构造方法 初始化敌机对象的属性
        self.x = 0  #敌机的起始X坐标
        self.y = 0  #敌机的起始Y坐标
        self.screen = screen_temp   #窗口
        self.image = pygame.image.load("./images/enemy0.png")    #创建一个敌机图片
        self.direction = "right"    #用来存储飞机移动方向,默认向右移动

        #爆炸效果用的属性
        self.hit = False #表示是否要爆炸
        self.bomb_lists = [] #用来存储爆炸时需要的图片
        self.__crate_images() #调用这个方法向bomb_lists中添加图片
        self.image_num = 0#用来记录while循环的次数,当次数达到一定值时才显示一张爆炸的图,然后清空,当这个次数再次达到时,再显示下一个爆炸效果的图片
        self.image_index = 0#用来记录当前要显示的爆炸效果的图片的序号

    def __crate_images(self):   #将爆炸需要的图片添加到self.bomb_lists中
        self.bomb_lists.append(pygame.image.load("./images/enemy0_down1.png"))
        self.bomb_lists.append(pygame.image.load("./images/enemy0_down2.png"))
        self.bomb_lists.append(pygame.image.load("./images/enemy0_down3.png"))
        self.bomb_lists.append(pygame.image.load("./images/enemy0_down4.png"))

    #判断爆炸的方法,x1表示子弹最左侧的X坐标,x2表示子弹最右侧的X坐标,y表示子弹当前的Y坐标
    def  blast(self,x1,x2,y):   
    #判断子弹能命中敌机的三种情况,满足任意一种即可让敌机爆炸,51是敌机图片的宽度,39是敌机图片的高度
    #1.子弹横坐标在敌机横坐标的区域中,并且子弹Y坐标小于敌机图片的高度
    #2.子弹最右侧坐标等于敌机最左侧坐标,并且子弹Y坐标小于敌机图片的高度
    #3.子弹最左侧坐标等于敌机最右侧坐标,并且子弹Y坐标小于敌机图片的高度
        if ((x1>=self.x and x2<=self.x+51) or x2==self.x or x1==self.x+51) and y<39:
            self.hit = True

    def display(self):  #显示敌机的方法
         #如果被击中,就显示爆炸效果,否则显示普通的飞机效果
        if self.hit == True:    #如果满足爆炸条件,就显示爆炸的图片
            self.screen.blit(self.bomb_lists[self.image_index], (self.x, self.y))
            self.image_num+=1   #这是统计循环次数,为了使玩家看清爆炸效果
            if self.image_num == 7: #如果循环次数达到7次
                self.image_num=0    #将循环次数改为0次
                self.image_index+=1 #图片显示序号+1,换为另一张图
            if self.image_index>3:  #这里爆炸图片一共是四张,所以是图片序号大于三次
                time.sleep(1)       #暂停一秒
                exit()  #调用exit让游戏退出
        else:   #否则显示正常的敌机图片
            self.screen.blit(self.image,(self.x, self.y))

    def move(self): #敌机移动方法
        if self.hit == True: 
            pass
        else:
            if self.direction=="right":     #如果是向右移动
                self.x += 5     #X坐标自增加5
            elif self.direction=="left":    #如果是向左移动
                self.x -= 5     #X坐标自减少5

            if self.x>480-50:   #如果X坐标大于窗口减去敌机宽度的值
                self.direction = "left" #移动方向改为左
            elif self.x<0:      #如果X坐标小于0
                self.direction = "right"    #移动方向改为右

#处理鼠标和键盘事件的方法
def key_control(aircraft_temp):

    #获取当前等待处理的事件,使用for循环来遍历里面的事件
    for event in pygame.event.get():
        #判断是否点击了退出按钮
        if event.type == QUIT:
            print("exit")   #输出“exit”
            exit()  #退出窗口
        #判断是不是键盘按下事件
        elif event.type == KEYDOWN:
            #检测按键是不是a或者left
            if event.key == K_a or event.key == K_LEFT:
                print('left')   #输出“left”
                aircraft_temp.move_left()   #执行飞机左移方法
            #检测按键是不是d或者right
            elif event.key == K_d or event.key == K_RIGHT:
                print('right')  #输出“right”
                aircraft_temp.move_right()  #执行飞机右移方法
            #检测按键是不是空格键
            elif event.key == K_SPACE:
                print('space')  #输出“space”
                aircraft_temp.fire()    #执行飞机类中存储子弹的方法

def main():
    #1. 创建窗口
    pygame.init()
    screen = pygame.display.set_mode((480,852),0,32)

    #2. 创建一个背景图片
    background = pygame.image.load("./images/background.png")

    #3. 创建一个飞机对象
    aircraft = Aircraft_obj(screen)

     #4. 创建一个敌机对象
    enemy = EnemyPlane(screen)

    while True:
        screen.blit(background, (0,0))  #把背景复制到窗口的0,0处开始贴进去
        aircraft.display()  #执行飞机类中显示飞机的方法

        for bullet in aircraft.bullet_list: #循环飞机对象中存储的子弹信息
            x1 = bullet.x       #子弹当前X坐标
            x2 = bullet.x + 22  #子弹当前X坐标+子弹图片的宽
            y1 = bullet.y       #子弹当前Y坐标
            enemy.blast(x1,x2,y1)    #判断子弹的坐标区域有没有与敌机相交

        enemy.display()     #执行敌机类中显示敌机的方法
        enemy.move()        #调用敌机的移动方法
        pygame.display.update() #更新需要显示的内容到窗口
        key_control(aircraft)   #处理飞机对象的相关事件
        time.sleep(0.01)    #暂停0.01秒

main()

图片资源

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年5月20日
下一篇 2023年5月20日

相关推荐