看见敌机了,总不能去撞吧,英雄机当然得有子弹了。
子弹的编写,前面的日志里已经写了很多了,这里稍微改一下,直接拿来用吧。
bullet.py
"""
子弹的基类
设置坐标,速度,角度,计算更新后的点的坐标
"""
from setting import *
import math
class Bullet(pygame.sprite.Sprite):
def __init__(self, group):
self._layer = 9
self.groups = allgroup, group
pygame.sprite.Sprite.__init__(self, self.groups)
#必须要的两个初始化
self.image = pygame.image.load('images/bullet/bulletdefault.png').convert()
self.rect = self.image.get_rect()
#用vector来表述,清晰些,子弹的尺寸,用来飞机发射时的位置
self.size = vect(self.rect.width, self.rect.height)
#设置图像的mask属性,碰撞检查时,透明图像就忽略了
self.mask = pygame.mask.from_surface(self.image)
#设置默认的数据参数,速度
self.speed = 4
#笛卡尔坐标系,angle = 90 垂直向下
self.angle = 90
#初始距离和原点坐标
self.distance = 0
self.x_original = 0
self.y_original = 0
#伤害值
self.damage = 1
#继承至sprite,被sprite.Group()加入后,只要调用了sprite的update,这里也会自动调用
def update(self):
"""计算图像位置
先计算单位时间后的距离,通过三角运算,加上原始坐标,即为更新后坐标。
想用pygame.time.get_fps()来计算时间,效果不好,直接写成了1000
"""
#计算距离
self.distance += 1000 * self.speed / 1000
#degree 换成 radian 角度换弧度,用临时变量angle,保障self.angle不被变更
angle = self.angle
angle = math.pi * angle / 180
#计算图像的左上角的x,y,三角函数换算加上原始点坐标
self.rect.x = self.distance * math.cos(angle) + self.x_original
self.rect.y = self.distance * math.sin(angle) + self.y_original
# 用一条语句实现了跑出屏幕的检查,我真是佩服我自己
# 如果子弹和屏幕不相碰,就表示在屏幕外了
#kill()超出屏幕自动删除,从所有sprite组里删除
if not self.rect.colliderect(SCENERECT):
self.kill()
#为了和飞机的位置配合,需要设置初始位置
def set_pos(self, x, y):
"""设置位置
x 左上方x坐标
y 左上方y坐标
"""
self.rect.x = x
self.rect.y = y
#rect.x,y会通过update更新,所以要记录原始点的坐标,用来计算更新后的坐标
self.x_original = x
self.y_original = y
# 为了获取当前坐标,目前位置没用到
def get_pos(self):
"""获取坐标,返回X,Y两个值
x 左上方x坐标
y 左上方y坐标
"""
return (self.rect.x, self.rect.y)
#设置速度、角度
def set_speed(self, speed=4, angle=0):
"""设置速度
speed 速度,为X,Y两个方向的向量和
angel 角度degree(不是弧度radian)
"""
self.speed = speed
self.angle = angle
# # 设置图像,重新计算rect
# def set_image(self, image):
# """ 设置子弹的图像"""
# self.image = image
# self.rect = self.image.get_rect()
# self.mask = pygame.mask.from_surface(self.image)
#设置伤害值
def set_damage(self, damage=1):
""" 设置子弹的伤害值 damage int
"""
self.damage = damage
英雄的子弹,飞行方向和飞行角度与敌人飞机不一致,默认速度在笛卡尔坐标里,往下是正的,90度,因此,往上只要速度改为
负数就行了。很简单吧。
herobullet.py
from setting import *
from animation import *
from bullet import *
class HeroBullet(Bullet):
def __init__(self):
self._layer = 9
self.groups = allgroup, herobulletgroup
Bullet.__init__(self,self.groups)
self.image = pygame.image.load("images/bullet/herobullet0.png").convert_alpha()
self.rect = self.image.get_rect()
self.mask = pygame.mask.from_surface(self.image)
def update(self):
# pass
Bullet.update(self)
def set_bullet_type(self, type=0):
"""设置子弹的类型
子弹的图片存在同一个目录里,以 enemybullet 加 序号 加 .png
type 0~3
"""
self.image_type = type
self.image = pygame.image.load('images/bullet/herobullet'+str(type)+'.png').convert_alpha()
# self.image = self.images[0].convert_alpha()
self.rect= self.image.get_rect()
self.mask = pygame.mask.from_surface(self.image)
让英雄能发射子弹,在heroplane.py里添加,用来设置发射子弹的类型,发射方式
def set_fire_type(self, firetype):
self.fire_type = firetype
def set_bullet_type(self, bullettye):
self.bullet_type = bullettye
def fire_bullet(self):
firetype = self.fire_type
bullettype = self.bullet_type
#hero 子弹的发射位置当然是头部中心
hero_fire_pos = vect(self.rect.midtop[0], self.rect.midtop[1])
#单颗子弹
if firetype == 0:
bullet = HeroBullet()
bullet.set_bullet_type(bullettype)
pos_x = hero_fire_pos.x - bullet.rect.width // 2
pos_y = hero_fire_pos.y-50
bullet.set_speed(self.bullet_speed, angle=90)
bullet.set_pos(pos_x, pos_y)
# 两个
elif firetype == 1:
interval = -self.rect.width // 4
for v in range(0, 2):
bullet = HeroBullet()
bullet.set_bullet_type(bullettype)
pos_x = hero_fire_pos.x - bullet.rect.width // 2 + interval
pos_y = hero_fire_pos.y-50
bullet.set_speed(self.bullet_speed, angle=90)
bullet.set_pos(pos_x, pos_y)
interval = self.rect.width // 4
#三个
elif firetype == 2:
interval = -self.rect.width // 4
for v in range(0, 3):
bullet = HeroBullet()
bullet.set_bullet_type(bullettype)
pos_x = hero_fire_pos.x - bullet.rect.width // 2 + interval
pos_y = hero_fire_pos.y-50
bullet.set_speed(self.bullet_speed, angle=90)
bullet.set_pos(pos_x, pos_y)
interval += self.rect.width // 4
# 向下30度角
elif firetype == 3:
for angle in range(75, 106, 10):
bullet = HeroBullet()
bullet.set_bullet_type(bullettype)
pos_x = hero_fire_pos.x
pos_y = hero_fire_pos.y
bullet.set_speed(self.bullet_speed, angle)
bullet.set_pos(pos_x, pos_y)
#向下 60度角
elif firetype == 4:
for angle in range(60, 121, 10):
bullet = HeroBullet()
bullet.set_bullet_type(bullettype)
pos_x = hero_fire_pos.x
pos_y = hero_fire_pos.y
bullet.set_speed(self.bullet_speed, angle)
bullet.set_pos(pos_x, pos_y)
#向下 90度角
elif firetype == 5:
for angle in range(45, 136, 10):
bullet = HeroBullet()
bullet.set_bullet_type(bullettype)
pos_x = hero_fire_pos.x
pos_y = hero_fire_pos.y
bullet.set_speed(self.bullet_speed, angle)
bullet.set_pos(pos_x, pos_y)
#向下 180度
elif firetype == 6:
for angle in range(0, 181, 10):
bullet = HeroBullet()
bullet.set_bullet_type(bullettype)
pos_x = hero_fire_pos.x
pos_y = hero_fire_pos.y
bullet.set_speed(self.bullet_speed, angle)
bullet.set_pos(pos_x, pos_y)
#360度
elif firetype == 7:
for angle in range(0, 360, 10):
bullet = HeroBullet()
bullet.set_bullet_type(bullettype)
pos_x = hero_fire_pos.x
pos_y = hero_fire_pos.y
bullet.set_speed(self.bullet_speed, angle)
bullet.set_pos(pos_x, pos_y)
在初始函数里,添加子弹的默认值
#子弹类型
self.bullet_type = 0
#发射类型
self.fire_type = 0
英雄机的发射功能齐备,牛刀小试一下。
在main.py里发射
初设化函数里添加
self.hero = HeroPlane(hero_index)
self.hero.set_bullet_type(hero_index)
self.hero.set_fire_type(0)
事件处理函数里添加
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_j:
#普通射击
self.hero.fire_bullet()
碰撞检查函数里添加英雄子弹精灵组和敌人飞机精灵组 的碰撞检查
hero_shot_enemy = pygame.sprite.groupcollide(herobulletgroup,enemygroup,True,True)
看下效果吧。