欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python代码实践编程“武装飞船”

程序员文章站 2023-11-24 11:58:40
这里写目录标题12.3 开始游戏项目12.3.1 创建pygame窗口以及响应用户输入12.3.2 设置背景颜色12.3.3 创建设置类12.3 开始游戏项目12.3.1 创建pygame窗口以及响应用户输入import sysimport pygamedef run_game(): # 初始化游戏并创建一个屏幕对象 pygame.init() # 初始化背景设置 # 创建宽1200像素,高800像素的游戏窗口 #对象screen是个surface,在pyg...






12.3 开始游戏项目

12.3.1 创建pygame窗口以及响应用户输入

alien_invision.py

import sys    #需要这个模块退出游戏  #sysy.exit()退出游戏

import pygame   #需要这个模块开发游戏有需要的功能

def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    #对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    #在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    #display.set_mode()返回的surface表示整个游戏窗口。
    screen = pygame.display.set_mode((1200, 750))   #里面的宽高可以调整
    pygame.display.set_caption("外星人入侵")

    # 开始游戏的主循环
    while True:

        # 监视键盘和鼠标事件
        #方法pygame.event.get()访问pygame检测到的事件
        #所有键盘和鼠标事件都将促使for循环运行
        for event in pygame.event.get():
            #在循环中,编写一系列if语句检测并相应特定的事件。
            if event.type == pygame.QUIT:
                sys.exit()  # 退出游戏

        # 让最近绘制的屏幕可见
        #在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
        pygame.display.flip()


run_game()

python代码实践编程“武装飞船”


12.3.2 设置背景颜色

alien_invision.py

import sys    #需要这个模块退出游戏  #sysy.exit()退出游戏

import pygame   #需要这个模块开发游戏有需要的功能

def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    #对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    #在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    #display.set_mode()返回的surface表示整个游戏窗口。
    screen = pygame.display.set_mode((1200, 750))   #里面的宽高可以调整
    pygame.display.set_caption("外星人入侵")

    #设置背景颜色,RGB颜色组合
    bg_color = (230, 230, 230)

    # 开始游戏的主循环
    while True:

        # 监视键盘和鼠标事件
        #方法pygame.event.get()访问pygame检测到的事件
        #所有键盘和鼠标事件都将促使for循环运行
        for event in pygame.event.get():
            #在循环中,编写一系列if语句检测并相应特定的事件。
            if event.type == pygame.QUIT:
                sys.exit()  # 退出游戏

        #每次循环时都重绘屏幕
        #调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
        screen.fill(bg_color)    #设置背景颜色

        # 让最近绘制的屏幕可见
        #在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
        pygame.display.flip()


run_game()

python代码实践编程“武装飞船”


12.3.3 创建设置类

alien_invision.py

import sys    #需要这个模块退出游戏  #sysy.exit()退出游戏

import pygame   #需要这个模块开发游戏有需要的功能

from settings import Settings   #导入settings模块中Settings类

def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    #对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    #在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    #display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    #创建实例
    #使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))
    pygame.display.set_caption("外星人入侵")



    # 开始游戏的主循环
    while True:

        # 监视键盘和鼠标事件
        #方法pygame.event.get()访问pygame检测到的事件
        #所有键盘和鼠标事件都将促使for循环运行
        for event in pygame.event.get():
            #在循环中,编写一系列if语句检测并相应特定的事件。
            if event.type == pygame.QUIT:
                sys.exit()  # 退出游戏

        #每次循环时都重绘屏幕
        #调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
        screen.fill(ai_settings.bg_color)    #设置背景颜色,使用ai_settings中的属性bg_color

        # 让最近绘制的屏幕可见
        #在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
        pygame.display.flip()


run_game()

settings.py

class Settings():
    """存储《外星人入侵》的所有设置的类"""
    
    def __init__(self):
        """初始化游戏的设置"""
        #屏幕设置
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)





12.4 添加飞船图像

在Python中,原点(0,0)位于屏幕的左上角,向右下角移动时,坐标值将增大。
在1200×800的屏幕上,原点在左上角,坐标(1200,800)在右下角。

12.4.1 创建Ship类

ship.py

import pygame

class Ship():
    # 方法__init__接受两个参数,screen是需要外部输入的参数
    def __init__(self, screen):
        """初始化飞船并设置其初始化位置"""
        self.screen = screen   #外来参数screen赋值给属性

        #加载飞船图像并获取其外接矩形
        #pygame.image.load()加载图片,存储在self.image
        self.image = pygame.image.load('images/ship.bmp')
        #get_rect()获取相应surface的属性rect
        self.rect = self.image.get_rect()      #飞机所在的矩形
        #将表示屏幕的矩形存储在self.screen_rect中
        self.screen_rect = screen.get_rect()   #整个屏幕的矩形

        #将每艘新飞船放在屏幕底部*
        #将self.rect.centerx(飞船中心的x坐标)设置为表示屏幕的矩形的属性centerx
        self.rect.centerx = self.screen_rect.centerx    #设置飞机所在矩形到*
        #将self.rect.bottom(飞船下边缘的y坐标)设置为表示屏幕的矩形的属性bottom
        self.rect.bottom = self.screen_rect.bottom      #设置飞机所在矩形到底部

    # 定义blitme()方法,它根据self.rect指定的位置将图像绘制到屏幕上
    def blitme(self):
        """在指定位置绘制飞船"""
        self.screen.blit(self.image, self.rect)    #两个参数,飞机图片、飞机所在的矩形



