import gc
import random
import pygame
# Sprite 精灵
from pygame.rect import Rect
import Constants
class HeroPlane(pygame.sprite.Sprite):
def __init__(self, screen):
# 这个精灵的初始化方法 必须调用
pygame.sprite.Sprite.__init__(self)
# 图片
self.image = pygame.image.load('./feiji/feiji.png')
# 根据图片image获取矩形的对象
self.rect = self.image.get_rect() # rect属性:矩形
self.rect.topleft = [512 / 2 - 100 / 2, 600] # 矩形左上角坐
# 窗口
self.screen = screen
# 速度
self.speed = 10
# 根据图片获取mask,属性,方便检测,非透明区域的碰撞
self.mask = pygame.mask.from_surface(self.image)
# 存放子弹的精灵组
self.bullets = pygame.sprite.Group()
# 定义飞机的血量
self.blood_value = 10
# 标记敌机是否挂掉
self.is_remove = False
# 显示爆炸图片的索引 从0开始
self.mIndex = 0
# 存爆炸图片的列表
self.bomb_mImages = []
for v in range(1, 14):
# 每一个存2次 多显示一次,效果更好些
self.bomb_mImages.append(pygame.image.load("./feiji/image " + str(v) + ".png"))
self.bomb_mImages.append(pygame.image.load("./feiji/image " + str(v) + ".png"))
def key_control(self):
"""
按键的监听 用来改变飞机坐标
"""
# 监听键盘事件 键盘一直按下
key_pressed = pygame.key.get_pressed() # 注意这种方式是能够检测到连续按下的,比之前的版本要新
# 改变飞机坐标 512, 768
if key_pressed[pygame.K_w] or key_pressed[pygame.K_UP]:
if self.rect.top < 0:
pass
else:
self.rect.top -= self.speed
if key_pressed[pygame.K_s] or key_pressed[pygame.K_DOWN]:
if self.rect.bottom > 768:
pass
else:
self.rect.bottom += self.speed
if key_pressed[pygame.K_a] or key_pressed[pygame.K_LEFT]:
if self.rect.left < 0:
pass
else:
self.rect.left -= self.speed
if key_pressed[pygame.K_d] or key_pressed[pygame.K_RIGHT]:
if self.rect.right > 512:
pass
else:
self.rect.right += self.speed
if key_pressed[pygame.K_SPACE]:
# 按下空格键
# print('发射子弹')
# 创建三个散弹对象
bullet1 = Bullet(self.screen, self.rect.left, self.rect.top, 1)
bullet2 = Bullet(self.screen, self.rect.left, self.rect.top, 2)
bullet3 = Bullet(self.screen, self.rect.left, self.rect.top, 3)
# 把三个子弹添加到精灵组
self.bullets.add(bullet1, bullet2, bullet3)
def bomb(self):
"""显示爆炸图片"""
self.screen.blit(self.bomb_mImages[self.mIndex], (self.rect.left, self.rect.top))
# 索引+1 下次显示下一张
self.mIndex += 1
print('self.mIndex', self.mIndex)
if self.mIndex >= len(self.bomb_mImages):
# 如果下标已经到最后 代表爆炸结束
# 下标重置 mVisible重置
self.mIndex = 0
# 爆炸结束返回True
return True
# 调用飞机的更新方法
def update(self):
# 判断飞机挂掉
if self.is_remove:
print('挂掉')
# 执行爆炸,并判断爆炸是否结束
if self.bomb():
print('玩家飞机爆炸结束')
# 移出窗口,坐标在窗口外就可以
self.rect.topleft = [-200, -200]
else:
self.key_control()
self.display()
def display(self):
"""显示飞机到窗口,显示子弹等"""
# 显示飞机
self.screen.blit(self.image, self.rect)
# 更新子弹坐标
self.bullets.update()
# 把所有的子弹全部添加到屏幕
self.bullets.draw(self.screen)
def kill_(self, kill_value=10):
"""飞机被打中,每次减10 如果碰到敌机-100"""
self.blood_value -= kill_value
print('被打中,血量剩%s' % self.blood_value)
if self.blood_value <= 0:
self.blood_value = 0 # 如果是负值就显示0
# 标记飞机挂掉
self.is_remove = True
# 开启游戏到期时
pygame.time.set_timer(Constants.game_over_id, 1000) # 开启游戏倒计时
# 子弹类
class Bullet(pygame.sprite.Sprite):
def __init__(self, screen, x, y, path_num):
"""
:param screen: 屏幕对象
:param x: 飞机的左上角x坐标
:param y: 飞机的左上角y坐标
:param path_num: 子弹的弹道序号,目前是三层散弹, 记作1,2,3
"""
pygame.sprite.Sprite.__init__(self)
# 图片
self.image = pygame.image.load('./feiji/zidan.png')
self.rect = self.image.get_rect() # rect属性:矩形
self.rect.topleft = [x + 38, y - 10] # 矩形左上角坐
# 窗口
self.screen = screen
# 速度
self.speed = 25
# 根据图片获取mask,属性,方便检测,非透明区域的碰撞
self.mask = pygame.mask.from_surface(self.image)
# 子弹的弹道序号
self.path_num = path_num
def update(self):
# 修改子弹y坐标
self.rect.top -= self.speed
if self.rect.top < -22:
# 如果子弹移出屏幕上方,则销毁子弹对象
self.kill()
if self.path_num == 1:
pass
elif self.path_num == 2:
# 如果等于2就是散弹中左侧子弹
self.rect.left -= 10
elif self.path_num == 3:
# 如果等于3就是散弹中右侧子弹
self.rect.right += 10
# 敌方飞机
class EnemyPlane(pygame.sprite.Sprite):
"""敌方飞机"""
rect: Rect
# 类属性 存放所有敌机对象的子弹的精灵组
all_bullets = pygame.sprite.Group()
def __init__(self, screen):
pygame.sprite.Sprite.__init__(self)
# 敌方飞机的图片
self.image = pygame.image.load('./feiji/img-plane_4.png') # 51*39
# 获取矩形区域
self.rect = self.image.get_rect()
# 敌机初始坐标 水平位置随机,上下位置在最顶部
self.rect.topleft = [random.randint(0, 512), 0]
# 飞机的速度
self.speed = 5
# 记录当前的窗口对象
self.screen = screen
# 飞机左右飞的方向 一开始向右
self.direction = 'right'
# 根据图片获取mask,属性,方便检测,非透明区域的碰撞
self.mask = pygame.mask.from_surface(self.image)
# 装子弹的列表
self.bullets = pygame.sprite.Group()
# 标记敌机是否被击中
self.is_remove = False
# 显示爆炸图片的索引 从0开始
self.mIndex = 0
# 存爆炸图片的列表
self.bomb_mImages = []
for v in range(1, 14):
# 每一个存2次 多显示一次,效果更好些
self.bomb_mImages.append(pygame.image.load("./feiji/image " + str(v) + ".png"))
self.bomb_mImages.append(pygame.image.load("./feiji/image " + str(v) + ".png"))
def display(self):
"""显示飞机到窗口"""
self.screen.blit(self.image, self.rect)
# 所有子弹更新坐标
self.bullets.update()
# 所有子弹贴到屏幕
self.bull