外星人

1.开发较大的项目时,进人每个开发阶段前回顾一下开发计划,搞清楚接下来要通过编写代码来完成哪些任务都是不错的主意。本章涉及以下内容。
2.研究既有代码,确定实现新功能前是否要进行重构。在屏幕左上角添加一个外星人,并指定合适的边距。
3.根据第一个外星人的边距和屏幕尺寸计算屏幕上可容纳多少个外星人。我们将编写一个循环来创建一系列外星人,这些外星人填满了屏幕的上半部分。
4.让外星人群向两边和下方移动,直到外星人被全部击落,有外星人撞到飞船,或有外星人抵达屏幕底端。如果整群外星人都被击落,我们将再创建一群外星人。如果有外星人撞到了飞船或抵达屏幕底端,我们将销毁飞船并再创建一群外星人。
5.限制玩家可用的飞船数量,配给的飞船用完后,游戏结束

修改退出模式

##game_function.py

import pygame
import sys
from bullet import bullet
...
def check_events_keydown(event, ship, settinge, screen, bullets):
	....
	##按下q退出
    elif event.key == pygame.K_q:
        sys.exit()

创建第一个外星人

创建alien类

这里的配置基本上与ship类和bullet类差不多

import pygame
from pygame.sprite import Sprite


class alien(Sprite):
    def __init__(self,screen,setting):
        super().__init__()
        self.screen = screen
		self.settings = setting
        ##设置外星人
        self.image = pygame.image.load('C:\\Users\\tanchang\Desktop\python\code\\alien\image\外星人.png')
        self.image = pygame.transform.scale(self.image,(30,40))
        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect()
        #外星人的位置 width也就是最左 height最右
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        ##外星人的精确位置
        self.x = float(self.rect.x)

    # def update(self):


    def prin_alien(self):
        """打印外星人"""
        self.screen.blit(self.image,self.rect)

创建alien实列

这里创建了外星人实列并在game_function.update_screen中创建了一个aliens实参

##alien_demo.py
from alien import alien


def run_game():
	....
    """创建一个外星人实列"""
    aliens = alien(screen,setting)
    """开始游戏的循环,这个游戏由一个循环语句来控制,死循环保证这个窗口一直再显示"""
    while True:
    	....
        game_functions.update_screen(ship_demo,settings, screen,bullets,aliens)

让外星人出现在屏幕上

##game_function.py
....
def update_screen(ship, settings, screen, bullets,alien):
	....
    ##打印飞船
    ship.print_ship()
	##打印外星人
    alien.prin_alien()


创建一群外星人

首先要确定一行可以容纳多少个外星人

##先看看可用空间多大,屏幕宽度存储在game_setting的setting类的width中
##屏幕两边还要留一些空白区域,那么可用用来显示的区域可用用这个公式表示

[可用区域] = 屏幕宽 - [2*外星人的宽]

##另外外星人和外星人之间也需要留空隔
##外星人和外星人之间留的空隔可用直接算在单个外星人上,可用直接用外星人的空间的两倍来表示,这样就可用算出可用去内可用显示多少个外星人了
[外星人数] = [可用区] / [2*外星人的宽]

创建一群外星人

在game_functions.py中添加创建多个外星人代码

##game_functions.py
....
from alien import Alien


def create_aliens(setting,screen,aliens):
    ##创建外星人实例
    alien = Alien(screen,setting)
    ##当个外星人的宽
    alien_width  = alien.rect.width
    #计算可用区 两边要留两个外星人的宽度所有*2
    available_zone = setting.width - (alien_width * 2 )
    #计算可用容纳多少个外星人 , 外星人中间还要空格就直接算一个外星人占的像素是两个外星人图像的宽度
    alines_quantity = int(available_zone / (2 * alien_width))
    print(alines_quantity,"个外星人")
    ##循环创建外星人
    for alien_num in range(alines_quantity):
        ##创建一个新的外星人
        alien = Alien(screen,setting)
        ##因为每个外星人都要先右推两个外星人位置所以就是 第一个外星人的宽 + 两个外星人的宽*第几个外星人
        alien.x = alien_width + 2 * alien_width * alien_num
        # print(alien.x)
        alien.rect.x = alien.x
        ###加入外星人编组
        aliens.add(alien)
....

def update_screen(ship, settings, screen, bullets,aliens):
	    ##打印外星人 对编组调用draw()时,Pygame自动绘制编组的每个元素,绘制位置由元素的属性rect决定。在这里,aliens.draw(screen)在屏幕上绘制编组中的每个外星人。
    aliens.draw(screen)