12.4.2 在屏幕上绘制飞船

alien_invision.py

import sys    #需要这个模块退出游戏  #sysy.exit()退出游戏

import pygame   #需要这个模块开发游戏有需要的功能

from settings import Settings   #导入settings模块中Settings类
from ship import Ship           #导入ship模块中Ship类


def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    #对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    #在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    #display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    #创建实例
    #使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  #赋值给screen
    pygame.display.set_caption("外星人入侵")

    #创建一艘飞船
    ship = Ship(screen)    #创建名为ship的Ship实例,实参为前面的screen

    # 开始游戏的主循环
    while True:

        # 监视键盘和鼠标事件
        #方法pygame.event.get()访问pygame检测到的事件
        #所有键盘和鼠标事件都将促使for循环运行
        for event in pygame.event.get():
            #在循环中,编写一系列if语句检测并相应特定的事件。
            if event.type == pygame.QUIT:
                sys.exit()  # 退出游戏

        #每次循环时都重绘屏幕
        #调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
        screen.fill(ai_settings.bg_color)   #设置背景颜色,使用ai_settings中的属性bg_color
        ship.blitme()   #调用,创建实例

        # 让最近绘制的屏幕可见
        #在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
        pygame.display.flip()


run_game()

python代码实践编程“武装飞船”




12.5 重构:模块game_functions

旨在简化既有代码的结构,使其更容易扩展。
实际的开发过程,一开始将代码编写的尽可能简单,并在项目越来越复杂时进行重构。

12.5.1 函数check_events()

game_functions.py

import sys

import pygame

def check_events():
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

alien_invision.py

import pygame   #需要这个模块开发游戏有需要的功能

from settings import Settings   #导入settings模块中Settings类
from ship import Ship           #导入ship模块中Ship类
import game_functions as gf     #导入game_functions模块,模块另命名为gf



def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    #对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    #在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    #display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    #创建实例
    #使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  #赋值给screen
    pygame.display.set_caption("外星人入侵")

    #创建一艘飞船
    ship = Ship(screen)    #创建名为ship的Ship实例,实参为前面的screen

    # 开始游戏的主循环
    while True:
        gf.check_events()     #调用gf模块中的方法check_events()

        #每次循环时都重绘屏幕
        #调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
        screen.fill(ai_settings.bg_color)   #设置背景颜色,使用ai_settings中的属性bg_color
        ship.blitme()   #调用,创建实例

        # 让最近绘制的屏幕可见
        #在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
        pygame.display.flip()


run_game()



12.5.2 函数update_screen()

game_functions.py

import sys

import pygame

def check_events():
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

def update_screen(ai_settings, screen, ship):   #三个参数
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    # 调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
    # 设置背景颜色,使用ai_settings中的属性bg_color,在settings模块内
    screen.fill(ai_settings.bg_color)
    # ship为Ship实例,实例的创建在主模块中
    ship.blitme()  # 调用,创建实例

    # 让最近绘制的屏幕可见
    # 在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
    pygame.display.flip()

alien_invision.py

import pygame   #需要这个模块开发游戏有需要的功能

from settings import Settings   #导入settings模块中Settings类
from ship import Ship           #导入ship模块中Ship类
import game_functions as gf     #导入game_functions模块,模块另命名为gf



def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    #对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    #在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    #display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    #创建实例
    #使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  #赋值给screen
    pygame.display.set_caption("外星人入侵")

    #创建一艘飞船
    ship = Ship(screen)    #创建名为ship的Ship实例,实参为前面的screen

    # 开始游戏的主循环
    while True:
        gf.check_events()     #调用gf模块中的方法check_events()
        # 调用gf模块中的方法update_screen(),三个参数
        gf.update_screen(ai_settings, screen, ship)

run_game()





12.6 驾驶飞船

1、左右移动飞船,按左键或右键能及时作出响应
2、首先专注于向右移动,用同样的原理控制向左

12.6.1 响应按键

game_functions.py

import sys

import pygame

def check_events(ship):   #加了ship参数
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

        elif event.type == pygame.KEYDOWN:   #每次按键都被注册为一个KEYDOWN事件
            if event.key == pygame.K_RIGHT:  #如果按下的是右键
                # 向右移动飞船
                ship.rect.centerx += 1       #x坐标加1



