赞
踩
本篇博客承接上一篇博客:
def update_bullets(ai_settings,screen,ship,aliens,bullets): # 更新子弹的位置, 并删除已消失的子弹 4303987588749 bullets.update() # 清楚越界的子弹,防止占用内存 # 遍历子弹编组的副本,在副本中检查每颗子弹,判断是否到顶端 for bullet in bullets.copy(): # 如果子弹到顶端则删除 if bullet.rect.bottom<=0: bullets.remove(bullet) # print(len(bullets)) # 打印输出剩余的子弹数量 check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets) def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets): # groupcollide遍历编组bullets中的所有子弹和编组aliens中的所有外星人。 # 当有子弹和外星人的rect重叠时,groupcollide返回一个键值对 collisions = pygame.sprite.groupcollide(bullets,aliens,True,True) if len(aliens) ==0 : # 删除现有的子弹并创建一群外星人 bullets.empty() create_fleet(ai_settings,screen,ship,aliens)
alien_invasion.py文件中
while True:
gf.check_events(ai_settings,screen,ship,bullets)
if stats.game_active:
ship.update()
# 更新子弹运行轨迹
gf.update_bullets(ai_settings,screen,ship,aliens,bullets)
gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # 更新外星人位置
gf.update_screen(ai_settings, screen, ship,aliens,bullets)
新建一个game_stats.py文件
# 跟踪游戏统计信息的类,记录飞船被撞了多少次
# 在游戏运行期间之创建一个GamStats类,但当玩
# 家开始游戏时,需要重置一些统计信息,所有用
# reset_stats来初始化大部分信息
class GamStats():
# 跟踪游戏的统计信息
def __init__(self,ai_settings):
# 初始化统计信息
self.ai_settings = ai_settings
self.reset_stats()
self.game_active= True
def reset_stats(self):
# 初始化在游戏运行期间可能变化的统计信息
self.ships_left = self.ai_settings.ship_limit
在alien_invasion.py文件中做如下修改
# 创建一个用于存储游戏统计信息的实例
stats = GamStats(ai_settings)
game_functions.py 文件中修改:
def update_aliens(ai_settings,stats,screen,ship,aliens,bullets): # 检查外星人是否到达边缘 check_fleet_edges(ai_settings,aliens) # 更新外星人群中所有外星人的位置 aliens.update() # 检测外星人和飞船之间的碰撞 # spritecollideany接受两个参数,一个精灵和一个编组。 # 它检查编组是否有成员与精灵发生了碰撞,如果没有发生碰撞,返回None if pygame.sprite.spritecollideany(ship,aliens): print("Ship hit!!!") if pygame.sprite.spritecollideany(ship,aliens): ship_hit(ai_settings,stats,screen,ship,aliens,bullets) check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets) def ship_hit(ai_settings,stats,screen,ship,aliens,bullets): # 响应被外星人撞到的飞船 # 将ships_left减1 if stats.ships_left > 0: stats.ships_left -= 1 # 清空外星人列表和子弹列表 aliens.empty() bullets.empty() # 创建一群新的外星人, 并将飞船放到屏幕底端中央 create_fleet(ai_settings,screen,ship,aliens) ship.center_ship() # 暂停 sleep(0.5) else: stats.geme_active = False
ship.py文件中新增函数:
def center_ship(self):
# 让飞船在屏幕上居中
self.center = self.screen_rect.centerx
def check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets):
# 检查是否有外星人到达了屏幕底端
screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
# 像飞船被撞到一样进行处理
ship_hit(ai_settings,stats,screen,ship,aliens,bullets)
break
class Settings(): """ 存储 游戏 的所有设置的类,存放一些基本参数""" def __init__(self): """ 初始化游戏的设置""" #屏幕设置 self.screen_width = 900 self.screen_height = 600 self.bg_color = (230,230,230) # 飞船设置 # 设置属性ship_speed_factor来控制飞船的速度 # 移动飞船时移动1.5 个像素 self.ship_speed_factor = 1.0 self.ship_limit = 3 # 子弹设置 self.bullet_speed_factor = 1 # 子弹速度 self.bullet_width = 3 self.bullet_height = 15 self.bullet_color = 60, 60, 60 self.bullets_allowed = 10 # 限制子弹数量 # 外星人参数设置 self.alien_speed_factor = 1 # 外星人撞到屏幕边缘时,外星人群向下移动 self.fleet_drop_speed = 10 # fleet_direction 为1表示向右移动,-1表示向左移 self.fleet_direction = 1
import pygame class Ship(): def __init__(self,ai_settings, screen): """ 初始化飞船设置其初始化位置""" self.screen = screen self.ai_settings = ai_settings # 加载飞船图像并获取其外接矩形 self.image = pygame.image.load('images/ship.bmp') self.rect = self.image.get_rect() self.screen_rect = screen.get_rect() #将每艘新飞船放在屏幕底部中央 self.rect.centerx = self.screen_rect.centerx self.rect.bottom = self.screen_rect.bottom # 在飞船的属性center中存储小数值 self.center = float(self.rect.centerx) # 添加一个向右移动的属性 初始化为False # 在向右键按下时,为真,松开为False,实现按住持续移动 self.moving_right = False self.moving_left = False # 更新飞船的位置坐标,窗口宽1200,飞船默认居中。 # 右加左减 def update(self): #控制飞船活动范围的方法,一种是限制位置变量的取值范围,这样是固定的范围 #一种是动态限制范围,以下是动态限制 # self.rect.right返回飞船外接矩形的右边缘的x坐标, # 如果这个值小于self.screen_rect.right的值,就说明飞船未触及屏幕右边缘 if self.moving_right and self.rect.right<self.screen_rect.right: # self.rect.centerx +=1 # ai_settings是settings模块中的函数,函数里面有ship_speed_factor速度变量 self.center += self.ai_settings.ship_speed_factor if self.moving_left and self.rect.left>0: self.center -= self.ai_settings.ship_speed_factor # center是自己创建的一个变量,用来记录飞船的位置 # self.rect.centerx是系统的变量,用来控制飞船的位置 self.rect.centerx = self.center def blitme(self): """ 在指定位置绘制飞船""" self.screen.blit(self.image,self.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_settings,screen): # 初始化外星人并设置其起始位置 super(Alien,self).__init__() self.screen = screen self.ai_settings = ai_settings # 加载外星人图像,并设置其screen属性 self.image = pygame.image.load('images/alien.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) def update(self): # 向左或向右移动外星人 self.x += (self.ai_settings. alien_speed_factor*self.ai_settings.fleet_direction) self.rect.x = self.x def check_edges(self): # 如果外星人位于屏幕边缘,就返回True screen_rect = self.screen.get_rect() if self.rect.right >= screen_rect.right: return True elif self.rect.left <=0: return True
import pygame from pygame.sprite import Sprite class Bullet(Sprite): # 对飞船发射的子弹进行管理 def __init__(self, ai_settings,screen,ship): # 在飞船所处的位置创建一个子弹对象 super(Bullet,self).__init__() self.screen = screen # 在(0,0)处创建一个表示子弹的矩形, 再设置正确的位置 # 使用pygame.Rect创建一个空白的矩形,创建时必须提供(x,y)坐标 # 子弹的宽度和高度从ai_settings中获取 self.rect = pygame.Rect(0,0,ai_settings.bullet_width, ai_settings.bullet_height) # 设置子弹的位置,位于飞船的正上方。 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 # 更新表示子弹的rect的位置 self.rect.y = self.y def draw_bullet(self): pygame.draw.rect(self.screen,self.color,self.rect)
import sys import pygame from bullet import Bullet from alien import Alien from time import sleep # 设置键盘按钮事件 def check_keydown_events(event,ai_settings,screen,ship,bullets): # 响应按键 右方向键 # 通过读取event.key,检查按下的是否是右箭头键 if event.key == pygame.K_RIGHT: # 向右移动飞船 # ship.rect.centerx += 1 飞船向右移动 ship.moving_right = True elif event.key == pygame.K_LEFT: # 向左移动飞船 # ship.rect.centerx -= 1 ship.moving_left = True elif event.key == pygame.K_SPACE: # 设置开火指令 fire_bullet(ai_settings, screen, ship, bullets) # 按下Q时退出游戏 elif event.key == pygame.K_q: sys.exit() 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): """ 响应按键和鼠标事件,在这个方法中指定需要检查的事件 """ # 事件都是通过pygame.event.get()方法获取 for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() # 每次按键都会注册一个KEYDOWN # 检测到KEYDOWN事件时,我们需要检查按下的是否是特定的键 elif event.type == pygame.KEYDOWN: check_keydown_events(event,ai_settings,screen,ship,bullets) # 松开方向键时触发的事件,将moving_right or moving_left设为false elif event.type == pygame.KEYUP: check_keyup_events(event,ship) def update_screen(ai_settings, screen, ship,aliens,bullets): # 更新屏幕上的图像, 并切换新屏幕 #每次循环都会重绘制屏幕 screen.fill(ai_settings.bg_color) #只能有一个参数 for bullet in bullets.sprites(): bullet.draw_bullet() ship.blitme() aliens.draw(screen) # 让最近绘制的屏幕可见 pygame.display.flip() def update_bullets(ai_settings,screen,ship,aliens,bullets): # 更新子弹的位置, 并删除已消失的子弹 4303987588749 bullets.update() # 清楚越界的子弹,防止占用内存 # 遍历子弹编组的副本,在副本中检查每颗子弹,判断是否到顶端 for bullet in bullets.copy(): # 如果子弹到顶端则删除 if bullet.rect.bottom<=0: bullets.remove(bullet) # print(len(bullets)) # 打印输出剩余的子弹数量 check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets) def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets): # groupcollide遍历编组bullets中的所有子弹和编组aliens中的所有外星人。 # 当有子弹和外星人的rect重叠时,groupcollide返回一个键值对 collisions = pygame.sprite.groupcollide(bullets,aliens,True,True) if len(aliens) ==0 : # 删除现有的子弹并创建一群外星人 bullets.empty() create_fleet(ai_settings,screen,ship,aliens) def fire_bullet(ai_settings, screen, ship, bullets): # 如果还没有到达限制,就发射一颗子弹 # 创建一颗子弹,并将其加入到编组bullets中 # 按下空格时,发射子弹,并且限制子弹数量 if len(bullets) < ai_settings.bullets_allowed: new_bullet = Bullet(ai_settings, screen, ship) bullets.add(new_bullet) # 获取外星人数量 def get_number_aliens_x(ai_settings,alien_width): # 计算每行可容纳多少个外星人 # 计算外星人可创建的区域,与屏幕边缘有边距 available_space_x = ai_settings.screen_width - 2*alien_width # 计算一行可用放的外星人数量 number_aliens_x = int(available_space_x / (2*alien_width)) return number_aliens_x def get_number_rows(ai_settings,ship_height,alien_height): # 计算屏幕可容纳多少行外星人 available_space_y = (ai_settings.screen_height - (3*alien_height)-ship_height) number_rows = int(available_space_y / (2*alien_height)) return number_rows # 创建外星人 def create_alien(ai_settings,screen,aliens,alien_number,row_number): # 创建一个外星人并将其放在当前行 alien = Alien(ai_settings,screen) alien_width = alien.rect.width alien.x = alien_width +2*alien_width * alien_number alien.rect.x = alien.x 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 aliens.add(alien) def create_fleet(ai_settings,screen,ship,aliens): # 创建外星人群 # 创建一个外星人,并计算一行可以容纳多少个外星人 # 外星人间距为外星人的宽度 alien = Alien(ai_settings,screen) # 创建一个外星人 number_aliens_x = get_number_aliens_x(ai_settings,alien.rect.width) number_rows = get_number_rows(ai_settings,ship.rect.height,alien.rect.height) # 创建第一行外星人 for row_number in range(number_rows): for alien_number in range(number_aliens_x): # 创建一个外星人并将其加入当前行 create_alien(ai_settings,screen,aliens,alien_number,row_number) def check_fleet_edges(ai_settings,aliens): # 有外星人到达边缘时采取相应的措施 for alien in aliens.sprites(): if alien.check_edges(): change_fleet_direction(ai_settings,aliens) break def change_fleet_direction(ai_settings,aliens): # 将整群外星人下移, 并改变它们的方向 for alien in aliens.sprites(): alien.rect.y += ai_settings.fleet_drop_speed ai_settings.fleet_direction *=-1 def update_aliens(ai_settings,stats,screen,ship,aliens,bullets): # 检查外星人是否到达边缘 check_fleet_edges(ai_settings,aliens) # 更新外星人群中所有外星人的位置 aliens.update() # 检测外星人和飞船之间的碰撞 # spritecollideany接受两个参数,一个精灵和一个编组。 # 它检查编组是否有成员与精灵发生了碰撞,如果没有发生碰撞,返回None if pygame.sprite.spritecollideany(ship,aliens): print("Ship hit!!!") if pygame.sprite.spritecollideany(ship,aliens): ship_hit(ai_settings,stats,screen,ship,aliens,bullets) check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets) def ship_hit(ai_settings,stats,screen,ship,aliens,bullets): # 响应被外星人撞到的飞船 # 将ships_left减1 if stats.ships_left > 0: stats.ships_left -= 1 # 清空外星人列表和子弹列表 aliens.empty() bullets.empty() # 创建一群新的外星人, 并将飞船放到屏幕底端中央 create_fleet(ai_settings,screen,ship,aliens) ship.center_ship() # 暂停 sleep(0.5) else: stats.geme_active = False def check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets): # 检查是否有外星人到达了屏幕底端 screen_rect = screen.get_rect() for alien in aliens.sprites(): if alien.rect.bottom >= screen_rect.bottom: # 像飞船被撞到一样进行处理 ship_hit(ai_settings,stats,screen,ship,aliens,bullets) break
# 跟踪游戏统计信息的类,记录飞船被撞了多少次
# 在游戏运行期间之创建一个GamStats类,但当玩
# 家开始游戏时,需要重置一些统计信息,所有用
# reset_stats来初始化大部分信息
class GamStats():
# 跟踪游戏的统计信息
def __init__(self,ai_settings):
# 初始化统计信息
self.ai_settings = ai_settings
self.reset_stats()
self.game_active= True
def reset_stats(self):
# 初始化在游戏运行期间可能变化的统计信息
self.ships_left = self.ai_settings.ship_limit
import sys import pygame from setting import Settings from pygame.sprite import Group from ship import Ship import game_functions as gf from alien import Alien from game_stats import GamStats def run_game(): # 初始化游戏并创建一个屏幕对象 pygame.init() #初始化背景设置 ai_settings = Settings() screen = pygame.display.set_mode( (ai_settings.screen_width, ai_settings.screen_height)) #创建一个sceen窗口 pygame.display.set_caption("Alien Invasion") # 创建一个用于存储游戏统计信息的实例 stats = GamStats(ai_settings) #创建一艘飞船 ship = Ship(ai_settings,screen) # 创建一个外星人 alien = Alien(ai_settings,screen) #设置背景颜色 bg_color = (230, 230, 230) # 创建一个用于存储子弹的编组,存储所有有效的子弹, # 管理发射出去的子弹 bullets = Group() # 创建一个空编组,用于存储全部外星人 aliens=Group() # 创建外星人群 gf.create_fleet(ai_settings,screen,ship,aliens) #开始游戏的主循环 #循环控制管理屏幕更新 while True: gf.check_events(ai_settings,screen,ship,bullets) if stats.game_active: ship.update() # 更新子弹运行轨迹 gf.update_bullets(ai_settings,screen,ship,aliens,bullets) gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # 更新外星人位置 gf.update_screen(ai_settings, screen, ship,aliens,bullets) run_game()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。