##alien_demo.py
....
from pygame.sprite import Group



def run_game():
	....
	"""创建一个外星人编组"""
    aliens = Group()

    """创建外星人群 ,因为没有什么可选条件,外星人的个数是不会变的所以可以直接先创建外星人组"""
    game_functions.create_aliens(settings,screen,aliens)
    """开始游戏的循环,这个游戏由一个循环语句来控制,死循环保证这个窗口一直再显示"""
    while True:
    	....
    	game_functions.bullet_update(bullets)
        ###game_functions.py update_screen()
        game_functions.update_screen(ship_demo,settings, screen,bullets,aliens)

重构create_alien

​ 可以看见create_alien函数,我们可以优化一下
​ 这里我是按照自己思维来重构的

##game_functions.py
....
from alien import Alien

def zone(setting,alien_width):
    #计算可用区 两边要留两个外星人的宽度所有*2
    available_zone = setting.width - (alien_width * 2 )
    #计算可用容纳多少个外星人 , 外星人中间还要空格就直接算一个外星人占的像素是两个外星人图像的宽度
    alines_quantity = int(available_zone / (2 * alien_width))
    return alines_quantity

def alien_add(setting,screen,aliens,alien_num,alien_width):
    """创建新的外星人并加入编组"""
    ##创建一个新的外星人
    alien = Alien(screen,setting)
    ##因为每个外星人都要先右推两个外星人位置所以就是 第一个外星人的宽 + 两个外星人的宽*第几个外星人
    alien.x = alien_width + 2 * alien_width * alien_num
    # print(alien.x)
    alien.rect.x = alien.x
    ###加入外星人编组
    aliens.add(alien)


def create_aliens(setting,screen,aliens):
    """汇总,创建外星人群"""
    ##创建一个外星人
    alien = Alien(screen,setting)
    alien_width = alien.rect.width
    ##循环创建外星人
    aliens_quantity = zone(setting,alien_width)
    for alien_num in range(aliens_quantity):
        alien_add(setting, screen, aliens, alien_num, alien_width)
    print(aliens)
.....

添加多行外星人

##要创建多行外星人就要看屏幕可以容纳多少行
##飞船和外星人之间还要留一些空格这些空格算2个外星人的高度
[可容纳区] = [屏幕高] - (2 * [外星人的高]) - [飞船的高] 

##还要计算可用容纳多少个,外星人行与行之间也需要空格
[可容纳多少个] = [可容纳区] / (2 * 外星人的高)
##game_functions.py
##上面的的create_aline那边我又优化了一下

....
from alien import Alien


def x_zone(setting, alien_width):
    # 计算可用区 两边要留两个外星人的宽度所有*2
    available_x_zone = setting.width - (alien_width * 2)
    # 计算可用容纳多少个外星人 , 外星人中间还要空格就直接算一个外星人占的像素是两个外星人图像的宽度
    alines_x_quantity = int(available_x_zone / (2 * alien_width))
    return alines_x_quantity


def y_zone(ship_height, setting, alien_height):
    ##计算y轴可用区 外星人和飞船要留3个外星人的长度
    available_y_zone = int(setting.high - (3 * alien_height) - ship_height)
    ##计算y轴可用区内可用容纳多少行外星人
    aliens_y_quantity = int(available_y_zone / (2 * alien_height))
    return aliens_y_quantity


def alien_add(setting, screen, aliens, alien_num, alien_num_rows):
    """创建新的外星人并加入编组"""
    ##创建一个新的外星人
    alien = Alien(screen,setting)
    alien_width = alien.rect.width
    alien_height = alien.rect.height
    ##因为每个外星人都要先右推两个外星人位置所以就是 第一个外星人的宽 + 两个外星人的宽*第几个外星人
    alien.x = alien_width + 2 * alien_width * alien_num
    ##每行外星人要向下推两个外星人的高度所以就 第一行外星人的高 + 两个外星人的高 * 第几个外星人
    alien.y = alien_height + 2 *  alien_height * alien_num_rows
    alien.rect.y = alien.y
    # print(alien.y)
    # print(alien.x)
    alien.rect.x = alien.x
    ###加入外星人编组
    aliens.add(alien)


