这里以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 我私发给你们