python代码实践编程“武装飞船”
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()
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()
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()
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