def create_aliens(ship, setting, screen, aliens):
    """汇总,创建外星人群"""
    ##创建一个外星人
    alien = Alien(screen,setting)
    ##创建飞船实列
    ships = ship(screen, setting)
    ##循环创建外星人
    aliens_quantity = x_zone(setting, alien.rect.width, )
    alien_num_rows = y_zone(ships.rect.height, setting, alien.rect.height)
    # print(alien_num_rows)
    ##创建多行
    for alien_row in range(alien_num_rows):
        ##创建一行外星人
        for alien_num in range(aliens_quantity):
            alien_add(setting, screen, aliens, alien_num, alien_row)
.

13-2更逼真的星星:为让星星的分布更逼真,可随机地放置星星。本书前面说过,可像下面这样来生成随机数:

from random import randint
random_number = randint(-10,10)

上述代码返回一个-10和10之间的随机整数。在为完成练习13-1而编写的程序中,随机地调整每颗星星的位置。

##start_demo.py
import pygame
from start_setting import setting
import  start_function
from pygame.sprite import Group

def run_game():
    ##初始化游戏
    pygame.init()
    settings = setting()
    screen = pygame.display.set_mode((settings.display_width,settings.display_height))
    pygame.display.set_caption("一闪一闪亮晶晶,满天都是小卫平")
    starts = Group()
    ##创建小星星
    start_function.create_start(settings,starts)
    # starts = start(screen)
    while True:
        start_function.check_key()
        start_function.update_screen(starts,screen)




run_game()
##start_function.py
import pygame
import  sys
from class_start import Start
from random import randint

def check_keydown(event):
    if event.key == pygame.K_q:
        sys.exit()


def check_key():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown(event)


def create_start(setting,starts):
    start = Start()
    start_x = int(setting.display_width / (2 * start.rect.width))
    print(start_x)
    start_y = int(setting.display_height / (2 * start.rect.height))
    print(start_y)
    for num_y in range(start_y):
        for num_x in range(start_x):
            random_y = randint(0,setting.display_height)
            print('y:',random_y)
            random_x = randint(0,setting.display_width)
            print('x:',random_x)
            start = Start()
            start.rect.y = random_y
            start.rect.x = random_x
            starts.add(start)




def update_screen(starts,screen):
    pygame.display.flip()
    starts.draw(screen)
##start_setting.py
class setting:
    def __init__(self):
        self.display_width = 1300
        self.display_height = 600
##class_start.py
import  pygame
from  pygame.sprite import Sprite
from  random import randint


class Start(Sprite):
    def __init__(self):
        super(Start, self).__init__()
        # self.screen = screen
        self.image = pygame.image.load('C:\\Users\\tanchang\Desktop\python\code\\13章-1练习题\image\大脑壳.png')
        random_num = randint(20,50)
        self.image = pygame.transform.scale(self.image,(random_num,random_num))
        self.rect = self.image.get_rect()

让外星人移动

向右移动外星人

##game_setting.py
class alien_settings():
    """外星人游戏中的设置参数"""

    def __init__(self):
        ##外星人设置
        ##外星人移动速度
        self.alien_speed = 0.3
 ##alien.py
 ...
     def update(self):
        self.x += self.settings.alien_speed
        self.rect.x = self.x
##game_functions.py
def update_alien(aliens):
    """更新外星人的位置"""
    aliens.update()
##aline_demo.py
import pygame
from alien_setting_demo import alien_settings
from ship import ship
import game_functions
from pygame.sprite import Group



def run_game():
    ....
    while True:
        ....
        ##更新外星人位置
        game_functions.update_alien(aliens)

创建外星人移动方向的设置

​ 创建让外星人撞到屏幕右边缘后下移,在向左移动的设置。

##game_settings.py
class alien_settings():
    """外星人游戏中的设置参数"""

    def __init__(self):
    
    	##外星人设置
        self.alien_speed = 0.3
        ##外星人撞到屏幕边缘时向下移动速度
        self.aline_drop_speed = 3
        ##外星人移动方向 -1为向左1为向右
        self.aline_direction = -1

检查外星人是否撞到了边缘

##alien.py
....
class Alien(Sprite):
	....
    def check_edges(self):
        screen_rect = self.screen.get_rect()
        ##如果外星人位于屏幕边缘时就返回True
        if self.rect.right >= screen_rect.right:
            return True
        if self.rect.left <= 0:
            return True
        
    def update(self):
        ##如果在左边aline_direction就为-1 那么就是外星人的x坐标减去移动速度,也就是向左移动,如果是1那么就是外星人的x坐标加上移动速度,也就是下向右移动
        self.x += (self.settings.alien_speed * self.settings.aline_direction)
        self.rect.x = self.x

向下移动外星人并改变方向

