python 面向对象版飞机大战

本文详细介绍了使用Python的pygame库开发的一款2D飞机大战游戏,包括背景音乐、音效、精灵(角色和道具)、碰撞检测以及用户界面管理等关键部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值