def update_screen(ai_settings, screen, ship):   #三个参数
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    # 调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
    # 设置背景颜色,使用ai_settings中的属性bg_color,在settings模块内
    screen.fill(ai_settings.bg_color)
    # ship为Ship实例,实例的创建在主模块中
    ship.blitme()  # 调用,创建实例

    # 让最近绘制的屏幕可见
    # 在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
    pygame.display.flip()

alien_invision.py

import pygame   #需要这个模块开发游戏有需要的功能

from settings import Settings   #导入settings模块中Settings类
from ship import Ship           #导入ship模块中Ship类
import game_functions as gf     #导入game_functions模块,模块另命名为gf



def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    #对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    #在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    #display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    #创建实例
    #使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  #赋值给screen
    pygame.display.set_caption("外星人入侵")

    #创建一艘飞船
    ship = Ship(screen)    #创建名为ship的Ship实例,实参为前面的screen

    # 开始游戏的主循环
    while True:
        gf.check_events(ship)     #调用gf模块中的方法check_events(),ship为飞船
        # 调用gf模块中的方法update_screen(),三个参数
        gf.update_screen(ai_settings, screen, ship)

run_game()



12.6.2 允许不断移动

1、按住右键不放能不断移动

ship.py

import pygame

class Ship():
    # 方法__init__接受两个参数,screen是需要外部输入的参数
    def __init__(self, screen):
        """初始化飞船并设置其初始化位置"""
        self.screen = screen   #外来参数screen赋值给属性

        #加载飞船图像并获取其外接矩形
        #pygame.image.load()加载图片,存储在self.image
        self.image = pygame.image.load('images/ship.bmp')
        #get_rect()获取相应surface的属性rect
        self.rect = self.image.get_rect()      #飞机所在的矩形
        #将表示屏幕的矩形存储在self.screen_rect中
        self.screen_rect = screen.get_rect()   #整个屏幕的矩形

        #将每艘新飞船放在屏幕底部*
        #将self.rect.centerx(飞船中心的x坐标)设置为表示屏幕的矩形的属性centerx
        self.rect.centerx = self.screen_rect.centerx    #设置飞机所在矩形到*
        #将self.rect.bottom(飞船下边缘的y坐标)设置为表示屏幕的矩形的属性bottom
        self.rect.bottom = self.screen_rect.bottom      #设置飞机所在矩形到底部

        #移动标志
        self.moving_right = False    #添加属性self.moving_right,初始值设置为False

    def update(self):
        """根据移动标志调整飞船的位置"""
        if self.moving_right:        #为True时
            self.rect.centerx += 1

    # 定义blitme()方法,它根据self.rect指定的位置将图像绘制到屏幕上
    def blitme(self):
        """在指定位置绘制飞船"""
        self.screen.blit(self.image, self.rect)    #两个参数,飞机图片、飞机所在的矩形

game_functions.py

import sys

import pygame

def check_events(ship):   #加了ship参数
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

        # 每次按键都被注册为一个KEYDOWN事件
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:  #如果按下的是右键,按下一直为True
                # 向右移动飞船
                ship.moving_right = True     #x坐标加1,ship在主函数实例,最终在ship.py

        elif event.type == pygame.KEYUP:     #松下
            if event.key == pygame.K_RIGHT:
                ship.moving_right = False



def update_screen(ai_settings, screen, ship):   #三个参数
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    # 调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
    # 设置背景颜色,使用ai_settings中的属性bg_color,在settings模块内
    screen.fill(ai_settings.bg_color)
    # ship为Ship实例,实例的创建在主模块中
    ship.blitme()  # 调用,创建实例

    # 让最近绘制的屏幕可见
    # 在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
    pygame.display.flip()

alien_invision.py

import pygame   #需要这个模块开发游戏有需要的功能

from settings import Settings   #导入settings模块中Settings类
from ship import Ship           #导入ship模块中Ship类
import game_functions as gf     #导入game_functions模块,模块另命名为gf



def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    #对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    #在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    #display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    #创建实例
    #使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  #赋值给screen
    pygame.display.set_caption("外星人入侵")

    #创建一艘飞船
    ship = Ship(screen)    #创建名为ship的Ship实例,实参为前面的screen

    # 开始游戏的主循环
    while True:
        gf.check_events(ship)     #调用gf模块中的方法check_events(),ship为飞船
        ship.update()
        # 调用gf模块中的方法update_screen(),三个参数
        gf.update_screen(ai_settings, screen, ship)

run_game()



12.6.3 左右移动

ship.py

import pygame

