总流程:
1.先创建一个游戏管理类,用来管理游戏中的玩家,敌人,道具,背景,以及UI和游戏的初始化以及事件检测和游戏的运行等。
2.创建一个最基本的精灵类BaseSprite,方便后面精灵类的继承,该精灵类继承pyga me.sp rit e.Sprite。
3.创建UI精灵类,继承BaseSprite,再写入一个形参center,代表的是UI精灵的矩形区域的中心位置。
4创建UI精灵管理类UiManage,创建游戏前,游戏中,以及游戏后所需要的精灵以及精灵组,再写一个update函数,用来更新游戏状态以及所需要绘制的精灵。
5.创建玩家精灵类PlayerSprite,继承BaseSprite,也要再写入一个形参center,代表的是玩家的中心位置。再写一个update函数用来控制玩家的上下左右的移动。
6.创建玩家管理类PlayerManage,在初始化函数中创建一个玩家精灵组,再写一个出生函数,死亡函数以及更新函数。
7.创建敌人类EnemySprite,继承BaseSprite,给敌人的bottom设为0,left根据屏幕尺寸以及敌人的尺寸进行随机选择,使用random函数。再写一个update函数用来实现敌人从上向下移动。
8.创建敌人管理类EnemyManage,在初始化函数中创建一个敌人精灵组,再i根据需要写敌人不同出生方式的函数,以及更新函数用来更新敌人组将敌人组绘制到屏幕上面。
9.创建一个子弹组BulletSprite,继承BaseSprite,创建一个子弹组,并且写一个更新函数,根据子弹的速度将子弹的位置进行更新。
再根据自己的需要写入道具组等等。代码里面所有关于路径的地方根据自己的实际情况进行更改。
源代码:
import random
import time
import pygame
import sys
class Util:
@staticmethod
def check(sprite):
if pygame.mouse.get_pressed()[0]:
if sprite.rect.collidepoint(pygame.mouse.get_pos()):
AudioSprite.play_sound("sound/click.mp3")
return True
else:
return False
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 UiSprite(BaseSprite):
def __init__(self, name, center):
super().__init__(name)
self.rect.center = center
def update(self):
pass
class UiManage:
def __init__(self, gm):
self.gm = gm
self.mode = None
self.is_victory = None
self.time_cha = 0
self.start_time = 0
self.current_background_music = None
# 创建游戏开始前精灵
self.start_image = pygame.image.load("img/游戏开始画面.png")
self.begin_group = pygame.sprite.Group()
self.sprite1 = UiSprite("img/简单模式.png", (700, 450))
self.sprite1.add(self.begin_group)
self.sprite2 = UiSprite("img/困难模式.png", (700, 550))
self.sprite2.add(self.begin_group)
self.sprite3 = UiSprite("img/Boss模式.png", (700, 650))
self.sprite3.add(self.begin_group)
self.sprite4 = UiSprite("img/返回菜单.png", (75, 30))
self.sprite4.add(self.begin_group)
# 创建游戏结束精灵
self.end_image = pygame.image.load("img/游戏结束画面.png")
self.end_group = pygame.sprite.Group()
self.end_sprit1 = UiSprite("img/重来一次.png", (800, 550))
self.end_sprit1.add(self.end_group)
self.end_sprit2 = UiSprite("img/返回菜单.png", (600, 550))
self.end_sprit2.add(self.end_group)
# 暂停后继续游戏以及返回菜单
self.continue_sprit_group = pygame.sprite.Group()
self.continue_sprit1 = UiSprite("img/继续游戏.png", (800, 350))
self.continue_sprit1.add(self.continue_sprit_group)
self.continue_sprit2 = UiSprite("img/返回菜单.png", (600, 350))
self.continue_sprit2.add(self.continue_sprit_group)
# 绘制分数
self.font = pygame.font.Font("font/font.ttf", 80)
# 失败精灵
self.lose_group = pygame.sprite.Group()
self.lose_sprite = UiSprite("img/失败.png", (700, 250))
self.lose_sprite.add(self.lose_group)
# 胜利精灵
self.victory_group = pygame.sprite.Group()
self.victory_sprite = UiSprite("img/胜利.png", (700, 250))
self.victory_sprite.add(self.victory_group)
# 退出游戏与选择模式
self.choice_image = pygame.image.load("img/选择页面.png")
self.choice_group = pygame.sprite.Group()
self.choice_sprite1 = UiSprite("img/退出游戏.png", (900, 450))
self.choice_sprite1.add(self.choice_group)
self.choice_sprite2 = UiSprite("img/开始游戏.png", (500, 450))
self.choice_sprite2.add(self.choice_group)
def update(self):
if self.gm.state == "ready":
self.mode = None
self.is_victory = None
self.gm.screen.blit(self.choice_image, (0, 0))
self.choice_group.draw(self.gm.screen)
if Util.check(self.choice_sprite2):
self.gm.state = "choose"
elif Util.check(self.choice_sprite1):
pygame.quit()
sys.exit()
elif self.gm.state == "choose":
self.gm.screen.blit(self.start_image, (0, 0))
self.begin_group.draw(self.gm.screen)
if Util.check(self.sprite1):
self.gm.state = "gaming"
pygame.mixer.music.load("sound/背景音乐.mp3")
pygame.mixer.music.play(-1)
self.mode = 1
self.gm.bg_manage.born()
self.gm.player_manage.born()
elif Util.check(self.sprite2):
self.gm.state = "gaming"
self.start_time = time.time()
pygame.mixer.music.load("sound/背景音乐.mp3")
pygame.mixer.music.play(-1)
self.mode = 2
self.gm.bg_manage.born()
self.gm.player_manage.born()
elif Util.check(self.sprite3):
self.gm.state = "gaming"
pygame.mixer.music.load("sound/雷霆战机背景音乐.wav")
pygame.mixer.music.play(-1)
self.mode = 3
self.gm.bg_manage.born()
self.gm.player_manage.born()
self.gm.boss_manage.born()
elif Util.check(self.sprite4):
self.gm.state = "ready"
elif self.gm.state == "gaming":
self.gm.draw_update()
elif self.gm.state == "stop":
self.continue_sprit_group.draw(self.gm.screen)
if Util.check(self.continue_sprit1):
self.time_cha = time.time() - self.gm.start_time1
self.gm.state = "gaming"
if Util.check(self.continue_sprit2):
self.time_cha = 0
self.gm.player_manage.die()
self.gm.state = "ready"
AudioSprite.play_bgm_music()
elif self.gm.state == "end":
self.gm.screen.blit(self.end_image, (0, 0))
self.end_group.draw(self.gm.screen)
if self.is_victory:
# 胜利的声音
if self.mode == 3:
self.victory_group.draw(self.gm.screen)
else:
self.score_surface = self.font.render(f"current score:{self.gm.bg_manage.score}", True, "red")
self.gm.screen.blit(self.score_surface, (460, 350))
self.victory_group.draw(self.gm.screen)
else:
# 失败的声音
if self.mode == 3:
self.lose_group.draw(self.gm.screen)
else:
self.score_surface = self.font.render(f"current score:{self.gm.bg_manage.score}", True,
"red")
self.gm.screen.blit(self.score_surface, (460, 350))
self.lose_group.draw(self.gm.screen)
if Util.check(self.end_sprit1):
self.gm.state = "gaming"
if self.mode == 2:
self.start_time = time.time()
self.gm.bg_manage.born()
self.gm.player_manage.born()
if self.mode == 1:
self.gm.bg_manage.born()
self.gm.player_manage.born()
if self.mode == 3:
self.gm.bg_manage.born()
self.gm.player_manage.born()
self.gm.boss_manage.born()
elif Util.check(self.end_sprit2):
self.gm.state = "ready"
AudioSprite.play_bgm_music()
class BgSprite(BaseSprite):
def __init__(self, name, topleft):
super().__init__(name)
self.rect.topleft = topleft
def update(self):
self.rect.top += 1
if self.rect.top >= 700:
self.rect.top = -700
class BgManage:
def __init__(self, gm):
self.gm = gm
self.bg_group = pygame.sprite.Group()
self.score = 0
self.font = pygame.font.Font("font/font.ttf", 50)
def born(self):
self.score = 0
BgSprite("img/游戏背景.png", (0, 0)).add(self.bg_group)
BgSprite("img/游戏背景.png", (0, -700)).add(self.bg_group)
def clear(self):
self.bg_group.empty()
def update(self):
self.bg_group.update()
self.bg_group.draw(self.gm.screen)
if self.gm.ui_manage.mode == 1:
self.score_surface = self.font.render(f"score:{self.score}", True, "red")
self.gm.screen.blit(self.score_surface, (1200, 30))
if self.gm.ui_manage.mode == 2:
self.time_surface = self.font.render(
f"time:{round(time.time() - self.gm.ui_manage.start_time - self.gm.ui_manage.time_cha, 2)}",
True, "red")
self.gm.screen.blit(self.time_surface, (1150, 80))
self.score_surface = self.font.render(f"score:{self.score}", True, "red")
self.gm.screen.blit(self.score_surface, (1150, 30))
class PlayerSprite(BaseSprite):
def __init__(self, name, center, speed, hp, gm):
super().__init__(name)
self.gm = gm
self.hp = hp
self.max_hp = hp
self.rect.center = center
self.speed = speed
self.bullet_group = pygame.sprite.Group()
self.time = 2
self.super_time = 0
self.mode = None
def shoot1(self):
self.bullet = BulletSprite("img/子弹.png", (self.rect.centerx, self.rect.top - 10), -10)
self.bullet.add(self.bullet_group)
def shoot2(self):
for i in range(5):
BulletSprite("img/子弹.png", (self.rect.centerx - 10 + 10 * i, self.rect.top - 10),
-12 if self.gm.ui_manage.mode == 3 else -10).add(
self.bullet_group)
def draw_blood(self):
pygame.draw.rect(self.gm.screen, (127, 127, 127),
(self.rect.left + self.rect.width / 2 - 50, self.rect.bottom, 100, 10))
pygame.draw.rect(self.gm.screen, (0, 255, 0), (
self.rect.left + self.rect.width / 2 - 50, self.rect.bottom, self.hp / self.max_hp * 100, 10))
def update(self):
self.draw_blood()
self.time -= 0.25 if self.gm.ui_manage.mode == 3 else 0.1
if self.time <= 0:
self.time = 2
if self.super_time > 0:
self.shoot2()
# 子弹发射的声音
self.mode = 2
self.super_time -= 1
else:
self.shoot1()
# 子弹发射的声音
self.mode = 1
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 < 1400:
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.bullet_group.update()
self.bullet_group.draw(self.gm.screen)
class PlayerManage:
def __init__(self, gm):
self.gm = gm
self.plane_group = pygame.sprite.Group()
# AudioSprite.play_bgm_music()
def born(self):
self.my_plane = PlayerSprite("img/玩家战机.png", (700, 620), 5, 10, self.gm)
self.my_plane.add(self.plane_group)
def die(self):
self.gm.bg_manage.clear()
self.plane_group.empty()
self.my_plane.bullet_group.empty()
for enemy in self.gm.enemy_manage.enemy_group.sprites():
enemy.kill()
for bullet in enemy.enemy_bullet_group.sprites():
bullet.kill()
self.gm.prop_manage.clear()
if self.gm.ui_manage.mode == 3:
for enemy in self.gm.boss_manage.boss_group.sprites():
enemy.kill()
for bullet in enemy.boss_bullet_group.sprites():
bullet.kill()
def update(self):
self.plane_group.update()
self.plane_group.draw(self.gm.screen)
class BulletSprite(BaseSprite):
def __init__(self, name, center, speed):
super().__init__(name)
self.rect.center = center
self.speed = speed
def update(self):
self.rect.centery += self.speed
if self.rect.centery >= 700:
self.kill()
class EnemySprite(BaseSprite):
def __init__(self, name, speed, hp, type, gm):
super().__init__(name)
self.gm = gm
self.rect.left = random.randrange(30, 1300, 100)
self.rect.bottom = 0
self.time1 = 2
self.time2 = 2
self.speed = speed
self.enemy_bullet_group = pygame.sprite.Group()
self.hp = hp
self.max_hp = hp
self.move_dir = "left"
self.type = type
def generate_bullet(self):
self.bullet = BulletSprite("img/敌人子弹.png", (self.rect.centerx, self.rect.bottom + 10), 5)
self.bullet.add(self.enemy_bullet_group)
def draw_blood(self):
pygame.draw.rect(self.gm.screen, (127, 127, 127),
(self.rect.left, self.rect.top, self.rect.width, 10))
pygame.draw.rect(self.gm.screen, (0, 255, 0), (
self.rect.left, self.rect.top, self.hp / self.max_hp * self.rect.width, 10))
def clear(self):
self.enemy_bullet_group.empty()
def update(self):
self.draw_blood()
self.time1 -= 1
if self.time1 <= 0:
self.time1 = 2
self.rect.centery += self.speed
self.time2 -= 0.03
if self.time2 <= 0:
self.time2 = 2
self.generate_bullet()
self.enemy_bullet_group.update()
self.enemy_bullet_group.draw(self.gm.screen)
class EnemyManage:
def __init__(self, gm):
self.gm = gm
self.enemy_group = pygame.sprite.Group()
self.time = 2
def generate_enemy1(self):
self.enemy = EnemySprite("img/敌方战机1.png", 5, 1, 1, self.gm)
self.enemy.add(self.enemy_group)
def generate_enemy2(self):
if random.random() > 0.4:
self.enemy = EnemySprite("img/敌方战机1.png", 5, 1, 1, self.gm)
self.enemy.add(self.enemy_group)
elif random.random() > 0.1:
self.enemy = EnemySprite("img/敌方战机2.png", 3, 3, 2, self.gm)
self.enemy.add(self.enemy_group)
else:
self.enemy = EnemySprite("img/Boss.png", 1, 5, 3, self.gm)
self.enemy.add(self.enemy_group)
def clear(self):
self.enemy_group.empty()
def update(self):
self.time -= 0.05
if self.time <= 0:
self.time = 2
if self.gm.ui_manage.mode == 1:
self.generate_enemy1()
elif self.gm.ui_manage.mode == 2:
self.generate_enemy2()
self.enemy_group.update()
self.enemy_group.draw(self.gm.screen)
class BossSprite(EnemySprite):
def __init__(self, name, speed, hp, type, gm, center):
super().__init__(name, speed, hp, type, gm)
# BulletSprite().__init__(self, center, speed)
self.rect.center = center
self.boss_bullet_group = pygame.sprite.Group()
self.move_dir = "left"
self.time = 2
def generate_bullet(self):
name = "img/炮弹.png" if random.random() > 0.5 else "img/炮弹2.png"
center = (self.rect.centerx, self.rect.centery + 20)
self.boss_bullet = BulletSprite(name, center, 3)
self.boss_bullet.add(self.boss_bullet_group)
def draw_blood(self):
pygame.draw.rect(self.gm.screen, (127, 127, 127),
(self.rect.left, self.rect.top, self.rect.width, 10))
pygame.draw.rect(self.gm.screen, (255, 0, 0), (
self.rect.left, self.rect.top, self.hp / self.max_hp * self.rect.width, 10))
def update(self):
self.draw_blood()
if self.rect.centery < 96:
self.rect.centery += self.speed * 2
else:
if self.move_dir == "left":
self.rect.centerx -= self.speed * 2
if self.rect.centerx <= 140:
self.move_dir = "right"
elif self.move_dir == "right":
self.rect.centerx += self.speed * 2
if self.rect.centerx >= 1240:
self.move_dir = "left"
self.time -= 0.05
if self.time <= 0:
self.time = 2
self.generate_bullet()
self.boss_bullet_group.update()
self.boss_bullet_group.draw(self.gm.screen)
class BossManage:
def __init__(self, gm):
self.gm = gm
self.boss_group = pygame.sprite.Group()
def born(self):
self.boss1 = BossSprite("img/Boss1.png", 1, 1000, 5, self.gm, (140, -96))
self.boss1.add(self.boss_group)
self.boss2 = BossSprite("img/Boss2.png", 1, 1000, 5, self.gm, (1260, -96))
self.boss2.add(self.boss_group)
def clear(self):
self.boss_group.empty()
def update(self):
self.boss_group.update()
self.boss_group.draw(self.gm.screen)
class PropSprite(BaseSprite):
def __init__(self, name, speed, type, gm):
super().__init__(name)
self.gm = gm
self.rect.left = random.randrange(0, 1340, 100)
self.rect.bottom = 0
self.speed = speed
self.time = 2
self.type = type
def update(self):
self.time -= 1
if self.time <= 0:
self.time = 2
self.rect.centery += self.speed
if self.rect.centery >= 700:
self.kill()
class PropManage:
def __init__(self, gm):
self.gm = gm
self.prop_group = pygame.sprite.Group()
self.time = 2
def generate(self):
if random.random() > 0.8:
PropSprite("img/改变攻击方式.png", 5, 1, self.gm).add(self.prop_group)
elif random.random() > 0.6:
PropSprite("img/清屏.png", 5, 2, self.gm).add(self.prop_group)
else:
PropSprite("img/加血.png", 5, 3, self.gm).add(self.prop_group)
def clear(self):
self.prop_group.empty()
def update(self):
self.time -= 1
if self.time <= 0:
self.time = 2
if len(self.prop_group.sprites()) < 1:
self.generate()
self.prop_group.update()
self.prop_group.draw(self.gm.screen)
class AudioSprite:
@staticmethod
def play_bgm_music():
pygame.mixer.music.load("sound/主菜单背景音乐.wav")
pygame.mixer.music.play(-1)
@staticmethod
def play_bgm_music2():
pygame.mixer.music.load("sound/背景音乐.mp3")
pygame.mixer.music.play(-1)
@staticmethod
def play_bgm_music3():
pygame.mixer.music.load("sound/雷霆战机背景音乐.wav")
pygame.mixer.music.play(-1)
@staticmethod
def play_sound(name):
sound = pygame.mixer.Sound(name)
sound.play()
class GameManage:
def __init__(self, name):
pygame.init()
self.state = "ready"
self.clock = pygame.time.Clock()
self.screen = pygame.display.set_mode((1400, 700))
pygame.display.set_caption(name)
self.icon_surface = pygame.image.load("img/小图标.png")
pygame.display.set_icon(self.icon_surface)
self.bg_manage = BgManage(self)
self.player_manage = PlayerManage(self)
self.enemy_manage = EnemyManage(self)
self.prop_manage = PropManage(self)
self.ui_manage = UiManage(self)
self.boss_manage = BossManage(self)
self.start_time1 = 0
self.start_time = 0
self.event_key = None
AudioSprite.play_bgm_music()
def check_event(self):
self.clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if self.state == "gaming" and event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
self.state = "stop"
self.start_time1 = time.time()
key_pressed = pygame.key.get_pressed()
if key_pressed[pygame.K_q]:
self.player_manage.my_plane.shoot2()
def check_is_victory(self):
if self.state == "gaming":
if self.ui_manage.mode == 1:
if self.player_manage.my_plane.hp > 0 and self.bg_manage.score >= 50:
self.player_manage.die()
self.state = "end"
self.ui_manage.is_victory = True
elif self.player_manage.my_plane.hp == 0:
self.player_manage.die()
self.state = "end"
self.ui_manage.is_victory = False
elif self.ui_manage.mode == 2:
if self.player_manage.my_plane.hp > 0 and self.bg_manage.score >= 50:
self.player_manage.die()
if time.time() - self.ui_manage.start_time <= 20:
self.ui_manage.is_victory = True
else:
self.ui_manage.is_victory = False
self.state = "end"
elif self.player_manage.my_plane.hp == 0 or (
time.time() - self.ui_manage.start_time >= 20 and self.bg_manage.score < 50):
self.player_manage.die()
self.state = "end"
self.ui_manage.is_victory = False
elif self.ui_manage.mode == 3:
if self.player_manage.my_plane.hp > 0 and len(self.boss_manage.boss_group.sprites()) == 0:
self.player_manage.die()
if len(self.boss_manage.boss_group.sprites()) == 0:
self.ui_manage.is_victory = True
else:
self.ui_manage.is_victory = False
self.state = "end"
elif self.player_manage.my_plane.hp == 0:
self.player_manage.die()
self.state = "end"
self.ui_manage.is_victory = False
def check_collide(self):
self.check_is_victory()
if self.state == "gaming":
player_prop = pygame.sprite.groupcollide(self.player_manage.plane_group, self.prop_manage.prop_group,
False, True)
for props in player_prop.values():
for prop in props:
if prop.type == 1:
self.player_manage.my_plane.super_time = 30 if self.ui_manage.mode == 3 else 10
if prop.type == 2:
if self.ui_manage.mode == 3:
for boss in self.boss_manage.boss_group.sprites():
boss.hp -= 50
if boss.hp <= 0:
boss.kill()
else:
for enemy in self.enemy_manage.enemy_group.sprites():
self.bg_manage.score += enemy.type
enemy.kill()
if prop.type == 3:
self.player_manage.my_plane.hp += 1
if self.player_manage.my_plane.hp > self.player_manage.my_plane.max_hp:
self.player_manage.my_plane.hp = self.player_manage.my_plane.max_hp
my_bullet_enemy = pygame.sprite.groupcollide(self.player_manage.my_plane.bullet_group,
self.enemy_manage.enemy_group, True, False)
if my_bullet_enemy:
for enemys in my_bullet_enemy.values():
for enemy in enemys:
enemy.hp -= 1
if enemy.hp <= 0:
enemy.kill()
self.bg_manage.score += enemy.type
for enemy in self.enemy_manage.enemy_group.sprites():
my_plane_enemy_bullet = pygame.sprite.groupcollide(self.player_manage.plane_group,
enemy.enemy_bullet_group, False, True)
if my_plane_enemy_bullet:
self.player_manage.my_plane.hp -= 1
for boss in self.boss_manage.boss_group.sprites():
if pygame.sprite.groupcollide(self.player_manage.my_plane.bullet_group,
boss.boss_bullet_group, True, True):
pass
bullet_boss = pygame.sprite.groupcollide(self.player_manage.my_plane.bullet_group,
self.boss_manage.boss_group, True, False)
for enemys in bullet_boss.values():
for enemy in enemys:
enemy.hp -= 1
if enemy.hp <= 0:
enemy.kill()
for boss in self.boss_manage.boss_group.sprites():
my_plane_enemy_bullet = pygame.sprite.groupcollide(self.player_manage.plane_group,
boss.boss_bullet_group, False, True)
if my_plane_enemy_bullet:
self.player_manage.my_plane.hp -= 1
def draw_update(self):
if self.state == "gaming":
self.bg_manage.update()
self.enemy_manage.update()
self.player_manage.update()
self.prop_manage.update()
if self.ui_manage.mode == 3:
self.boss_manage.update()
def run(self):
while True:
self.check_event()
# self.draw_update()
self.check_collide()
self.ui_manage.update()
pygame.display.flip()
gm = GameManage("雷霆战机")
gm.run()