##game_functions.py
from alien import Alien


def check_alien_edges(setting,aliens):
    ##遍历每个外星人位置
    for alien in aliens.sprites():
        ##如果在边缘就移动
        if alien.check_edges():
            check_alien_direction(setting,aliens)
            break

def check_alien_direction(setting,aliens):
    for alien in aliens.sprites():
        ##如果外星人在屏幕边缘就向下移动
        alien.rect.y += setting.aline_drop_speed
    ##因为外星人都先是向右移动的,aline_direction初始值就为1,这里*-1后变为-1变为-1就会向左移动,然后aline_direction的值就会变为-1第二次循环的时候就变为1了
    setting.aline_direction *= -1

def update_alien(setting,aliens):
    """更新外星人的位置"""
    ##检擦是否有外星人位于屏幕边缘,并更新整群外星人位置
    check_alien_edges(setting,aliens)
    aliens.update()
##alien_demo.py
from pygame.sprite import Group



def run_game():
	....
	    while True:
        ##game_fuctions
        game_functions.check_events(ship_demo,settings, screen,bullets)
        ##更新飞船位置
        ship_demo.update()
        game_functions.bullet_update(bullets)
        ##更新外星人位置
        game_functions.update_alien(settings,aliens)
        ##用于测试,测试好了之后可以把这条删除,如果你留下这条语句,你的运行效率会大大降低,因为输出到终端打印的时间比绘制图像的时间还要久
        # print(len(bullets))
        ###game_functions.py update_screen()
        game_functions.update_screen(ship_demo,settings, screen,bullets,aliens)

13-3雨滴:寻找一幅雨滴图像,并创建一系列整齐排列的雨滴。让这些雨滴往下落,直到到达屏幕底端后消失。

13-4连绵细雨:修改为完成练习13-3而编写的代码,使得一行雨滴消失在屏幕底端后,屏幕顶端又出现一行新雨滴,并开始往下落。

##man.py
import pygame
from raindrop_setting import settings
import raindrop_functions
from pygame.sprite import Group

def run_raindrop():
    pygame.init()
    setting = settings()
    screen = pygame.display.set_mode((setting.display_width,setting.display_height))
    pygame.display.set_caption("小雨滴")
    raindrops = Group()
    raindrop_functions.create_raindrop(screen,setting,raindrops)
    while True:
        raindrop_functions.check_event()
        raindrop_functions.update_raindrop(screen,raindrops,setting)
        raindrop_functions.update_screen(screen,setting,raindrops)


run_raindrop()


##raindrop.py
import pygame
from pygame.sprite import Sprite

class raindrop(Sprite):
    def __init__(self,screen,setting):
        super(raindrop, self).__init__()
        self.screen = screen
        self.setting = setting
        self.image = pygame.image.load('C:\\Users\\tanchang\Desktop\python\code\\13练习2\image\雨滴.png')
        # self.image= pygame.transform.scale(self.image,(30,40))
        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect()
        self.rect.x = self.rect.width
        self.rect.y = self.screen_rect.top
    #
    def update(self):
        self.rect.y += self.setting.raindrop_speed
        print(self.rect.y)
##raindrop_functions.py
import sys
import pygame
from raindrop import raindrop


def x_raindorp(setting, raindorp):
    raindorp_zone = int(setting.display_width - (raindorp.rect.x * 2))
    raindorp_num = int(raindorp_zone / raindorp.rect.x)
    return raindorp_num


def raindorp_add(screen, setting, raindrops, r_num):
    raindrop1 = raindrop(screen, setting)
    raindrop_width = raindrop1.rect.width
    raindrop1.x = raindrop_width + raindrop_width * r_num
    raindrop1.rect.x = raindrop1.x
    raindrops.add(raindrop1)


def create_raindrop(screen, setting, raindrops):
    raindrop1 = raindrop(screen, setting)
    raindorp_num = x_raindorp(setting, raindrop1)
    for r_num in range(raindorp_num):
        raindorp_add(screen, setting, raindrops, r_num)


def update_raindrop(screen, raindrop, setting):
    raindrop.update()
    for rain_1 in raindrop.copy():
        if rain_1.rect.top >= setting.display_width:
            raindrop.remove(rain_1)
    if len(raindrop) == 0:
        create_raindrop(screen, setting,raindrop)
        print(len(raindrop))


def check_event():
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()


def update_screen(screen, setting, raindrop):
    screen.fill(setting.bg_color)
    raindrop.draw(screen)
    pygame.display.flip()