class Ship():
    # 方法__init__接受两个参数,screen是需要外部输入的参数
    def __init__(self, screen):
        """初始化飞船并设置其初始化位置"""
        self.screen = screen   # 外来参数screen赋值给属性

        # 加载飞船图像并获取其外接矩形
        # pygame.image.load()加载图片,存储在self.image
        self.image = pygame.image.load('images/ship.bmp')
        # get_rect()获取相应surface的属性rect
        self.rect = self.image.get_rect()      # 飞机所在的矩形
        # 将表示屏幕的矩形存储在self.screen_rect中
        self.screen_rect = screen.get_rect()   # 整个屏幕的矩形

        # 将每艘新飞船放在屏幕底部*
        # 将self.rect.centerx(飞船中心的x坐标)设置为表示屏幕的矩形的属性centerx
        self.rect.centerx = self.screen_rect.centerx    # 设置飞机所在矩形到*
        # 将self.rect.bottom(飞船下边缘的y坐标)设置为表示屏幕的矩形的属性bottom
        self.rect.bottom = self.screen_rect.bottom      # 设置飞机所在矩形到底部

        # 移动标志
        self.moving_right = False    # 添加属性self.moving_right,初始值设置为False
        self.moving_left = False

    def update(self):
        """根据移动标志调整飞船的位置"""
        if self.moving_right:        # 为True时
            self.rect.centerx += 1
        if self.moving_left:         # 为True时
            self.rect.centerx -= 1

    # 定义blitme()方法,它根据self.rect指定的位置将图像绘制到屏幕上
    def blitme(self):
        """在指定位置绘制飞船"""
        self.screen.blit(self.image, self.rect)    # 两个参数,飞机图片、飞机所在的矩形

game_functions.py

import sys

import pygame

def check_events(ship):   # 加了ship参数
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

        # 每次按键都被注册为一个KEYDOWN事件
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:    # 如果按下的是右键,按下一直为True
                # 向右移动飞船
                ship.moving_right = True       # x坐标加1,ship在主函数实例,最终在ship.py
            elif event.key == pygame.K_LEFT:   # 按下左键
                ship.moving_left = True

        elif event.type == pygame.KEYUP:       # 松下
            if event.key == pygame.K_RIGHT:    # 松下右键
                ship.moving_right = False
            elif event.key == pygame.K_LEFT:   # 松下左键
                ship.moving_left = False



def update_screen(ai_settings, screen, ship):   # 三个参数
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    # 调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
    # 设置背景颜色,使用ai_settings中的属性bg_color,在settings模块内
    screen.fill(ai_settings.bg_color)
    # ship为Ship实例,实例的创建在主模块中
    ship.blitme()  # 调用,创建实例

    # 让最近绘制的屏幕可见
    # 在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
    pygame.display.flip()

alien_invision.py

import pygame   # 需要这个模块开发游戏有需要的功能

from settings import Settings   # 导入settings模块中Settings类
from ship import Ship           # 导入ship模块中Ship类
import game_functions as gf     # 导入game_functions模块,模块另命名为gf



def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    # 对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    # 在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    # display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    # 创建实例
    # 使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  # 赋值给screen
    pygame.display.set_caption("外星人入侵")

    # 创建一艘飞船
    ship = Ship(screen)    # 创建名为ship的Ship实例,实参为前面的screen

    # 开始游戏的主循环
    while True:
        gf.check_events(ship)     # 调用gf模块中的方法check_events(),ship为飞船
        ship.update()
        # 调用gf模块中的方法update_screen(),三个参数
        gf.update_screen(ai_settings, screen, ship)

run_game()



12.6.4 调整飞船的速度

每次执行while循环时,飞船最多移动1像素,这里设置成1.5
settings.py

class Settings():
    """存储《外星人入侵》的所有设置的类"""
    
    def __init__(self):
        """初始化游戏的设置"""
        # 屏幕设置
        self.screen_width = 1200
        self.screen_height = 750
        self.bg_color = (230, 230, 230)

        #飞船的速度
        self.ship_speed_factor = 1.5

ship.py

import pygame

class Ship():
    # 方法__init__接受两个参数,screen是需要外部输入的参数
    def __init__(self, ai_settings, screen):
        """初始化飞船并设置其初始化位置"""
        self.screen = screen   # 外来参数screen赋值给属性
        self.ai_settings = ai_settings   #获得速度设置

        # 加载飞船图像并获取其外接矩形
        # pygame.image.load()加载图片,存储在self.image
        self.image = pygame.image.load('images/ship.bmp')
        # get_rect()获取相应surface的属性rect
        self.rect = self.image.get_rect()      # 飞机所在的矩形
        # 将表示屏幕的矩形存储在self.screen_rect中
        self.screen_rect = screen.get_rect()   # 整个屏幕的矩形

        # 将每艘新飞船放在屏幕底部*
        # 将self.rect.centerx(飞船中心的x坐标)设置为表示屏幕的矩形的属性centerx
        self.rect.centerx = self.screen_rect.centerx    # 设置飞机所在矩形到*
        # 将self.rect.bottom(飞船下边缘的y坐标)设置为表示屏幕的矩形的属性bottom
        self.rect.bottom = self.screen_rect.bottom      # 设置飞机所在矩形到底部

        # 在飞船的属性center中存储小数值
        self.center = float(self.rect.centerx)       #转化为小数

        # 移动标志
        self.moving_right = False    # 添加属性self.moving_right,初始值设置为False
        self.moving_left = False

    def update(self):
        """根据移动标志调整飞船的位置"""
        # 更新飞船的center值,而不是rect
        if self.moving_right:        # 为True时
            self.center += self.ai_settings.ship_speed_factor
        if self.moving_left:         # 为True时
            self.center -= self.ai_settings.ship_speed_factor

        #根据self.center更新rect对象
        self.rect.centerx = self.center

    # 定义blitme()方法,它根据self.rect指定的位置将图像绘制到屏幕上
    def blitme(self):
        """在指定位置绘制飞船"""
        self.screen.blit(self.image, self.rect)    # 两个参数,飞机图片、飞机所在的矩形

