如何使用面向对象制作小游戏

这里以pygame做飞机大战来讲解

不墨迹 直接上成品源码        有看不懂的可以评论或这私我 可以细讲

window11

pygame

pycharm

1 新建一个总的游戏管理类

class GameManage:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((SCREEN_W, SCREEN_H))
        pygame.display.set_caption('星空飞机大战')
        self.clock = pygame.time.Clock()
        self.state = 'ready'

        self.bg_manage = BGManage(self)
        self.player_manage = PlayerManage(self)
        self.ui_manage = UIManage(self)
        self.enemy_manage = EnemyManage(self)
        self.prop_manage = ProManage(self)

    def check_event(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()


    def draw_update(self):
        self.bg_manage.update()
        self.ui_manage.update()
        if self.state == 'gaming':
            self.player_manage.update()
            self.enemy_manage.update()
            self.prop_manage.update()

    def collide_event(self):
        # 玩家和补给的碰撞检测
        player_prop_collide = pygame.sprite.groupcollide(self.player_manage.player_group, self.prop_manage.prop_group,
                                                         False, True)
        # print(player_prop_collide)
        for props in player_prop_collide.values():
            for prop in props:
                if prop.type == 1:
                    AudioManage.play_sound('sound/get_bomb.wav')
                    AudioManage.play_sound('sound/use_bomb.wav')
                    AudioManage.play_sound('sound/enemy3_flying.wav')
                    for enemy in self.enemy_manage.enemy_group.sprites():
                        if enemy.type == 1:
                            self.player_manage.score += 5
                            AudioManage.play_sound('sound/upgrade.wav')
                            AudioManage.play_sound('sound/enemy3_flying.wav')
                            AudioManage.play_sound('sound/enemy3_down.wav')
                            enemy.kill()
                        elif enemy.type == 2:
                            self.player_manage.score += 3
                            AudioManage.play_sound('sound/enemy3_flying.wav')
                            AudioManage.play_sound('sound/enemy2_down.wav')
                            AudioManage.play_sound('sound/upgrade.wav')
                            enemy.kill()
                        else:
                            self.player_manage.score += 1
                            AudioManage.play_sound('sound/enemy3_flying.wav')
                            AudioManage.play_sound('sound/enemy1_down.wav')
                            AudioManage.play_sound('sound/upgrade.wav')
                            enemy.kill()

                elif prop.type == 2:
                    AudioManage.play_sound('sound/get_bullet.wav')
                    self.player_manage.player.shoot2()
                    # if self.player_manage.player.shoot2():
                    #     self.enemy_manage.is_alive = False
                else:
                    AudioManage.play_sound('sound/supply.wav')
                    self.player_manage.player.hp += 1
                    if self.player_manage.player.hp >= self.player_manage.player.max_hp:
                        self.player_manage.player.hp = self.player_manage.player.max_hp

        # 玩家子弹和敌人的碰撞
        player_bullet_enemy_collide = pygame.sprite.groupcollide(self.player_manage.player.bullet_group,
                                                                 self.enemy_manage.enemy_group, True, False)
        if player_bullet_enemy_collide:
            # print(player_bullet_enemy_collide)
            for enemys in player_bullet_enemy_collide.values():
                for enemy in enemys:
                    AudioManage.play_sound('sound/enemy3_flying.wav')
                    enemy.hp -= 1
                    if enemy.hp <= 0:
                        if enemy.is_alive:
                            if enemy.type == 1:
                                self.player_manage.score += 5
                                AudioManage.play_sound('sound/enemy3_down.wav')
                                AudioManage.play_sound('sound/upgrade.wav')
                            elif enemy.type == 2:
                                self.player_manage.score += 3
                                AudioManage.play_sound('sound/enemy2_down.wav')
                                AudioManage.play_sound('sound/upgrade.wav')
                            else:
                                self.player_manage.score += 1
                                AudioManage.play_sound('sound/enemy1_down.wav')
                                AudioManage.play_sound('sound/upgrade.wav')
                        enemy.is_alive = False

        player_bullet_enemy_collide2 = pygame.sprite.groupcollide(self.player_manage.player.super_bullet_group,
                                                                 self.enemy_manage.enemy_group, False, True)





        # 玩家和敌人子弹的碰撞
        for enemy in self.enemy_manage.enemy_group.sprites():
            player_enemy_bullet_collide = pygame.sprite.groupcollide(self.player_manage.player_group,
                                                                     enemy.bullet_group, False, True)
            if player_enemy_bullet_collide:
                self.player_manage.player.hp -= 1
                if self.player_manage.player.hp <= 0:
                    self.state = 'end'
                    self.player_manage.player_group.empty()
                    self.enemy_manage.enemy_group.empty()
                    self.prop_manage.prop_group.empty()
                    AudioManage.play_sound('sound/me_down.wav')
        # 玩家和敌人的碰撞
        player_enemy_collide = pygame.sprite.groupcollide(self.player_manage.player_group,
                                                          self.enemy_manage.enemy_group, False, True)
        print(player_enemy_collide)
        if player_enemy_collide:
            self.player_manage.player.hp -= 3
            if self.player_manage.player.hp <= 0:
                self.state = 'end'
                self.player_manage.player_group.empty()
                self.enemy_manage.enemy_group.empty()
                self.prop_manage.prop_group.empty()
                AudioManage.play_sound('sound/me_down.wav')

    def run(self):
        while True:
            self.clock.tick(24)
            self.check_event()
            self.draw_update()
            self.collide_event()

            pygame.display.flip()

2.新建一个基础精灵父类 继承pygame.sprite.Sprite

class BaseSprite(pygame.sprite.Sprite):
    """所有精灵类的父类"""

    def __init__(self, name_img):  # 图片url:name_img
        super().__init__()
        self.image = pygame.image.load(name_img)
        self.rect = self.image.get_rect()

    def update(self):
        pass

3.新建一个BG精灵类 和BG管理类 用于背景图片的调控

class BGSprite(BaseSprite):
    def __init__(self, name_img, topleft):
        super().__init__(name_img)  # topleft: 图片url的左上角
        self.rect.topleft = topleft
        self.speed = BG_IMG_SPEED  # speed: 图片速度

    def update(self):
        """更新图片位移"""
        self.rect.bottom += self.speed
        if self.rect.top >= 700:
            self.rect.top = -700


class BGManage:
    def __init__(self, gm):
        self.gm = gm
        self.bg_group = pygame.sprite.Group()  # bg精灵组
        BGSprite('images2/bg_img.jpeg', (0, 0)).add(self.bg_group)
        BGSprite('images2/bg_img.jpeg', (0, -700)).add(self.bg_group)

    def update(self):
        self.bg_group.update()
        self.bg_group.draw(self.gm.screen)

4.新建一个UI精灵类 和UI管理类 用于调控游戏的游戏前 游戏中 游戏结束的三种状态

class UISprite(BaseSprite):
    def __init__(self, name_img, center):
        super().__init__(name_img)
        self.rect.center = center

    def update(self):
        pass

class UIManage:
    def __init__(self, gm):
        self.gm = gm

        self.font = pygame.font.Font(UIS_FONT_URL, FONT_SIZE)

        # 游戏开始前
        self.begin_group = pygame.sprite.Group()
        self.begin_btn = UISprite('images2/begin_btn.png', (500, 350))
        self.begin_btn.add(self.begin_group)
        # 游戏中
        self.font_surface = self.font.render(f'当前得分:{self.gm.player_manage.score}', True, (255, 0, 0))

        # 游戏结束
        self.end_group = pygame.sprite.Group()
        self.again_btn = UISprite('images/again.png', (500, 350))
        self.again_btn.add(self.end_group)

    def update(self):
        if self.gm.state == 'ready':
            AudioManage.bg_play_music()
            self.begin_group.draw(self.gm.screen)
            self.begin_group.update()
            if Toolkit.mouse_click(self.begin_btn):
                AudioManage.play_sound('sound/begin.mp3')
                self.gm.state = 'gaming'
        elif self.gm.state == 'gaming':
            self.font_surface = self.font.render(f'当前得分:{self.gm.player_manage.score}', True, (255, 0, 0))
            self.gm.screen.blit(self.font_surface, (800, 80))

            get_pressed = pygame.key.get_pressed()
            if get_pressed[pygame.K_SPACE]:
                self.gm.player_manage.player.shoot1()
                AudioManage.play_sound('sound/bullet.wav')

            if get_pressed[pygame.K_ESCAPE]:
                self.gm.player_manage.player.shoot2()

        else:
            self.end_group.draw(self.gm.screen)
            self.end_group.update()
            if Toolkit.mouse_click(self.again_btn):
                AudioManage.play_sound('sound/begin.mp3')
                self.gm.state = 'gaming'
                self.gm.player_manage.birth()

5 建立玩家Playe精灵类 和玩家管理类

        子弹的管理在玩家中 讲子弹与玩家的rect绑定在一起 就可以形成发射

class PlayerSprite(BaseSprite, NormalAnimateMixin):
    normal_images = ['images2/player_plane.png', 'images2/player_plane2.png']

    def __init__(self, name_img, center, gm):
        super().__init__(name_img)
        NormalAnimateMixin.__init__(self)
        self.gm = gm
        self.rect.center = center
        self.hp = 100
        self.max_hp = 100

        # 初始化子弹组
        self.bullet_group = pygame.sprite.Group()
        # 初始化超级子弹组
        self.super_bullet_group = pygame.sprite.Group()

    # 设置血条
    def set_hp(self):
        pygame.draw.rect(self.gm.screen, (127, 127, 127), (self.rect.left + 26, self.rect.top + 125, 120, 20))
        pygame.draw.rect(self.gm.screen, (0, 255, 0),
                         (self.rect.left + 26, self.rect.top + 125, self.hp / self.max_hp * 120, 20))

    def shoot1(self):
        BulletSprite('images2/player_bullet.png', self.rect.center, 5).add(self.bullet_group)

    def shoot2(self):
        BulletSprite('images2/laser.png', self.rect.center, 5).add(self.super_bullet_group)

    # def shoot3(self):
    #     for i in range(10):
    #         BulletSprite('images2/pilosity.png', (self.rect.centerx + i*5, self.rect.centery))

    def update(self):

        NormalAnimateMixin.update_normal_images(self)

        self.set_hp()

        get_pressed = pygame.key.get_pressed()
        if get_pressed[pygame.K_LEFT] and self.rect.left >= 0:
            self.rect.left -= 25
        if get_pressed[pygame.K_RIGHT] and self.rect.right <= 1000:
            self.rect.left += 25
        if get_pressed[pygame.K_UP] and self.rect.top >= 0:
            self.rect.top -= 25
        if get_pressed[pygame.K_DOWN] and self.rect.bottom <= 710:
            self.rect.top += 25

        # 更新子弹
        self.bullet_group.draw(self.gm.screen)
        self.bullet_group.update()
        self.super_bullet_group.draw(self.gm.screen)
        self.super_bullet_group.update()


class PlayerManage:
    def __init__(self, gm):
        self.gm = gm
        self.player_group = pygame.sprite.Group()
        self.birth()
        self.score = 0

    def birth(self):
        self.player = PlayerSprite('images2/player_plane.png', (800, 500), self.gm)
        self.player.add(self.player_group)

    def update(self):
        self.player_group.draw(self.gm.screen)
        self.player_group.update()

6.新建一个子弹精灵类  --管理类在玩家和敌人中

class BulletSprite(BaseSprite):
    def __init__(self, name_img, center, speed):
        super().__init__(name_img)
        self.rect.center = center
        self.speed = speed  # # speed:子弹发射的速度

    def update(self):
        self.rect.top -= self.speed
        if self.rect.top > 700:
            self.kill()  # 如果子弹出界 则删除子弹

7.新建敌人精灵和敌人管理类

class EnemySprite(BaseSprite, DestroyAnimateMixin):
    destroy_images = [f'images/enemy1_down{i}.png' for i in range(1, 5)]

    def __init__(self, name_img, speed, hp, type, gm):
        super().__init__(name_img)
        DestroyAnimateMixin.__init__(self)
        self.gm = gm
        self.rect.left = random.randint(0, SCREEN_W - self.rect.width)
        self.rect.bottom = -10
        self.speed = speed
        self.hp = hp
        self.max_hp = hp
        self.is_alive = True
        self.type = type
        self.count_time = 3

        # 敌人子弹组
        self.bullet_group = pygame.sprite.Group()

    def shoot_enemy(self):
        BulletSprite('images/bullet2.png', (self.rect.centerx, self.rect.centery), -10).add(self.bullet_group)

    def set_hp(self):
        pygame.draw.rect(self.gm.screen, (128, 128, 128),
                         (self.rect.left + self.rect.width / 2 - 55, self.rect.bottom + 20, 120, 20))
        pygame.draw.rect(self.gm.screen, (255, 0, 0),
                         (self.rect.left + self.rect.width / 2 - 55, self.rect.bottom + 20, self.hp / self.max_hp * 120,
                          20))

    def update(self):
        self.count_time -= 0.2
        if self.count_time <= 0:
            self.count_time = 3
            self.shoot_enemy()

        if self.is_alive:
            pass
        else:
            self.update_destroy_images()

        self.set_hp()
        self.rect.top += self.speed
        if self.rect.top >= SCREEN_H:
            self.kill()  # 敌人越界杀死
        self.bullet_group.update()
        self.bullet_group.draw(self.gm.screen)


class AdvanceEnemySprite(EnemySprite):
    destroy_images = [f'images/enemy2_down{i}.png' for i in range(1, 5)]


class BossEnemySprite(EnemySprite, NormalAnimateMixin, DestroyAnimateMixin):
    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_img, speed, hp, type, gm):
        super().__init__(name_img, speed, hp, type, gm)

        NormalAnimateMixin.__init__(self)
        DestroyAnimateMixin.__init__(self)

    def update_image(self):
        if self.is_alive:
            self.update_normal_images()
        else:
            self.update_destroy_images()

    def update(self):
        EnemySprite.update(self)
        self.update_image()


