做了两种方式,一种屏幕绘制子弹,一种图片版,屏幕绘制版在代码内加了注释部分
ps:为了和子弹适配,换了彩色飞机~呃 在某宝淘了一整份飞机大战素材,结果有一大部分在linux上查看不了的痛谁能懂,懒得换电脑,就这样凑合着来吧 哈哈
设置模块做了一些更改,添加了子弹设置
"""
#子弹设置
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = (60,60,60)
self.bullet_speed_factor = 1
self.bullets_allowed = 15
"""
#子弹设置(图片版)
self.bullet_speed_factor = 1
self.bullets_allowed = 15
self.bullet_image = pygame.image.load('images/bullet.png')
子弹模块部分导入了精灵类,以便子弹以编组的形式存在,可同时操作编组中的所有元素
"""
存储bullet类,导入sprite(精灵类)
2019/12/6
方法__init__()是一个特殊的方法,每次创建新实例时,python都会自动运行它。
python调用__init__()方法创建实例的时候,将自动传入实参self,每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用
让实例能够访问类中的属性和方法
以self为前缀的变量都可供类中的所有方法使用,还可以通过类的任何实例来访问这些变量
"""
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
"""一个对飞船发射子弹进行管理的类"""
def __init__(self,screen,ship,ai_settings):
"""在飞船所处的位置创建一个子弹对象"""
super().__init__()#调用super()继承sprite类
self.screen = screen
#在(0,0)处创建一个表示子弹的矩形,在设置正确的位置
#self.rect = pygame.Rect(0,0,ai_settings.bullet_width,ai_settings.bullet_height)
#图片版子弹
self.bullet = ai_settings.bullet_image
self.rect = self.bullet.get_rect()
self.rect.centerx = ship.rect.centerx
self.rect.bottom = 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)
#图片版
self.screen.blit(self.bullet,self.rect)
"""
目的:存储让《外星人入侵》运行的函数
日期:2019/12/4
"""
import sys
import pygame
from bullet import Bullet
def check_events(screen,ai_settings,ship,bullets):
"""响应按键和鼠标事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
check_keydown_events(event,screen,ai_settings,ship,bullets)
if event.type == pygame.KEYUP:
check_keyup_events(event,ship)
def check_keydown_events(event,screen,ai_settings,ship,bullets):
"""响应按键事件"""
if event.key == pygame.K_RIGHT:
#向右移动飞船
ship.moving_right = True
if event.key == pygame.K_LEFT:
ship.moving_left = True
if event.key == pygame.K_UP:
ship.moving_up = True
if event.key == pygame.K_DOWN:
ship.moving_down = True
if event.key == pygame.K_SPACE:
fire_bullet(bullets,screen,ship,ai_settings)
def check_keyup_events(event,ship):
"""响应松开"""
if event.key == pygame.K_RIGHT:
ship.moving_right = False
if event.key == pygame.K_LEFT:
ship.moving_left = False
if event.key == pygame.K_UP:
ship.moving_up = False
if event.key == pygame.K_DOWN:
ship.moving_down = False
def fire_bullet(bullets,screen,ship,ai_settings):
"""如果没有到达限制,就发射一颗子弹"""
if len(bullets) <= ai_settings.bullets_allowed:
#创建一个子弹,并将其添加到编组中
new_bullet = Bullet(screen,ship,ai_settings)
bullets.add(new_bullet)
def update_bullets(bullets):
"""更新子弹位置,并删除已消失的子弹"""
#更新子弹位置
bullets.update()
#删除已消失的子弹
for bullet in bullets.copy():
#在for循环中不应从列表或编组中直接删除条目,因此必须遍历编组的副本,所以使用了方法copy()来设置for循环
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
def update_screen(ai_settings,screen,ship,bullets):
"""更新屏幕上的图像,并切换到新屏幕"""
#每次循环是都重绘屏幕
screen.fill(ai_settings.bg_color)
#绘制背景图片
#screen.blit(ai_settings.bg_image,(0,0))
ship.blitme()
#在飞船和外星人后面重绘所有子弹
for bullet in bullets.sprites():#方法bullets.sprites()返回一个列表,其中包含编组bullets的所有精灵
bullet.draw_bullet()
#让最近绘制的屏幕可见
pygame.display.flip()
主文件导入了pygame.sprite中的Group,对子弹进行编组
game_function中增加了关于子弹部分的函数,while循环中的调用进行了相应修改
#--snip--
from pygame.sprite import Group
#--snip--
#创建一个用于存放子弹的编组
bullets = Group()
#开始游戏的主循环
while True:
gf.check_events(screen,ai_settings,ship,bullets)#事件检查
gf.update_bullets(bullets)#更新子弹
ship.update()#飞船位置更新
gf.update_screen(ai_settings,screen,ship,bullets)#更新屏幕