alien_invision.py

import pygame   # 需要这个模块开发游戏有需要的功能

from settings import Settings   # 导入settings模块中Settings类
from ship import Ship           # 导入ship模块中Ship类
import game_functions as gf     # 导入game_functions模块,模块另命名为gf



def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置
    # 创建宽1200像素,高800像素的游戏窗口
    # 对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    # 在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    # display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    # 创建实例
    # 使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  # 赋值给screen
    pygame.display.set_caption("外星人入侵")

    # 创建一艘飞船
    ship = Ship(ai_settings, screen)    # 创建名为ship的Ship实例,实参为前面的screen

    # 开始游戏的主循环
    while True:
        gf.check_events(ship)     # 调用gf模块中的方法check_events(),ship为飞船
        ship.update()
        # 调用gf模块中的方法update_screen(),三个参数
        gf.update_screen(ai_settings, screen, ship)

run_game()



12.6.5 限制飞船的活动范围

玩家按住箭头键的时间朱够长,飞船会到屏幕外面,这里修复这个问题
ship.py

import pygame

class Ship():
    # 方法__init__接受两个参数,screen是需要外部输入的参数
    def __init__(self, ai_settings, screen):
        """初始化飞船并设置其初始化位置"""
        self.screen = screen   # 外来参数screen赋值给属性
        self.ai_settings = ai_settings   #获得速度设置

        # 加载飞船图像并获取其外接矩形
        # pygame.image.load()加载图片,存储在self.image
        self.image = pygame.image.load('images/ship.bmp')
        # get_rect()获取相应surface的属性rect
        self.rect = self.image.get_rect()      # 飞机所在的矩形
        # 将表示屏幕的矩形存储在self.screen_rect中
        self.screen_rect = screen.get_rect()   # 整个屏幕的矩形

        # 将每艘新飞船放在屏幕底部*
        # 将self.rect.centerx(飞船中心的x坐标)设置为表示屏幕的矩形的属性centerx
        self.rect.centerx = self.screen_rect.centerx    # 设置飞机所在矩形到*
        # 将self.rect.bottom(飞船下边缘的y坐标)设置为表示屏幕的矩形的属性bottom
        self.rect.bottom = self.screen_rect.bottom      # 设置飞机所在矩形到底部

        # 在飞船的属性center中存储小数值
        self.center = float(self.rect.centerx)       #转化为小数

        # 移动标志
        self.moving_right = False    # 添加属性self.moving_right,初始值设置为False
        self.moving_left = False

    def update(self):
        """根据移动标志调整飞船的位置"""
        # 更新飞船的center值,而不是rect
        if self.moving_right and self.rect.right < self.screen_rect.right:        # 为True时
            self.center += self.ai_settings.ship_speed_factor
        if self.moving_left and self.rect.left > 0:         # 为True时
            self.center -= self.ai_settings.ship_speed_factor

        #根据self.center更新rect对象
        self.rect.centerx = self.center

    # 定义blitme()方法,它根据self.rect指定的位置将图像绘制到屏幕上
    def blitme(self):
        """在指定位置绘制飞船"""
        self.screen.blit(self.image, self.rect)    # 两个参数,飞机图片、飞机所在的矩形



12.6.6重构check_events()

函数check_events越来越长,重构,拆出两个
game.functions.py

import sys

import pygame

def check_keydown_events(event, ship):
    """响应按键"""
    if event.key == pygame.K_RIGHT:  # 如果按下的是右键,按下一直为True
        # 向右移动飞船
        ship.moving_right = True  # x坐标加1,ship在主函数实例,最终在ship.py
    elif event.key == pygame.K_LEFT:  # 按下左键
        ship.moving_left = True

def check_keyup_events(event, ship):
    "响应松开"
    if event.key == pygame.K_RIGHT:  # 松下右键
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:  # 松下左键
        ship.moving_left = False

def check_events(ship):   # 加了ship参数
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

        # 每次按键都被注册为一个KEYDOWN事件
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ship)    #调用了上面的

        elif event.type == pygame.KEYUP:       # 松下
            check_keyup_events(event, ship)      #调用了上面的