##raindrop_setting.py
class settings:
    def __init__(self):
        self.display_width = 1200
        self.display_height = 600
        self.bg_color = (0, 0, 0)
        self.raindrop_speed = 1

射杀外星人

在游戏编程中碰撞是指游戏元素重叠在一起,我们将使用sprite.groupcollide()来检查两个编组的成员是否碰撞

检测外星人与子弹的碰撞

##game_funtions.py
import pygame
def bullet_update(bullets,aliens):
	"""检测外星人和子弹是否碰撞,如果碰撞的话就都消失"""
    """pygame.sprite.groupcollide(形参,形参,是否消失,是否消失),他会遍历bullets编组中的每个子弹和aliens编组中的每个外星人,检测它们是否碰撞"""
    
    collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
##alien_demo.py
    while True:
            game_functions.update_alien(settings,aliens)

现在就可以击落外星人了

修改配置

可以自己试着修改配置然后再去测试游戏可以让游戏玩的更爽

生成新的外星人群

​ 游戏特点是外星人无穷无尽,击落一批外星人后又会生成新的外星人
​ 我们可以先检测aliens编组如果编组为空就在调用create_aliens,在到update_alines中调用,因为外星人都是在这里被消灭的

##game_funtions.py
...
def bullet_update(ship, setting, screen,bullets,aliens):
	...
    if len(aliens) == 0:
        ##清空所有子弹
        bullets.empty()
        ##如果外星人                                                   ##创建新的外星人群                     
        create_aliens(ship, setting, screen, aliens)
##aline_demo.py
def run_game():	
    while True:
		game_functions.bullet_update(ship, settings ,screen,bullets, aliens)

重构bullet_update()

刚刚是吧消失子弹和碰撞和创建新外星人放在一个方法里面,这里我可用把它们划分为多个方法

def bullet_update(ship, setting, screen, bullets, aliens):
    ##子弹向上移动,bullets.py
    bullets.update()
    bullet_disappear(bullets)
    collision_disappear(bullets,aliens)
    check_aliens_disappear(screen,setting,ship,bullets,aliens)
    
##让超过屏幕的子弹消失
def bullet_disappear(bullets):
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)


##碰撞消失
def collision_disappear(bullets,aliens):
    """检测外星人和子弹是否碰撞,如果碰撞的话就都消失"""
    """pygame.sprite.groupcollide(形参,形参,是否消失,是否消失),他会遍历bullets编组中的每个子弹和aliens编组中的每个外星人,检测它们是否碰撞"""
    collisions = pygame.sprite.groupcollide(bullets, aliens, False, True)

##检测编组外星人是否没有了,如果没有了就新建
def check_aliens_disappear(screen,setting,ship,bullets,aliens):
    if len(aliens) == 0:
        bullets.empty()
        create_aliens(ship, setting, screen, aliens)

13-5抓球:创建一个游戏,在屏幕底端放置一个玩家可左右移动的角色。让一个球出现在屏幕顶端,且水平位置是随机的,并让这个球以固定的速度往下落。如果角色与球发生碰撞(表示将球抓住了),就让球消失。每当角色抓住球或球因抵达屏幕底端而消失后,都创建一个新球。


结束游戏

​ 设置一些挑战
​ 如果玩家根本不会输,游戏还有什么趣味和挑战性可言?如果玩家没能在足够短的时间内将整群外星人都消灭干净,且有外星人撞到了飞船,飞船将被摧毁。与此同时,我们还限制了可供玩家使用的飞船数,而有外星人抵达屏幕底端时,飞船也将被摧毁。玩家用光了飞船后,游戏便结束。

检测外星人和飞船碰撞

##game_functions.py
##检测飞船是否和外星人碰撞
def aline_ship_collision(ships,aliens):
    ##如果外星人和飞船没有碰撞那么spritecollideany返回none,如果碰撞了就返回这个外星人,然后if语句就会执行
    if pygame.sprite.spritecollideany(ships, aliens):
        print('飞船损坏掉了!!!')

##更新外星人位置
def update_alien(screen, setting, ships, bullet, aliens):
    ....
    aline_ship_collision(screen,ships,bullet,aliens,setting)

响应外星人和飞船的碰撞

​ 现在需要确定外星人与飞船发生碰撞时,该做些什么。我们不销毁ship实例并创建一个新的ship实例,而是通过跟踪游戏的统计信息来记录飞船被撞了多少次(跟踪统计信息还有助于记分)。
​ 我们创建一个用于跟踪游戏统计信息的类