class EnemyManage:
    def __init__(self, gm):
        self.gm = gm
        self.enemy_group = pygame.sprite.Group()
        self.count_time = 3
        self.birth()

    def birth(self):
        r = random.random()
        if r >= 0.8:
            BossEnemySprite('images/enemy3_down1.png', 3, 20, 1, self.gm).add(self.enemy_group)
        elif r >= 0.5:
            AdvanceEnemySprite('images/enemy2.png', 5, 15, 2, self.gm).add(self.enemy_group)
        else:
            enemy = EnemySprite('images/enemy1.png', 7, 10, 3, self.gm)
            enemy.add(self.enemy_group)

    def update(self):

        self.count_time -= 0.3
        if self.count_time <= 0:
            self.count_time = 3
            self.birth()

        self.enemy_group.update()
        self.enemy_group.draw(self.gm.screen)

8.新建一个补给精灵类 和补给类

class PropSprite(BaseSprite):
    def __init__(self, name_img, type):
        super().__init__(name_img)
        self.rect.left = random.randint(0, SCREEN_W - self.rect.width)
        self.rect.bottom = -10
        self.speed = 4
        self.type = type

    def update(self):
        self.rect.top += self.speed
        if self.rect.top > SCREEN_H:
            self.kill()  # 越界清除补给