def update_screen(ai_settings, screen, ship):   # 三个参数
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    # 调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
    # 设置背景颜色,使用ai_settings中的属性bg_color,在settings模块内
    screen.fill(ai_settings.bg_color)
    # ship为Ship实例,实例的创建在主模块中
    ship.blitme()  # 调用,创建实例

    # 让最近绘制的屏幕可见
    # 在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
    pygame.display.flip()





12.8 射击

12.8.1 添加子弹设置

settings.py

class Settings():
    """存储《外星人入侵》的所有设置的类"""
    
    def __init__(self):
        """初始化游戏的设置"""
        # 屏幕设置
        self.screen_width = 1200
        self.screen_height = 750
        self.bg_color = (230, 230, 230)
        
        #子弹设置
        self.bullet_speed_factor = 1   #速度比飞船低,飞船1.5
        self.bullet_width = 3       #宽3像素
        self.bullet_height = 15     #高15像素
        self.bullet_color = 60, 60, 60    #深灰色子弹

        #飞船的速度
        self.ship_speed_factor = 1.5



12.8.2 创建Bullet类

import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):  # 继承Sprite类
    """一个对飞船发射的子弹进行管理的类"""

    def __init__(self, ai_settings, screen, ship):
        """在飞船所处的位置穿件一个子弹对象"""
        super(Bullet, self).__init__()
        self.screen = screen

        # 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
        self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
                                ai_settings.bullet_height)
        # 子弹的renterx设置为飞船的rect.centerx
        self.rect.centerx = ship.rect.centerx
        # 子弹的顶部设置成飞船的顶部
        self.rect.top = ship.rect.top

        # 存储用小数表示的子弹位置
        self.y = float(self.rect.y)

        self.color = ai_settings.bullet_color               # 子弹颜色
        self.speed_factor = ai_settings.bullet_speed_factor  # 子弹速度

    def update(self):
        """向上移动子弹"""
        # 更新表示子弹位置的小数值
        self.y -= self.speed_factor   # 向上移动,y坐标不断减少
        # 更新表示子弹的rect的位置
        self.rect.y = self.y

    def draw_bullet(self):
        """在屏幕上绘制子弹"""
        pygame.draw.rect(self.screen, self.color, self.rect)



12.8.3 将子弹存储在编组中

alien_invision.py

import pygame   # 需要这个模块开发游戏有需要的功能
from pygame.sprite import Group  # 导入pygame.sprite中的Group类

from settings import Settings   # 导入settings模块中Settings类
from ship import Ship           # 导入ship模块中Ship类
import game_functions as gf     # 导入game_functions模块,模块另命名为gf



def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置

    # 创建宽1200像素,高800像素的游戏窗口
    # 对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    # 在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    # display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    # 创建实例
    # 使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  # 赋值给screen
    pygame.display.set_caption("外星人入侵")

    # 创建一艘飞船
    ship = Ship(ai_settings, screen)    # 创建名为ship的Ship实例,实参为前面的screen

    # 创建一个用于存储子弹的编组
    bullets = Group()  #创建实例,命名为bullets

    # 开始游戏的主循环
    while True:
        gf.check_events(ai_settings, screen, ship, bullets)     # 调用gf模块中的方法check_events(),ship为飞船
        ship.update()
        bullets.update()
        # 调用gf模块中的方法update_screen(),三个参数
        gf.update_screen(ai_settings, screen, ship, bullets)


run_game()



12.8.4 开火

game_functions.py

import sys

import pygame
from bullet import Bullet


def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """响应按键"""
    if event.key == pygame.K_RIGHT:  # 如果按下的是右键,按下一直为True
        # 向右移动飞船
        ship.moving_right = True  # x坐标加1,ship在主函数实例,最终在ship.py
    elif event.key == pygame.K_LEFT:  # 按下左键
        ship.moving_left = True
    elif event.key == pygame.K_SPACE:
        # 创建一颗子弹,并将其加入到编组bullets中
        new_bullet = Bullet(ai_settings, screen, ship)
        bullets.add(new_bullet)


def check_keyup_events(event, ship):
    "响应松开"
    if event.key == pygame.K_RIGHT:  # 松下右键
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:  # 松下左键
        ship.moving_left = False


def check_events(ai_settings, screen, ship, bullets):   # 加了ship参数
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

        # 每次按键都被注册为一个KEYDOWN事件
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ai_settings, screen, ship, bullets)    #调用了上面的

        elif event.type == pygame.KEYUP:       # 松下
            check_keyup_events(event, ship)      #调用了上面的


def update_screen(ai_settings, screen, ship, bullets):
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    # 调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
    # 设置背景颜色,使用ai_settings中的属性bg_color,在settings模块内
    screen.fill(ai_settings.bg_color)
    # ship为Ship实例,实例的创建在主模块中

    # 在飞船和外星人后面绘制所有子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()

    ship.blitme()  # 调用,创建实例

    # 让最近绘制的屏幕可见
    # 在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
    pygame.display.flip()



12.8.5 删除消失的子弹

子弹到达顶部后消失,只是无法消失屏幕外的子弹,实际上仍然存在,这里我们删除这些子弹
alien_invision.py

