对于项目一,确实有些杂,但是我们只要理清其中的思路即可。毕竟第一次的项目,往后要不断回顾才是。
这样吧,我附上整个项目的代码。有什么不懂的地方可以留言问我。
# 02 import sys
import pygame
from settings import Setting # 01
from ship import Ship # 01
import game_function as gf # 02
from pygame.sprite import Group # 03 pygame.sprite.Group 类类似于列表,但提供了有助于开发游戏的额外功能
# from aliens import Alien # 04
from game_stats import GameStats # 04
from button import Button # 05
from scoreboard import Scoreboard # 05
def run_game(): # 初始化游戏,并且创建一个屏幕对象
pygame.init() # 初始化背景设置,让Pygame能够正确地工作
# 01 screen = pygame.display.set_mode((1200, 800)) # 创建一个名为screen 的显示窗口,括号里是元组!!!
# 01 # 这个游戏的所有图形元素都将在其中绘制
ai_set = Setting() # 因为导入类而做了代码替换
screen = pygame.display.set_mode(
(ai_set.screen_width, ai_set.screen_height)
)
# 01 bg_color = (230,230,230) # 设置背景颜色
pygame.display.set_caption('外星人入侵')
# 创建一个play按钮
play_button = Button(ai_set, screen, 'Play')
# 创建一个用于存储游戏统计信息的实例 并【创建记分牌】
stats = GameStats(ai_set)
sb = Scoreboard(ai_set, screen, stats)
# 创建一艘飞船对象
ship = Ship(ai_set, screen)
# 03 导入Group类并且创建一个Group实例,用于存储子弹的编组
bullets = Group()
# 04 创建一个外星人,编组
# alien = Alien(ai_set,screen)
aliens = Group()
# 04 创建外星人群
gf.create_fleet(ai_set, screen, ship, aliens)
# 为让程序响应事件,我们编写一个事件循环,以侦听事件,并根据发生的事件执行相应的任务。
while True: # 游戏的主循环
# 02 for event in pygame.event.get(): # 监视键盘和鼠标
# 02 if event.type == pygame.QUIT: #编写一系列的if 语句来检测并响应特定的事件
# 02 sys.exit() # 我们调用sys.exit() 来退出游戏
gf.check_event(ai_set, screen, stats, sb, play_button, ship, aliens, bullets) # 02 03 05 06
if stats.game_active:
ship.update() # 02
gf.update_bullet(ai_set, screen, stats, sb, ship, aliens, bullets) # 03 04 05
gf.update_aliens(ai_set, screen, stats, sb, ship, aliens, bullets) # 04 06
# 03 bullets.update() # 03
# # 03 删除已经消失,看不到的子弹
# for bull in bullets.copy():
# if bull.rect.bottom <= 0:
# bullets.remove(bull)
# print(len(bullets))
# 01screen.fill(bg_color) # 每次循环都重绘屏幕
# 02 screen.fill(ai_set.bg_color)
# 02 ship.blitme() # 调用blitme函数,使飞船出现
# 02 pygame.display.flip() # 让最近绘制的屏幕可见
gf.update_screen(ai_set, screen, stats, sb, ship, aliens, bullets, play_button) # 02 03 04 05
run_game()
input()
import sys
import pygame
from settings import Setting
from bullet import Bullet # 03
from aliens import Alien # 04
from time import sleep # 04
from game_stats import GameStats # 05
# 响应按键 03
def check_keydown(event, ai_settings, screen, ship, bullets):
if event.key == pygame.K_RIGHT:
# 向右移动飞船
ship.moving_right = True
# ship.rect.centerx += 10
elif event.key == pygame.K_LEFT:
# 向左移动飞船
# ship.rect.centerx -= 10
ship.moving_left = True
# 03 创建一颗子弹,并将其加入到编组bullets中
elif event.key == pygame.K_SPACE:
if len(bullets) < ai_settings.bullet_allowed: # 限制三个子弹
# 玩家按空格键时,创建一颗新子弹(一个名为new_bullet 的Bullet 实例),
new_bullet = Bullet(ai_settings, screen, ship)
# 并使用方法add() 将其加入到编组bullets中
bullets.add(new_bullet)
# 04 按q结束
elif event.key == pygame.K_q:
sys.exit()
# 响应松开 03
def check_keyup(event, ship):
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
# 响应按键和鼠标事件
def check_event(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets): # 03
for i in pygame.event.get():
if i.type == pygame.QUIT:
sys.exit()
elif i.type == pygame.KEYDOWN:
check_keydown(i, ai_setting, screen, ship, bullets) # 重构
# 03 if i.key == pygame.K_RIGHT:
# 03 # 向右移动飞船
# 03 ship.moving_right = True
# 03 # ship.rect.centerx += 10
# 03 elif i.key == pygame.K_LEFT:
# 03 # 向左移动飞船
# 03 # ship.rect.centerx -= 10
# 03 ship.moving_left = True
elif i.type == pygame.KEYUP:
check_keyup(i, ship) # 重构
# 03 if i.key == pygame.K_RIGHT:
# 03 ship.moving_right = False
# 03 elif i.key == pygame.K_LEFT:
# 03 ship.moving_left = False
# 05 鼠标点击事件
elif i.type == pygame.MOUSEBUTTONDOWN:
# 无论玩家单击屏幕的什么地方,Pygame都将检测到一个MOUSEBUTTONDOWN 事件
# 但我们只想让这个游戏在玩家用鼠标单击Play按钮时作出响应
# 为此,我们使用了pygame.mouse.get_pos() ,它返回一个元组,其中包含玩家单击时鼠标的x 和y 坐标
mouse_x, mouse_y = pygame.mouse.get_pos()
# 我们将这些值传递给函数check_play_button()
# 而这个函数使用collidepoint() 检查鼠标单击位置是否在Play按钮的rect 内
check_play_button(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y)
# 05 在玩家单击play按钮时开始新的游戏
def check_play_button(ai_setting, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y):
# 仅当玩家单击了Play按钮且 游戏当前处于非活动状态时,游戏才重新开始
# collidepoint() 检查鼠标单击位置是否在Play按钮的rect 内
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active: # 控制仅仅在按钮区域,且 游戏停止状态 才会重置
# 重置游戏的设置,如初始速度等
ai_setting.initialize_dynamic_settings()
# 隐藏光标,直到游戏重开时出现,修改visible状态的代码写到ship_hit()中
pygame.mouse.set_visible(False)
# 重置游戏统计信息
stats.reset_stats()
stats.game_active = True
# 06 为确保开始新游戏时更新记分和等级图像,在按钮Play被单击时触发重置
sb.prep_score()
sb.prep_high_score()
sb.prep_level()
# 06 我们在开始新游戏时调用prep_ships()
sb.prep_ship()
# 清空外星人列表和子弹列表
aliens.empty()
bullets.empty()
# 创建一群新的外星人,并让飞船居中
create_fleet(ai_setting, screen, ship, aliens)
ship.center_ship() # ship.py中的函数
# -------------------------------------更新屏幕-------------------------------------
# 更新屏幕上的图像,并切换到新屏幕
def update_screen(ai_setting, screen, stats, sb, ship, aliens, bullets, play_button):
# 每次循环时都重绘屏幕
screen.fill(ai_setting.bg_color)
# 03 在飞船和外星人后面重绘所有子弹
# 为在屏幕上绘制发射的所有子弹,我们遍历编组bullets 中的精灵,并对每个精灵都调用draw_bullet()
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
# 04 alien.blitme()
aliens.draw(screen) # 04 绘制外星人,使用的是内置draw函数
# 06 显示得分
sb.show_score()
# 05 如果处于非游戏状态,就绘制play按钮
if not stats.game_active:
play_button.draw_button() # 此函数在button.py文件
# 让最近绘制的屏幕可见
pygame.display.flip()
# -------------------------------------以下是子弹----------------------------------------------
# 03 更新子弹位置,并删除已经消失的子弹
def update_bullet(ai_setting, screen, stats, sb, ship, aliens, bullets): # 05
bullets.update() # 更新子弹位置
# 03 删除已经消失,看不到的子弹
for bull in bullets.copy():
if bull.rect.bottom <= 0:
bullets.remove(bull)
print(len(bullets))
# ----- 04 检查是否碰撞-------
check_bullet_alien_collision(ai_setting, screen, stats, sb, ship, aliens, bullets) # 05
# 检查子弹和外星人是否碰撞
def check_bullet_alien_collision(ai_setting, screen, stats, sb, ship, aliens, bullets):
# 方法sprite.groupcollide() 将每颗子弹的rect 同每个外星人的rect 进行比较,并返回一个字典,
# 其中包含发生了碰撞的子弹和外星人。在这个字典中,每个键都是一颗子弹,而相应的值都是被击中的外星人
# 检查是否有子弹击中了外星人
# 如果是这样,就删除相应的子弹和外星人
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
# 05 若碰撞则加分
if collisions:
# 如果字典collisions 存在,我们就遍历其中的所有值。
# 别忘了,每个值都是一个列表,包含被同一颗子弹击中的所有外星人。
# 对于每个列表,都将一个外星人的点数乘以其中包含的外星人数量,并将结果加入到当前得分中
for alie in collisions.values():
# 有子弹撞到时,Pygame返回一个字典(collisions )。
# 我们检查这个字典是否存在,如果存在,就将得分加上一个外星人值的点数
stats.score += ai_setting.alien_point * len(alie)
sb.prep_score() # 此函数在scoreboard.py文件中
check_high_score(stats, sb) # 此函数在本页最后
# 如果外星人编组为空,则删除现有子弹并新建一群外星人
# 06 如果整群外星人都被消灭,就提高一个等级
if len(aliens) == 0:
bullets.empty()
ai_setting.increase_speed() # 增加游戏节奏
# 06 提高等级
stats.level += 1
sb.prep_level()
create_fleet(ai_setting, screen, ship, aliens)
# ai_setting.fleet_drop_speed += 20 # 自己加的----------------------------------------------------
# -------------------------------------以下是外星人 04 --------------------------------------------
# 04 创建外星人群
def create_fleet(ai_setting, screen, ship, aliens):
# 创建一个外星人,并计算一行可容纳多少个外星人
# 外星人间距为外星人宽度
# 我们先创建一个外星人,这个外星人不是外星人群的成员,因此没有将它加入到编组aliens 中
ali = Alien(ai_setting, screen)
number_alien_x = get_number_aliens_x(ai_setting, ali.rect.width) # 04 重构create_fleet
number_rows = get_number_row(ai_setting, ship.rect.height, ali.rect.height)
# 04 # 我们从外星人的rect 属性中获取外星人宽度,并将这个值存储到alien_width 中,以免反复访问属性rect
# 04 ali_width = ali.rect.width
# 04 # 我们计算可用于放置外星人的水平空间,以及其中可容纳多少个外星人。
# 04 available_space_x = ai_setting.screen_width - 2 * ali_width
# 04 number_alien_x = int(available_space_x / (2 * ali_width))
# 创建第一行外星人
for row_num in range(number_rows):
for ali_num in range(number_alien_x):
# 创建一个外星人,并加入当前行
# alien = Alien(ai_setting,screen) # 通过设置x 坐标将其加入当前行
# alien.x = ali_width + 2 * ali_width * ali_num
# alien.rect.x = alien.x
# aliens.add(alien)
create_alien(ai_setting, screen, aliens, ali_num, row_num) # 04 重构create_fleet
# 计算每行可容纳多少个外星人
def get_number_aliens_x(ai_setting, alien_width):
available_space_x = ai_setting.screen_width - 2 * alien_width
number_alien_x = int(available_space_x / (2 * alien_width))
return number_alien_x
# 计算屏幕可容纳多少行外星人
def get_number_row(ai_setting, ship_height, alien_height):
available_space_y = (ai_setting.screen_height - (3 * alien_height) - 3.5 * ship_height)
number_rows = int(available_space_y / (2 * alien_height))
return number_rows
# 创建一个外星人并将其放在当前行
def create_alien(ai_setting, screen, aliens, alien_number, row_number):
alien = Alien(ai_setting, screen) # 通过设置x 坐标将其加入当前行
alien_width = alien.rect.width
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number # 创建时,计算y的坐标
aliens.add(alien)
# 更新外星人群中所有外星人位置
def update_aliens(ai_set, screen, stats, sb, ship, alie, bullets):
# 检查是否有外星人到达屏幕边,然后更新所有外星人的位置
check_fleet_edges(ai_set, alie)
alie.update()
# 04 检测外星人和飞船之间的碰撞
# 方法spritecollideany() 接受两个实参:一个精灵和一个编组。
# 它检查编组是否有成员与精灵发生了碰撞,并在找到与精灵发生了碰撞的成员后就停止遍历编组。
if pygame.sprite.spritecollideany(ship, alie):
ship_hit(ai_set, screen, stats, sb, ship, alie, bullets)
# 检测是否有外星人到达屏幕底部
check_aliens_bottom(ai_set, screen, stats, sb, ship, alie, bullets)
# 检测是否有外星人到达的屏幕底端
def check_aliens_bottom(ai_setting, screen, stats, sb, ship, aliens, bullets):
screen_rect = screen.get_rect()
for ali in aliens.sprites():
if ali.rect.bottom >= screen_rect.bottom:
# 像飞船撞到外星人一样处理
ship_hit(ai_setting, screen, stats, sb, ship, aliens, bullets)
break
# 响应被外星人撞到的飞船
def ship_hit(ai_setting, screen, stats, sb, ship, aliens, bullets):
if stats.ships_left > 0:
# 将ships_left减一
stats.ships_left -= 1
# 我们还在飞船被外星人撞到时调用prep_ships() ,从而在玩家损失一艘飞船时更新飞船图像:
sb.prep_ship()
# 清空外星人和子弹列表
aliens.empty()
bullets.empty()
# 重新创建一群新的外星人,并将飞船放到屏幕底部
create_fleet(ai_setting, screen, ship, aliens)
ship.center_ship() # ship.py中的函数
# 暂停0.5秒
sleep(0.5)
else:
stats.game_active = False
# 使光标出现
pygame.mouse.set_visible(True)
# 有外星人到达边缘时,采取相应的措施
def check_fleet_edges(ai_setting, aliens):
for ali in aliens.sprites(): # 我们遍历外星人群,并对其中的每个外星人调用check_edge()
if ali.check_edge(): # aliens.py中有此函数
change_fleet_direction(ai_setting, aliens)
break
# 将整群外星人下移,并改变它们的方向
def change_fleet_direction(ai_set, aliens):
for ali in aliens.sprites():
ali.rect.y += ai_set.fleet_drop_speed
ai_set.fleet_direction *= -1
# ---------------------------------------以下是检测是否诞生最高分----------------------------------------
def check_high_score(stats, sb):
if stats.score > stats.high_score:
stats.high_score = stats.score
sb.prep_high_score()
import pygame
from pygame.sprite import Sprite # 06
class Ship(Sprite):
def __init__(self, ai_setting, screen): # 初始化飞船,并设置初始位置
super().__init__() # 06 继承初始化
self.screen = screen
self.ai_setting = ai_setting # 02
# 加载飞船图像并获取其外接矩形
self.image = pygame.image.load('.\\feii.bmp')
self.rect = self.image.get_rect() # 我们使用get_rect() 获取相应surface的属性rect
self.screen_rect = self.screen.get_rect()
# 将每艘新飞船放在屏幕底部中央
# 要将游戏元素居中,可设置相应rect 对象的属性center 、centerx 或centery 。
self.rect.centerx = self.screen_rect.centerx
# 要让游戏元素与屏幕边缘对齐,可使用属性top 、bottom 、left 或right ;
# 要调整游戏元素的水平或垂直位置,可使用属性x 和y ,它们分别是相应矩形左上角的 x 和 y 坐标。
self.rect.bottom = self.screen_rect.bottom
# 在飞船的属性center中存储小数数值
self.center = float(self.rect.centerx) # 小数形式的位移可以更好的控制飞船移动
# 移动标志,# 02
# 飞船不动时,标志moving_right将为False 。
# 玩家按下右箭头键时,我们将这个标志设置为True ;而玩家松开时,我们将这个标志重新设置为False
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False
# 根据移动标志,移动飞船 # 02
def update(self):
if self.moving_right and self.rect.right < self.screen_rect.right: # 控制飞船移动的左右范围
# 02 self.rect.centerx += 1
# 02 更新飞船的center值,而不是rect
self.center += self.ai_setting.ship_speed_factor
if self.moving_left and self.rect.left > 0:
# 02 self.rect.centerx -= 1
self.center -= self.ai_setting.ship_speed_factor
# 根据self.center更新rect对象
self.rect.centerx = self.center
# 我们定义了方法blitme() ,它根据self.rect 指定的位置将图像绘制到屏幕上
# 在指定位置绘制飞船
def blitme(self):
self.screen.blit(self.image, self.rect) # 把image这个surface对象贴到rect的位置
# 让飞船在屏幕上居中
def center_ship(self):
self.center = self.screen_rect.centerx
import pygame
from pygame.sprite import Sprite
# 表示单个外星人的类
class Alien(Sprite):
# 初始化外星人并设置其起始位置
def __init__(self, ai_setting, screen):
super().__init__()
self.screen = screen
self.ai_setting = ai_setting
# 加载外星人图形,并设置其rect属性
self.image = pygame.image.load(r'.\\alien-1.bmp')
self.rect = self.image.get_rect()
# 每个外星人都在屏幕左上角附近
self.rect.x = self.rect.width
self.rect.y = self.rect.height
# 存储外星人的准确位置
self.x = float(self.rect.x)
# 在指定位置绘制外星人
def blitme(self):
self.screen.blit(self.image, self.rect)
# 如果外星人处于屏幕边缘,就返回True,此函数会在game_function中用到
# 如果外星人处于屏幕边缘,就返回True,此函数会在game_function中用到
def check_edge(self):
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right:
return True
elif self.rect.left <= screen_rect.left:
return True
# 向左或向右移动外星人
def update(self, *args):
self.x += self.ai_setting.alien_speed_factor * self.ai_setting.fleet_direction
self.rect.x = self.x
import pygame
from pygame.sprite import Sprite # 导入精灵
# 一个对飞船发射的子弹进行管理的类
class Bullet(Sprite):
def __init__(self, ai_setting, screen, ship):
# 在飞船所处的位置创建一个子弹对象
super().__init__() # 初始化父类 2.7写法super(Bullet,self).__init__()
self.screen = screen
# 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
# 我们创建了子弹的属性rect 。子弹并非基于图像的,因此我们必须使用pygame.Rect()类从空白开始创建一个矩形
# 我们在(0, 0)处创建这个矩形,但接下来的两行代码将其移到了正确的位置
# self.rect = pygame.Rect(0,0,ai_setting.bullet_width,ai_setting.bullet_height)-------原版,下两行DIY-------
self.image = pygame.image.load('.\\Heart7.bmp')
self.rect = self.image.get_rect()
# 我们将子弹的centerx设置为飞船的rect.centerx 。
# 子弹应从飞船顶部射出,因此我们将表示子弹的rect的top属性设置为飞船的rect的top属性,
# 让子弹看起来像是从飞船中射出的
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top
# 存储用小数表示的子弹位置
self.y = float(self.rect.y)
self.color = ai_setting.bullet_color
self.speed = ai_setting.bullet_speed_factor
# 向上移动子弹
def update(self, *args):
# 更新表示子弹位置的小数值
self.y -= self.speed / 2
# 更新表示子弹位置的rect的位置
self.rect.y = self.y
# 在屏幕上绘制子弹
def draw_bullet(self):
# 函数draw.rect()使用存储在self.color中的颜色填充表示子弹的rect占据的屏幕部分
# pygame.draw.rect(self.screen,self.color,self.rect)-----------------------原版,下一行DIY-------------------
self.screen.blit(self.image, self.rect)
import pygame.sysfont
class Button():
# 初始化按钮属性
def __init__(self, ai_setting, screen, msg):
self.screen = screen
self.screen_rect = screen.get_rect()
# 设置按钮的尺寸和其他属性
self.width, self.height = 200, 50
self.button_color = (0, 255, 0)
self.text_color = (255, 255, 255)
self.font = pygame.sysfont.SysFont('arial', 48)
# 创建按钮的rect对象,并使其居中
# 为让按钮在屏幕上居中,我们创建一个表示按钮的rect 对象
# 并将其center 属性设置为屏幕的center 属性
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.rect.center = self.screen_rect.center
# 按钮的标签只需创建一次
# Pygame通过将你要显示的字符串渲染为图像来处理文本。我们调用prep_msg() 来处理这样的渲染
self.prep_msg(msg)
# 将msg渲染为图像,并使其在按钮上居中
def prep_msg(self, msg):
self.msg_image = self.font.render(msg, True, self.text_color, self.button_color)
self.msg_image_rect = self.msg_image.get_rect()
self.msg_image_rect.center = self.rect.center
# 最后,我们创建方法draw_button() ,通过调用它可将这个按钮显示到屏幕上
def draw_button(self):
# 绘制一个用颜色填充的按钮,再绘制文本
self.screen.fill(self.button_color, self.rect)
self.screen.blit(self.msg_image, self.msg_image_rect)
# 跟踪游戏的统计信息
class GameStats():
# 初始化统计信息
def __init__(self, ai_setting):
self.ai_setting = ai_setting
self.reset_stats()
# # 游戏刚开始时处于活动状态
# self.game_active = True
# 游戏刚开始时处于停止状态,直到play按钮按下
self.game_active = False # 05
# 在任何情况下都不重置最高分
self.high_score = 0
# 初始化在游戏运行期间可能变化的统计信息
def reset_stats(self):
self.ships_left = self.ai_setting.ship_limit
self.score = 0 # 05 记分,在每次游戏开始时,重置记分
self.level = 1 # 06 等级
import pygame.sysfont
from pygame.sprite import Group # 06
from ship import Ship # 06
# 显示得分信息的类
class Scoreboard():
# 初始化显示涉及得分的属性
def __init__(self, ai_setting, screen, stats):
self.screen = screen
self.screen_rect = screen.get_rect()
self.ai_setting = ai_setting
self.stats = stats
# 显示得分信息时使用的字体设置
self.text_color = (30, 30, 30)
self.font = pygame.sysfont.SysFont('arial', 48)
# 准备初始得分图像
self.prep_score() # 为将要显示的文本转换为图像
# 准备最高分的图像
self.prep_high_score()
# 06 准备显示等级的图像
self.prep_level()
# 06 准备显示剩余飞船的图像
self.prep_ship()
# 将得分转换为一副渲染的图像
def prep_score(self):
round_score = round(self.stats.score)
score_str = '{:,}'.format(round_score)
self.score_image = self.font.render(score_str, True, self.text_color, self.ai_setting.bg_color)
# 将得分放到屏幕右上角
self.score_rect = self.score_image.get_rect()
self.score_rect.right = self.screen_rect.right - 20
self.score_rect.top = 20 # 让其上边缘与屏幕上边缘也相距20像素
# 将最高分渲染为图像
def prep_high_score(self):
high_score = round(self.stats.high_score)
high_score_str = '{:,}'.format(high_score)
self.high_score_image = self.font.render(high_score_str, True, self.text_color, self.ai_setting.bg_color)
# 将最高分放在屏幕顶部中央
self.high_score_rect = self.high_score_image.get_rect()
self.high_score_rect.centerx = self.screen_rect.centerx
self.high_score_rect.top = self.screen_rect.top
# 06 等级渲染为图像
def prep_level(self):
self.leve_image = self.font.render(str(self.stats.level), True, self.text_color, self.ai_setting.bg_color)
# 将等级放在得分下方
self.level_rect = self.leve_image.get_rect()
self.level_rect.right = self.screen_rect.right - 20
self.level_rect.top = self.score_rect.bottom + 10
# 06 显示剩余多少飞船
def prep_ship(self):
# 方法prep_ships() 创建一个空编组self.ships ,用于存储飞船实例
self.ships = Group()
# 为填充这个编组,根据玩家还有多少艘飞船运行一个循环相应的次数
for ship_num in range(self.stats.ships_left):
# 在这个循环中,我们创建一艘新飞船,并设置其x 坐标,
# 让整个飞船编组都位于屏幕左边,且每艘飞船的左边距都为10像素
# 我们还将y 坐标设置为离屏幕上边缘10像素,让所有飞船都与得分图像对齐
ship = Ship(self.ai_setting, self.screen)
ship.rect.x = 10 + ship_num * ship.rect.width
ship.rect.y = 10
# 最后,我们将每艘新飞船都添加到编组ships 中
self.ships.add(ship)
# 在屏幕上显示得分
def show_score(self):
# 这个方法将得分图像显示到屏幕上,并将其放在score_rect 指定的位置
self.screen.blit(self.score_image, self.score_rect)
self.screen.blit(self.high_score_image, self.high_score_rect)
self.screen.blit(self.leve_image, self.level_rect) # 06
# 为在屏幕上显示飞船,我们对编组调用了draw() 。Pygame将绘制每艘飞船。
self.ships.draw(self.screen)
class Setting(): # 存储《外星人入侵》中所有的设置类
def __init__(self): # 初始化游戏设置
self.screen_width = 1200 # 屏幕设置
self.screen_height = 800
self.bg_color = (230, 230, 230)
# self.ship_speed_factor = 2.5 # 02 设置飞船速度
# 03 子弹设置
# 05 self.bullet_speed_factor = 3 # 子弹速度
self.bullet_width = 500 # 子弹宽度
self.bullet_height = 3 # 子弹长度
self.bullet_color = 60, 60, 60 # 子弹颜色
self.bullet_allowed = 3 # 限制子弹数量为3
# 04 外星人设置
# 05 self.alien_speed_factor = 1
self.fleet_drop_speed = 10
# 05 # fleet_direction为1表示向右移动,为-1表示向左移动
# self.fleet_direction = 1
# 04 飞船设置
self.ship_limit = 2
# 以什么样的速度加快游戏节奏
self.speedup_scale = 1.1
# 玩家每提高一个等级,游戏都变得更难,因此处于较高的等级时,外星人的点数应更高。
# 外星人点数的提高速度
self.score_scale = 1.5
# 05 我们将动态变量 和 静态变量分开
# 调用initialize_dynamic_settings() ,以初始化随游戏进行而变化的属性
self.initialize_dynamic_settings()
# 05 初始化随游戏进行而变化的设置
def initialize_dynamic_settings(self):
self.bullet_speed_factor = 3 # 子弹速度
self.alien_speed_factor = 0.8
self.ship_speed_factor = 1.5 # 02 设置飞船速度
# fleet_direction为1表示向右移动,为-1表示向左移动
self.fleet_direction = 1
# 05 记分
# 随着游戏的进行,我们将提高每个外星人值的点数。
# 为确保每次开始新游戏时这个值都会被重置,我们在initialize_dynamic_settings() 中设置它。
self.alien_point = 50
# 05 每当玩家提高一个等级时,我们都使用increase_speed() 来提高飞船、子弹和外星人的速度
# 提高速度
def increase_speed(self):
self.ship_speed_factor *= self.speedup_scale
self.alien_speed_factor *= self.speedup_scale
self.ship_speed_factor *= self.speedup_scale
self.alien_point = int(self.alien_point * self.score_scale)