class ProManage:
    def __init__(self, gm):
        self.gm = gm
        self.prop_group = pygame.sprite.Group()
        self.count_time = 3

    def birth(self):
        r = random.random()
        if r >= 0.66:
            PropSprite('images/bomb_supply.png', 1).add(self.prop_group)
        elif r >= 0.33:
            PropSprite('images/bullet_supply.png', 2).add(self.prop_group)
        else:
            PropSprite('images/life.png', 3).add(self.prop_group)

    def update(self):
        self.count_time -= 0.1
        if self.count_time <= 0:
            self.count_time = 3
            self.birth()

        self.prop_group.update()
        self.prop_group.draw(self.gm.screen)

9.封装了一个鼠标点击返回True或False的类 静态方法 类名调用

# 鼠标点击事件
class Toolkit:  # 工具包
    """静态方法 类名调用 鼠标点击"""

    @staticmethod
    def mouse_click(sprite):
        """鼠标点击事件 返回布尔值 """
        if pygame.mouse.get_pressed()[0]:
            if sprite.rect.collidepoint(pygame.mouse.get_pos()):
                return True
        return False

10.封装了两个方法 一个是图片的切换 一个是爆炸效果的切换

class NormalAnimateMixin:
    normal_images = []

    def __init__(self):
        self.images1 = [pygame.image.load(name) for name in self.normal_images]
        self.normal_index = 0
        if not self.normal_images:
            raise Exception('normal_images为空')

    def update_normal_images(self):
        self.normal_index += 1
        if self.normal_index == len(self.normal_images) * 5:
            self.normal_index = 0
        self.image = self.images1[self.normal_index // 5]


class DestroyAnimateMixin:
    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为空')

11.封装一个音乐类 静态方法 类名调用 用来给游戏添加音乐

class AudioManage:
    """音乐包"""

    @staticmethod
    def bg_play_music():
        pygame.mixer.music.load('sound/game_music.ogg')
        pygame.mixer.music.play(True)

    @staticmethod
    def play_sound(name):  # 音乐路径

        sound = pygame.mixer.Sound(name)
        sound.play()

成品演示

开始游戏前:

        

 

 游戏中:

        

 

 游戏结束:

        

 

需要源码以及素材的评论区可扣个1 我私发给你们

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值