import pygame   # 需要这个模块开发游戏有需要的功能
from pygame.sprite import Group  # 导入pygame.sprite中的Group类

from settings import Settings   # 导入settings模块中Settings类
from ship import Ship           # 导入ship模块中Ship类
import game_functions as gf     # 导入game_functions模块,模块另命名为gf



def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置

    # 创建宽1200像素,高800像素的游戏窗口
    # 对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    # 在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    # display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    # 创建实例
    # 使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  # 赋值给screen
    pygame.display.set_caption("外星人入侵")

    # 创建一艘飞船
    ship = Ship(ai_settings, screen)    # 创建名为ship的Ship实例,实参为前面的screen

    # 创建一个用于存储子弹的编组
    bullets = Group()  # 创建实例,命名为bullets

    # 开始游戏的主循环
    while True:
        gf.check_events(ai_settings, screen, ship, bullets)     # 调用gf模块中的方法check_events(),ship为飞船
        ship.update()
        bullets.update()

        # 删除已消失的子弹
        for bullet in bullets.copy():
            if bullet.rect.bottom <= 0:
                bullets.remove(bullet)
           # print(len(bullets))

        # 调用gf模块中的方法update_screen(),三个参数
        gf.update_screen(ai_settings, screen, ship, bullets)


run_game()



12.8.6 限制子弹数量

以鼓励玩家有目的的射击
settings.py

class Settings():
    """存储《外星人入侵》的所有设置的类"""
    
    def __init__(self):
        """初始化游戏的设置"""
        # 屏幕设置
        self.screen_width = 1200
        self.screen_height = 750
        self.bg_color = (230, 230, 230)

        # 子弹设置
        self.bullet_speed_factor = 1   # 速度比飞船低,飞船1.5
        self.bullet_width = 3       # 宽3像素
        self.bullet_height = 15     # 高15像素
        self.bullet_color = 60, 60, 60    # 深灰色子弹
        self.bullets_allowed = 3

        # 飞船的速度
        self.ship_speed_factor = 1.5

game_functions.py

import sys

import pygame
from bullet import Bullet


def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """响应按键"""
    if event.key == pygame.K_RIGHT:  # 如果按下的是右键,按下一直为True
        # 向右移动飞船
        ship.moving_right = True  # x坐标加1,ship在主函数实例,最终在ship.py
    elif event.key == pygame.K_LEFT:  # 按下左键
        ship.moving_left = True
    elif event.key == pygame.K_SPACE:
        if len(bullets) < ai_settings.bullets_allowed:
            # 创建一颗子弹,并将其加入到编组bullets中
            new_bullet = Bullet(ai_settings, screen, ship)
            bullets.add(new_bullet)


def check_keyup_events(event, ship):
    "响应松开"
    if event.key == pygame.K_RIGHT:  # 松下右键
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:  # 松下左键
        ship.moving_left = False


def check_events(ai_settings, screen, ship, bullets):   # 加了ship参数
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

        # 每次按键都被注册为一个KEYDOWN事件
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ai_settings, screen, ship, bullets)    #调用了上面的

        elif event.type == pygame.KEYUP:       # 松下
            check_keyup_events(event, ship)      #调用了上面的


def update_screen(ai_settings, screen, ship, bullets):
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    # 调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
    # 设置背景颜色,使用ai_settings中的属性bg_color,在settings模块内
    screen.fill(ai_settings.bg_color)
    # ship为Ship实例,实例的创建在主模块中

    # 在飞船和外星人后面绘制所有子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()

    ship.blitme()  # 调用,创建实例

    # 让最近绘制的屏幕可见
    # 在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
    pygame.display.flip()



12.8.7 创建函数update_bullets()

game_functions.py

import sys

import pygame
from bullet import Bullet


def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """响应按键"""
    if event.key == pygame.K_RIGHT:  # 如果按下的是右键,按下一直为True
        # 向右移动飞船
        ship.moving_right = True  # x坐标加1,ship在主函数实例,最终在ship.py
    elif event.key == pygame.K_LEFT:  # 按下左键
        ship.moving_left = True
    elif event.key == pygame.K_SPACE:
        if len(bullets) < ai_settings.bullets_allowed:
            # 创建一颗子弹,并将其加入到编组bullets中
            new_bullet = Bullet(ai_settings, screen, ship)   # 创建实例
            bullets.add(new_bullet)


def check_keyup_events(event, ship):
    "响应松开"
    if event.key == pygame.K_RIGHT:  # 松下右键
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:  # 松下左键
        ship.moving_left = False


def check_events(ai_settings, screen, ship, bullets):   # 加了ship参数
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

        # 每次按键都被注册为一个KEYDOWN事件
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ai_settings, screen, ship, bullets)    #调用了上面的

        elif event.type == pygame.KEYUP:       # 松下
            check_keyup_events(event, ship)      #调用了上面的


