import random
import pygame, sys
class AudioManage:
@staticmethod
def play_bg_music():
"""
背景音乐
"""
pygame.mixer.music.load("sound/bgm.wav")
pygame.mixer.music.play(True)
@staticmethod
def play_sound(name):
"""
音效
"""
sound = pygame.mixer.Sound(name)
sound.play()
class NormalAnimateMixin:
normal_images = []
def __init__(self):
self.images1 = [pygame.image.load(name) for name in self.normal_images]
self.normal_index = 0
def update_normal_images(self):
self.normal_index += 1
if self.normal_index == len(self.normal_images) * 2:
self.normal_index = 0
self.image = self.images1[self.normal_index // 2]
class DestAnimateMixin:
destroy_images = []
def __init__(self):
self.images2 = [pygame.image.load(name) for name in self.destroy_images]
self.destroy_index = 0
if not self.destroy_images:
raise Exception("destroy_images 为空")
def update_destroy_images(self):
self.destroy_index += 1
if self.destroy_index < len(self.destroy_images) * 5:
self.image = self.images2[self.destroy_index // 5]
else:
self.kill()
class BaseSprite(pygame.sprite.Sprite):
def __init__(self, name):
super().__init__()
self.image = pygame.image.load(name)
self.rect = self.image.get_rect()
def update(self):
pass
# 道具精灵类
class PropSprite(BaseSprite):
def __init__(self, name, speed, type):
super().__init__(name)
self.speed = speed
self.type = type
self.rect.left = random.randint(0, 480 - self.rect.width)
self.rect.bottom = 0
def update(self):
self.rect.top += self.speed
if self.rect.top >= 700:
self.kill()
# 道具管理类
class PropManage:
def __init__(self, gm):
self.gm = gm
self.prop_group = pygame.sprite.Group()
self.time = 5
# 道具生成
def generate(self):
value = random.random()
# 道具生成概率
if value > 0.7:
PropSprite("images/life.png", 7, 1).add(self.prop_group)
elif value > 0.4:
PropSprite("images/bomb_supply.png", 7, 2).add(self.prop_group)
else:
PropSprite("images/bullet_supply.png", 7, 3).add(self.prop_group)
# 清空道具
def clear(self):
self.prop_group.empty()
def update(self):
self.time -= 0.1
if self.time <= 0:
self.time = 5
self.generate()
self.prop_group.draw(self.gm.screen)
self.prop_group.update()
# 敌人精灵类
class EnemySprite(BaseSprite, DestAnimateMixin):
destroy_images = [f"images/enemy1_down{i}.png" for i in range(1, 5)]
def __init__(self, name, speed, hp, type, gm):
super().__init__(name)
DestAnimateMixin.__init__(self)
self.gm = gm
self.max_hp = hp
self.hp = hp
self.rect.left = random.randint(0, 480 - self.rect.width)
self.speed = speed
self.rect.bottom = 0
self.buller_group = pygame.sprite.Group()
self.shoot_time = 2
self.type = type
self.is_alive = True
self.value = random.choice([-5, 5])
def shoot(self):
BulletSprite("images/bullet2.png", self.rect.centerx, self.rect.bottom + 20, -10).add(self.buller_group)
def shoot2(self):
for i in range(3):
BulletSprite("images/bullet2.png", self.rect.centerx + 10 - i * 20 / 2, self.rect.bottom + 10, -10).add(
self.buller_group)
def shoot3(self):
for i in range(7):
BulletSprite("images/bullet2.png", self.rect.centerx + 30 - i * 20 / 2, self.rect.bottom + 10, -10).add(
self.buller_group)
def drow_hp(self):
pygame.draw.rect(self.gm.screen, (175, 175, 175),
(self.rect.left + self.rect.width / 2 - 50, self.rect.top - 20, 100, 10))
pygame.draw.rect(self.gm.screen, (0, 255, 0), (
self.rect.left + self.rect.width / 2 - 50, self.rect.top - 20, self.hp / self.max_hp * 100, 10))
def move(self):
self.rect.left += self.value
if self.rect.left <= 0:
self.value = 5
if self.rect.right >= 480:
self.value = -5
def update_image(self):
if self.is_alive:
pass
else:
AudioManage.play_sound("sound/enemy2_down.wav")
self.update_destroy_images()
def update(self):
self.update_image()
self.drow_hp()
self.move()
self.shoot_time -= 0.1
if self.shoot_time <= 0:
self.shoot_time = 2
if self.type == 2:
self.shoot2()
elif self.type == 3:
self.shoot()
else:
self.shoot3()
self.rect.top += self.speed
if self.rect.top >= 700:
self.kill()
self.buller_group.update()
self.buller_group.draw(self.gm.screen)
# 敌人管理类
class EnemyManage:
def __init__(self, gm):
self.gm = gm
self.em_group = pygame.sprite.Group()
self.time = 5
# 敌人出现概率
def generate(self):
value = random.random()
if value > 0.9:
BossEnemySprite("images/enemy3_n1.png", 3, 50, 1, self.gm).add(self.em_group)
elif value > 0.6:
AdvanceEnemySprite("images/enemy2.png", 4, 3, 2, self.gm).add(self.em_group)
else:
EnemySprite("images/enemy1.png", 5, 1, 3, self.gm).add(self.em_group)
def clear(self):
self.em_group.empty()
def update(self):
self.time -= 0.1
if self.time <= 0:
self.time = 5
self.generate()
self.em_group.draw(self.gm.screen)
self.em_group.update()
class AdvanceEnemySprite(EnemySprite):
destroy_images = [f"images/enemy2_down{i}.png" for i in range(1, 5)]
class BossEnemySprite(EnemySprite, NormalAnimateMixin, DestAnimateMixin):
normal_images = ["images/enemy3_n1.png", "images/enemy3_n2.png"]
destroy_images = [f"images/enemy3_down{i}.png" for i in range(1, 7)]
def __init__(self, name, speed, hp, type, gm):
EnemySprite.__init__(self, name, speed, hp, type, gm)
NormalAnimateMixin.__init__(self)
DestAnimateMixin.__init__(self)
def update_image(self):
if self.is_alive:
self.update_normal_images()
else:
AudioManage.play_sound("sound/enemy3_down.wav")
self.update_destroy_images()
def update(self):
EnemySprite.update(self)
self.update_image()
# 子弹精灵类
class BulletSprite(BaseSprite):
def __init__(self, name, centerx, y, speed):
super().__init__(name)
self.rect.centerx = centerx
self.rect.top = y
self.speed = speed
def update(self):
self.rect.top -= self.speed
if self.rect.top >= 700 or self.rect.top <= 0:
self.kill()
# 玩家精灵类
class PlayerSprite(BaseSprite, NormalAnimateMixin):
normal_images = ["images/me1.png", "images/me2.png"]
def __init__(self, name, center, hp, gm):
BaseSprite.__init__(self, name)
NormalAnimateMixin.__init__(self)
self.gm = gm
self.max_hp = hp
self.hp = hp
self.rect.center = center
self.speed = 10
self.buller_group = pygame.sprite.Group()
self.shoot_time = 1
self.super_bullet = 0
def shoot2(self):
AudioManage.play_sound("sound/bullet.wav")
BulletSprite("images/bullet2.png", self.rect.centerx, self.rect.top - 30, 10).add(self.buller_group)
AudioManage.play_sound("sound/bullet.wav")
def shoot(self):
AudioManage.play_sound("sound/bullet.wav")
for i in range(5):
BulletSprite("images/bullet2.png", self.rect.centerx + 10 - i * 20 / 2, self.rect.top - 30, 10).add(
self.buller_group)
def update(self):
NormalAnimateMixin.update_normal_images(self)
self.shoot_time -= 0.1
if self.shoot_time <= 0:
self.shoot_time = 1
if self.super_bullet > 0:
self.shoot()
self.super_bullet -= 1
if self.super_bullet <= 0:
self.shoot2()
# 玩家移动
key_pressed = pygame.key.get_pressed()
if key_pressed[pygame.K_LEFT] and self.rect.left > 0:
self.rect.left -= self.speed
if key_pressed[pygame.K_RIGHT] and self.rect.right < 480:
self.rect.left += self.speed
if key_pressed[pygame.K_UP] and self.rect.top > 0:
self.rect.top -= self.speed
if key_pressed[pygame.K_DOWN] and self.rect.bottom < 700:
self.rect.top += self.speed
self.buller_group.update()
self.buller_group.draw(self.gm.screen)
# 玩家管理类
class PlayerManage:
def __init__(self, gm):
self.gm = gm
self.pm_group = pygame.sprite.Group()
self.player_sprite = PlayerSprite("images/me1.png", (180, 600), 5, self.gm)
self.player_sprite.add(self.pm_group)
AudioManage.play_bg_music()
def delete(self):
self.pm_group.empty()
self.gm.state = "end"
def generate(self):
self.pm_group = pygame.sprite.Group()
self.player_sprite = PlayerSprite("images/me1.png", (180, 600), 5, self.gm)
self.player_sprite.add(self.pm_group)
def update(self):
self.pm_group.draw(self.gm.screen)
self.pm_group.update()
# 背景精灵类
class BgSprite(BaseSprite):
def __init__(self, name, top_left):
super().__init__(name)
self.rect.topleft = top_left
def update(self):
self.rect.top += 3
if self.rect.top >= 700:
self.rect.top = -700
# 背景管理类
class BgManage:
def __init__(self, gm):
self.gm = gm
self.bm_group = pygame.sprite.Group()
BgSprite("images/background.png", (0, 0)).add(self.bm_group)
BgSprite("images/background.png", (0, -700)).add(self.bm_group)
def update(self):
self.bm_group.update()
self.bm_group.draw(self.gm.screen)
class Util:
"""
工具类: 提供静态方法
"""
@staticmethod
def click_check(sprite):
"""
精灵的点击检测
"""
if pygame.mouse.get_pressed()[0]:
if sprite.rect.collidepoint(pygame.mouse.get_pos()):
return True
return False
# UI精灵类
class UISprite(BaseSprite):
def __init__(self, name, center):
super().__init__(name)
self.rect.center = center
class UIManage:
def __init__(self, gm):
self.gm = gm
self.randey_group = pygame.sprite.Group()
self.begin_btn = UISprite("img/begin_btn.png", (240, 350))
self.begin_btn.add(self.randey_group)
# 设置字体
self.font = pygame.font.Font("font/msyh.ttc", 16)
# 游戏中显示分数
self.gaming_group = pygame.sprite.Group()
self.scare_surface = self.font.render(f"分数:{self.gm.score}", True, (255, 255, 0))
self.hp_surface = self.font.render(f"血量:{self.gm.player_manage.player_sprite.hp}", True, (225, 0, 225))
# 游戏后
self.end_group = pygame.sprite.Group()
self.replay_btn = UISprite("images/again.png", (240, 350))
self.replay_btn.add(self.end_group)
def update(self):
# 未进入
if self.gm.state == "ready":
self.randey_group.draw(self.gm.screen)
if Util.click_check(self.begin_btn):
AudioManage.play_sound("sound/click.mp3")
self.gm.state = "gaming"
# 游戏中
if self.gm.state == "gaming":
self.gaming_group.draw(self.gm.screen)
self.gm.screen.blit(self.scare_surface, (400, 20))
self.scare_surface = self.font.render(f"分数:{self.gm.score}", True, (255, 0, 0))
self.gm.screen.blit(self.hp_surface, (400, 40))
self.hp_surface = self.font.render(f"血量:{self.gm.player_manage.player_sprite.hp}", True, (225, 0, 225))
# 游戏结束
if self.gm.state == "end":
self.gm.screen.blit(self.scare_surface, (200, 250))
self.scare_surface = self.font.render(f"分数:{self.gm.score}", True, (255, 0, 0))
self.end_group.draw(self.gm.screen)
self.gm.enemy_manage.clear()
self.gm.prop_mamage.clear()
if Util.click_check(self.replay_btn):
AudioManage.play_sound("sound/click.mp3")
self.gm.state = "gaming"
self.gm.player_manage.player_sprite.hp = self.gm.player_manage.player_sprite.max_hp
self.gm.score = 0
self.gm.enemy_manage.generate()
self.gm.prop_mamage.generate()
self.gm.player_manage.generate()
class GameManage:
def __init__(self):
pygame.init()
self.state = "ready"
self.score = 0
self.clock = pygame.time.Clock()
self.screen = pygame.display.set_mode((480, 700))
pygame.display.set_caption("飞机大战")
self.bg_manage = BgManage(self)
self.player_manage = PlayerManage(self)
self.enemy_manage = EnemyManage(self)
self.prop_mamage = PropManage(self)
self.ui_manage = UIManage(self)
# 碰撞检测
def check_collider(self):
player_bullet_enemy_collider = pygame.sprite.groupcollide(self.player_manage.player_sprite.buller_group,
self.enemy_manage.em_group, True, False)
if player_bullet_enemy_collider:
for events in player_bullet_enemy_collider.values():
for event in events:
event.hp -= 1
if event.hp <= 0:
event.is_alive = False
self.score += 1
for enemy in self.enemy_manage.em_group.sprites():
enemy_bullet_player_bullet_collider = pygame.sprite.groupcollide(enemy.buller_group,
self.player_manage.player_sprite.buller_group,
True, True)
if enemy_bullet_player_bullet_collider:
pass
for enemy in self.enemy_manage.em_group.sprites():
enemy_bullet_playe_collider = pygame.sprite.groupcollide(enemy.buller_group, self.player_manage.pm_group,
True, False)
if enemy_bullet_playe_collider:
self.player_manage.player_sprite.hp -= 1
# self.ui_manage.gaming_group.remove(self.ui_manage.gaming_group.sprites()[-1])
if self.player_manage.player_sprite.hp <= 0:
self.player_manage.delete()
enemy_player_collider = pygame.sprite.groupcollide(self.enemy_manage.em_group, self.player_manage.pm_group,
True, False)
if enemy_player_collider:
pass
prop_player_collider = pygame.sprite.groupcollide(self.player_manage.pm_group, self.prop_mamage.prop_group,
False, True)
if prop_player_collider:
for props in prop_player_collider.values():
for prop in props:
if prop.type == 3:
self.player_manage.player_sprite.super_bullet = 10
if prop.type == 2:
for enemy in self.enemy_manage.em_group.sprites():
AudioManage.play_sound("sound/use_bomb.wav")
enemy.kill()
self.score += len(self.enemy_manage.em_group.sprites())
if prop.type == 1:
self.player_manage.player_sprite.hp += 1
if self.player_manage.player_sprite.hp >= self.player_manage.player_sprite.max_hp:
self.player_manage.player_sprite.hp = self.player_manage.player_sprite.max_hp
def check_event(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# 测试功能 一键杀死
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
self.state = "end"
self.player_manage.delete()
def run(self):
while True:
self.clock.tick(20)
self.check_event()
self.bg_manage.update()
self.ui_manage.update()
if self.state == "gaming":
self.player_manage.update()
self.enemy_manage.update()
self.check_collider()
self.prop_mamage.update()
pygame.display.flip()
gm = GameManage()
gm.run()