##game_stats.py
class Gamestats:
    def __init__(self,settings):
        self.settings = settings
        self.reset_stats()

    def reset_stats(self):
        """初始化在游戏中可能变化的信息系统"""
        self.ship_left = self.settings.ship_num
##game_settings
class alien_settings():
    """外星人游戏中的设置参数"""

    def __init__(self):
    	...
    	##飞船数量
    	self.ship_num = 3
##game_functions.py
##外星人和飞船碰撞后
def alien_ship_later(screen,setting,ships, bullet, aliens):
    ##飞船数减一
    setting.ship_num -= 1
    #清空外星人
    bullet.empty()
    #亲空子弹
    aliens.empty()
    ##创建新的外星人
    create_aliens(setting,screen,aliens)
    ##当飞船损坏后,创建新的飞船并把飞船放到中间
    ships.center_ship()
    sleep(0.5)

    
    

##检测飞船是否和外星人碰撞
def aline_ship_collision(screen,ships, bullet, aliens,setting):
    ##如果外星人和飞船没有碰撞那么spritecollideany返回none,如果碰撞了就返回这个外星人,然后if语句就会执行
    if pygame.sprite.spritecollideany(ships, aliens):
        alien_ship_later(screen,setting,ships,bullet,aliens)
        print('飞船损坏掉了!!!')

##更新外星人位置
def update_alien(screen, setting, ships, bullet, aliens):
	....    		
	aline_ship_collision(screen,ships,bullet,aliens,setting)
##ship.py
import pygame


class ship:
	....
    def center_ship(self):
        self.center=self.screen_rect.centerx

检查外星人是否到达屏幕底端

##game_functions.py
def aline_ship_collision(screen,ships, bullet, aliens,setting):
	....
	alines_screen_bottom(screen, setting, ships, bullet, aliens)

def alines_screen_bottom(screen, setting, ships, bullet, aliens):
    ##获取屏幕矩形
    screen_rect = screen.get_rect()
    ##遍历aliens编组
    for alien in aliens.sprites():
        ##判断外星人是否在屏幕最低端
        if alien.rect.bottom >= screen_rect.bottom:
            ##是就执行外星人碰撞后的操作
            alien_ship_later(screen,setting,ships,bullet,aliens)

游戏结束

##game_stat.py
class Gamestats:
    def __init__(self, settings):
    ....
            #游戏开始状态是运行中
        self.game_status_ing = True
##game_functions.py
##外星人和飞船碰撞后
def alien_ship_later(screen, setting, ships, bullet, aliens, gamestat):
    ##飞船数减一
    setting.ship_num -= 1
    ##如果还有飞船就继续游戏
    if setting.ship_num >= 0:
        print(setting.ship_num)
        # 清空外星人
        bullet.empty()
        # 亲空子弹
        aliens.empty()
        ##创建新的外星人
        create_aliens(setting, screen, aliens)
        ##当飞船损坏后,创建新的飞船并把飞船放到中间
        ships.center_ship()
        sleep(0.5)
    ##如果飞船没有了就结束游戏
    else:
        gamestat.game_status_ing = False
        print('游戏结束!!')
##alien_demo.py
   	"""开始游戏的循环,这个游戏由一个循环语句来控制,死循环保证这个窗口一直再显示"""
    while True:
        ##game_fuctions
        game_functions.check_events(ship_demo, settings, screen, bullets)
        ##游戏运行中调用哪些函数
        if gamestat.game_status_ing:
            ##更新飞船位置-
            ship_demo.update()
            game_functions.bullet_update(settings, screen, bullets, aliens)
            ##更新外星人位置
            game_functions.update_alien(screen, settings, ship_demo, bullets, aliens, gamestat)
            ##用于测试,测试好了之后可以把这条删除,如果你留下这条语句,你的运行效率会大 大降低,因为输出到终端打印的时间比绘制图像的时间还要久
            # print(len(bullets))
            ###game_functions.py update_screen()
        game_functions.update_screen(ship_demo, settings, screen, bullets, aliens)

在主循环中,在任何情况下都需要调用check_events(),即便游戏处于非活动状态时亦如此。例如,我们需要知道玩家是否按了Q键以退出游戏,或单击关闭窗口的按钮。我们还需要不断更新屏幕,以便在等待玩家是否选择开始新游戏时能够修改屏幕。其他的函数仅在游戏处于活动状态时才需要调用,因为游戏处于非活动状态时,我们不用更新游戏元素的位置。