def update_screen(ai_settings, screen, ship, bullets):
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    # 调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
    # 设置背景颜色,使用ai_settings中的属性bg_color,在settings模块内
    screen.fill(ai_settings.bg_color)
    # ship为Ship实例,实例的创建在主模块中

    # 在飞船和外星人后面绘制所有子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()

    ship.blitme()  # 调用,创建实例

    # 让最近绘制的屏幕可见
    # 在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
    pygame.display.flip()


def update_bullets(bullets):
    """更新子弹的位置,并删除已消失的子弹"""
    # 更新子弹的位置
    bullets.update()

    # 删除已消失的子弹
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)
    # print(len(bullets))

alien_invasion.py

import pygame   # 需要这个模块开发游戏有需要的功能
from pygame.sprite import Group  # 导入pygame.sprite中的Group类

from settings import Settings   # 导入settings模块中Settings类
from ship import Ship           # 导入ship模块中Ship类
import game_functions as gf     # 导入game_functions模块,模块另命名为gf



def run_game():
    # 初始化游戏并创建一个屏幕对象
    pygame.init()  # 初始化背景设置

    # 创建宽1200像素,高800像素的游戏窗口
    # 对象screen是个surface,在pygame中surface只是屏幕的一部分,用于显示游戏元素
    # 在这个游戏中,每个元素(如外星人和飞船)都是一个surface。
    # display.set_mode()返回的surface表示整个游戏窗口。
    ai_settings = Settings()    # 创建实例
    # 使用ai_settings中的属性screen_width和screen_height
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))  # 赋值给screen
    pygame.display.set_caption("外星人入侵")

    # 创建一艘飞船
    ship = Ship(ai_settings, screen)    # 创建名为ship的Ship实例,实参为前面的screen

    # 创建一个用于存储子弹的编组
    bullets = Group()  # 创建实例,命名为bullets

    # 开始游戏的主循环
    while True:
        gf.check_events(ai_settings, screen, ship, bullets)     # 调用gf模块中的方法check_events(),ship为飞船
        ship.update()
        gf.update_bullets(bullets)     # 调用方法

        # 调用gf模块中的方法update_screen(),三个参数
        gf.update_screen(ai_settings, screen, ship, bullets)


run_game()



12.8.4 创建函数fire_bullet()

game_functions.py

import sys

import pygame
from bullet import Bullet


def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """响应按键"""
    if event.key == pygame.K_RIGHT:  # 如果按下的是右键,按下一直为True
        # 向右移动飞船
        ship.moving_right = True  # x坐标加1,ship在主函数实例,最终在ship.py
    elif event.key == pygame.K_LEFT:  # 按下左键
        ship.moving_left = True
    elif event.key == pygame.K_SPACE:
        fire_bullet(ai_settings, screen, ship, bullets)  # 调用下面的,使得elif语句简单


def fire_bullet(ai_settings, screen, ship, bullets):
    """如果还没有达到限制,就发射一颗子弹"""
    if len(bullets) < ai_settings.bullets_allowed:
        # 创建一颗子弹,并将其加入到编组bullets中
        new_bullet = Bullet(ai_settings, screen, ship)  # 创建实例
        bullets.add(new_bullet)


def check_keyup_events(event, ship):
    "响应松开"
    if event.key == pygame.K_RIGHT:  # 松下右键
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:  # 松下左键
        ship.moving_left = False


def check_events(ai_settings, screen, ship, bullets):   # 加了ship参数
    """响应按键和鼠标事件"""
    # 监视键盘和鼠标事件
    # 方法pygame.event.get()访问pygame检测到的事件
    # 所有键盘和鼠标事件都将促使for循环运行
    for event in pygame.event.get():
        # 在循环中,编写一系列if语句检测并相应特定的事件。
        if event.type == pygame.QUIT:
            sys.exit()  # 退出游戏

        # 每次按键都被注册为一个KEYDOWN事件
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event, ai_settings, screen, ship, bullets)    #调用了上面的

        elif event.type == pygame.KEYUP:       # 松下
            check_keyup_events(event, ship)      #调用了上面的


def update_screen(ai_settings, screen, ship, bullets):
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    # 调用方法screen.fill(),用背景颜色填充屏幕,这种方法只接受一个实参:一种颜色
    # 设置背景颜色,使用ai_settings中的属性bg_color,在settings模块内
    screen.fill(ai_settings.bg_color)
    # ship为Ship实例,实例的创建在主模块中

    # 在飞船和外星人后面绘制所有子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()

    ship.blitme()  # 调用,创建实例

    # 让最近绘制的屏幕可见
    # 在每次执行while循环时都会绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见,不断更新屏幕
    pygame.display.flip()


def update_bullets(bullets):
    """更新子弹的位置,并删除已消失的子弹"""
    # 更新子弹的位置
    bullets.update()

    # 删除已消失的子弹
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)
    # print(len(bullets))

本文地址:https://blog.csdn.net/qq_39236499/article/details/107067392