目录
3)设置游戏的开始 游戏中 游戏后 的各种的背景 按键(实现前面所说的按键点击检测)
敌人精灵中要有自己的属性 敌人子弹 敌人的移动(与玩家一样)
最后希望我的讲解可以给你带来理解,希望我的源码可以给你的游戏增添色彩~~~游戏内容没有那么完整,还需您多多指点!!!!
1 了解游戏的元素
首先我们要知道飞机大战中的元素都有什么
飞机即玩家 | player |
敌人 | enemy |
子弹(玩家子弹)(敌人子弹) | bullet |
道具 | prop |
boss | boss |
每一个元素都对应这每一个精灵组 每一个精灵组也要有自己的对应的管理类(一般情况)
接下来用一个图给大家展示一下之间的关系:
关系管理图
最开始的是游戏管理 游戏管理管理着背景管理 玩家管理 还有 敌人管理 子弹管理 道具管理等等 游戏管理是最大的管理类 管理着各种的类 背景管理中有背景精灵组 管理着背景精灵 背景精灵中有初始化方法__init__ 更新BGSprite的基本属性 位置 图片 的update() 其他都是类似的 这里就介绍以下BGSprite 。
要记得需要什么元素 一般很大情况下都要有他自己的精灵类 精灵管理组。
2 规划进行游戏设计
1) 我们要创建一个不会关闭的窗口
代码实现:
class GameManage:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((1500, 900))
self.rect = self.screen.get_rect()
pygame.display.set_caption("飞机")
def run(self):
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.flip()
gm = GameManage()
gm.run()
2) 加载一下循环背景
代码实现:
class BaseSprite(pygame.sprite.Sprite):
def __init__(self, name):
super().__init__()
self.image = pygame.image.load(name)
self.rect = self.image.get_rect()
class BGSprite(BaseSprite):
def __init__(self, name, topleft):
super().__init__(name)
self.rect.topleft = topleft
def update(self):
self.rect.top += 2
if self.rect.top >= 900:
self.rect.top = -900
class BGManage:
def __init__(self, gm):
self.gm = gm
self.bg_group = pygame.sprite.Group()
BGSprite("img/gaming_bg.jpg", (0, 0)).add(self.bg_group)
BGSprite("img/gaming_bg.jpg", (0, -900)).add(self.bg_group)
def update(self):
self.bg_group.update()
self.bg_group.draw(self.gm.screen)
在写BGSprite时要提前写个BaseSprite精灵类用于被继承 其中BaseSprite继承了我们的pygame.sprite.Sprite 继承可以调用父类的方法 在子类中不用再声明 减少代码 增加了我们的功能
(这里面的代码前面已经讲过,这边就不深入讲解)
3)设置游戏的开始 游戏中 游戏后 的各种的背景 按键(实现前面所说的按键点击检测)
游戏的开始 游戏中 游戏后的背景 按键 都属于UI管理的,因此我们会创建一个继承BaseSprite的UISprite精灵 还有一个用于管理UISprite精灵的管理类UIManage,具体的功能也要根据自己的需求去实现。
参考代码:
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.is_victory = None
self.font = pygame.font.Font("font/font.ttf", 32)
self.font1 = pygame.font.Font("font/font.ttf", 128)
# 游戏开始前的UI
self.ready_group = pygame.sprite.Group()
self.ready_btn1 = UISprite("img/bg.jpg", (750, 450))
self.ready_btn2 = UISprite("img/begin_gaming.png", (750, 450))
self.ready_over_image = UISprite("img/end.png", (750, 600))
self.ready_btn1.add(self.ready_group)
self.ready_btn2.add(self.ready_group)
self.ready_over_image.add(self.ready_group)
# 游戏中的UI
# self.gaming_group = pygame.sprite.Group()
# self.gaming_score = self.font.render(f"Score:{self.gm.player_manage.score}", True, "#FF4500")
# 游戏后的UI
self.end_group = pygame.sprite.Group()
self.end_bg_image = UISprite("img/bg.jpg", (750, 450))
self.end_fail_image = UISprite("img/fail.png", (750, 150))
self.end_btn = UISprite("img/rebegin.png", (750, 450))
self.end_end_image = UISprite("img/end.png", (750, 600))
self.end_victory_image = UISprite("img/victory.png", (750, 150))
self.end_bg_image.add(self.end_group)
self.end_btn.add(self.end_group)
self.end_end_image.add(self.end_group)
self.fail_group = pygame.sprite.Group()
self.end_fail_image.add(self.fail_group)
self.victory_group = pygame.sprite.Group()
self.end_victory_image.add(self.victory_group)
# 游戏暂停的UI
self.paused_group = pygame.sprite.Group()
self.paused_image = UISprite("img/continue.png", (750, 450))
self.paused_image.add(self.paused_group)
def update(self):
# 游戏前
if self.gm.state == "ready":
self.ready_group.draw(self.gm.screen)
if Util.click_check(self.ready_btn1):
AudioMusic.button_music("music/button.mp3")
self.gm.state = "gaming"
self.gm.boss_manage.born()
self.gm.player_manage.born()
if Util.click_check(self.ready_over_image):
AudioMusic.button_music("music/button.mp3")
pygame.quit()
sys.exit()
# AudioMusic.begin_music("music/begin_music.mp3")
elif self.gm.state == "gaming":
self.score_surface = self.font.render(f"Score:{self.gm.player_manage.score}", True, "#FF4500")
self.gm.draw_update()
self.gm.screen.blit(self.score_surface, (1350, 50))
elif self.gm.state == "end":
self.end_group.draw(self.gm.screen)
self.end_score_surface = self.font1.render(f"Score:{self.gm.player_manage.score}", True, "#7CFC00")
self.gm.screen.blit(self.end_score_surface, (550, 200))
if self.is_victory == False:
self.fail_group.draw(self.gm.screen)
elif self.is_victory == True:
self.victory_group.draw(self.gm.screen)
if Util.click_check(self.end_btn):
AudioMusic.button_music("music/button.mp3")
self.gm.die()
self.gm.state = "gaming"
self.gm.boss_manage.born()
self.gm.player_manage.born()
if Util.click_check(self.end_end_image):
AudioMusic.button_music("music/button.mp3")
pygame.quit()
sys.exit()
elif self.gm.state == "paused":
self.paused_group.draw(self.gm.screen)
if Util.click_check(self.paused_image):
AudioMusic.button_music("music/button.mp3")
self.gm.state = "gaming"
我这边是根据自己的功能去实现的。具体如下:
开始前
游戏中
游戏暂停(通过空格实现)
游戏结束失败的画面
游戏结束胜利的画面
上面的开始游戏 继续游戏 结束游戏 start over 都是用鼠标左键点击实现的,要用到
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
每当点击的时候调用Util的click_check函数就可以了
4)在游戏中添加玩家(此时的玩家应该会移动)
玩家精灵类 玩家管理类
代码实现:
class PlayerSprite(BaseSprite):
def __init__(self, name, center, speed, gm):
super().__init__(name)
self.gm = gm
self.rect.center = center
self.speed = speed
self.max_hp = 10
self.hp = 10
self.shoot_time = 2
self.bullet_group = pygame.sprite.Group()
self.super_bullet_num1 = 0
self.super_bullet_num2 = 0
def shoot(self):
BulletSprite("img/bullet.png", self.rect.centerx, self.rect.top - 50, -20).add(self.bullet_group)
def shoot1(self):
for i in range(5):
BulletSprite("img/bullet.png", self.rect.centerx - 20 + 10 * i, self.rect.top - 50, -20).add(
self.bullet_group)
def shoot2(self):
BulletSprite("img/bullet.png", self.rect.centerx, self.rect.top - 50, -20).add(self.bullet_group)
BulletSprite("img/bullet.png", self.rect.centerx - 75, self.rect.top - 50, -20).add(self.bullet_group)
BulletSprite("img/bullet.png", self.rect.centerx + 75, self.rect.top - 50, -20).add(self.bullet_group)
def shoot3(self):
for i in range(7):
BulletSprite("img/bullet.png", self.rect.centerx - 30 + 10 * i, self.rect.top - 50, -20).add(
self.bullet_group)
def draw_hp(self):
pygame.draw.rect(self.image, (127, 127, 127), (self.rect.width / 2 - 75, self.rect.height - 10, 150, 10))
pygame.draw.rect(self.image, (0, 255, 0),
(self.rect.width / 2 - 75, self.rect.height - 10, self.hp / self.max_hp * 150, 10))
def update(self):
self.draw_hp()
self.shoot_time -= 0.8
if self.shoot_time <= 0:
self.shoot_time = 2
value = random.random()
if value > 0.5:
if self.super_bullet_num1 > 0:
self.shoot1()
self.super_bullet_num1 -= 1
else:
self.shoot()
else:
if self.super_bullet_num2 > 0:
self.shoot2()
self.super_bullet_num2 -= 1
else:
self.shoot()
key_presses = pygame.key.get_pressed()
if key_presses[pygame.K_a] and self.rect.left > 0:
self.rect.left -= self.speed
if key_presses[pygame.K_d] and self.rect.right < 1500:
self.rect.right += self.speed
if key_presses[pygame.K_w] and self.rect.top > 0:
self.rect.top -= self.speed
if key_presses[pygame.K_s] and self.rect.bottom < 900:
self.rect.bottom += self.speed
self.bullet_group.update()
self.bullet_group.draw(self.gm.screen)
class PlayerManage:
def __init__(self, gm):
self.gm = gm
self.score = None
self.player_group = pygame.sprite.Group()
self.player = PlayerSprite("img/player1.png", (750, 825), 20, self.gm)
AudioMusic.play_bg_music()
def born(self):
self.player = PlayerSprite("img/player1.png", (750, 825), 20, self.gm)
self.player.hp = 10
self.score = 0
self.player.add(self.player_group)
def update(self):
self.player_group.update()
self.player_group.draw(self.gm.screen)
玩家的属性 移动 子弹 都要写入玩家精灵类的update中 我这里面有四种不同的射击方式分别对应着不同的道具
玩家的操作 创建玩家精灵组 玩家出生 更新玩家精灵组都要写入玩家管理类的update中
5) 在游戏添加敌人(敌人也要会移动)
敌人精灵 敌人管理类
代码实现:
class EnemySprite(BaseSprite):
def __init__(self, name, centerx, y, speed, hp, gm):
super().__init__(name)
self.rect.centerx = centerx
self.rect.top = y
self.speed = speed
self.hp = hp
self.max_hp = hp
self.bullet_group = pygame.sprite.Group()
self.time_count2 = 2
self.time_move = 2
self.gm = gm
def shoot(self):
value = random.random()
if value > 0.7:
BulletSprite("img/enemybullet.png", self.rect.centerx - 20, self.rect.top + self.rect.height + 30, 10).add(
self.bullet_group)
else:
BulletSprite("img/enemybullet.png", self.rect.centerx - 20, self.rect.top + self.rect.height + 30, 10).add(
self.bullet_group)
def draw_hp(self):
pygame.draw.rect(self.image, (127, 127, 127), (self.rect.width / 2 - 40, self.rect.height - 78, 70, 15))
pygame.draw.rect(self.image, (0, 255, 0),
(self.rect.width / 2 - 40, self.rect.height - 78, self.hp / self.max_hp * 70, 15))
def update(self):
self.time_count2 -= 0.1
if self.time_count2 <= 0:
self.time_count2 = 2
self.shoot()
self.time_move -= 0.5
if self.time_move <= 0:
self.time_move = 2
value = random.random()
if value > 0.5:
self.rect.top += self.speed * 2
self.rect.centerx += self.speed
else:
self.rect.top += self.speed * 2
self.rect.centerx -= self.speed * 2
if self.rect.y > 900 or self.rect.right > 1500 or self.rect.left < 0:
self.kill()
self.draw_hp()
self.bullet_group.update()
self.bullet_group.draw(self.gm.screen)
class EnemyManage:
def __init__(self, gm):
self.gm = gm
self.enemy_group = pygame.sprite.Group()
self.time_count1 = 5
def generate(self):
value = random.random()
# if value > 0.9:
# EnemySprite("img/enemy3.png", random.randrange(25, 1500, 25), 0, 4, 8, self.gm).add(self.enemy_group)
if value > 0.5:
EnemySprite("img/enemy1.png", random.randrange(50, 1450, 25), 0, 6, 8, self.gm).add(self.enemy_group)
# if value > 0.3:
# EnemySprite("img/enemy4.png", random.randrange(25, 1500, 25), 0, 8, 4, self.gm).add(self.enemy_group)
if value > 0:
EnemySprite("img/enemy.png", random.randrange(50, 1450, 25), 0, 8, 6, self.gm).add(self.enemy_group)
def update(self):
self.time_count1 -= 0.2
if self.time_count1 <= 0:
self.time_count1 = 5
self.generate()
self.enemy_group.update()
self.enemy_group.draw(self.gm.screen)
敌人精灵中要有自己的属性 敌人子弹 敌人的移动(与玩家一样)
敌人管理类中有敌人的精灵组 敌人的出生条件 在哪出生 出生什么敌人 都是我们要考虑的问题
最后将敌人放进敌人精灵组 之后绘制在窗口中显示出来
6)在游戏中添加boss(boss出现的条件自己设定就行)
boss精灵 boss管理类
代码实现:
class BossSprite(BaseSprite):
def __init__(self, name, center, hp, gm):
super().__init__(name)
self.rect.center = center
self.boss_speed = 5
self.hp = hp
self.max_hp = hp
self.bullet_group = pygame.sprite.Group()
self.gm = gm
self.time_count5 = 2
def shoot(self):
BulletSprite("img/boss_bullet.png", self.rect.centerx, self.rect.centery, 10).add(
self.bullet_group)
def draw_hp(self):
pygame.draw.rect(self.image, (127, 127, 127), (self.rect.width / 2 - 200, self.rect.height - 310, 400, 20))
pygame.draw.rect(self.image, (0, 255, 0),
(self.rect.width / 2 - 200, self.rect.height - 310, self.hp / self.max_hp * 400, 20))
def update(self):
self.rect.centerx -= self.boss_speed
if self.rect.centerx > 1300 or self.rect.centerx < 200:
self.boss_speed *= -1
self.time_count5 -= 0.2
if self.time_count5 <= 0:
self.time_count5 = 2
self.shoot()
self.draw_hp()
self.bullet_group.update()
self.bullet_group.draw(self.gm.screen)
class BossManage:
def __init__(self, gm):
self.gm = gm
self.boss_group = pygame.sprite.Group()
self.boss = BossSprite("img/boss.png", (random.randrange(200, 1300, 50), 200), 400, self.gm)
def born(self):
self.boss.hp = 400
def update(self):
if self.gm.player_manage.score >= 50:
self.boss.add(self.boss_group)
self.boss_group.update()
self.boss_group.draw(self.gm.screen)
boss和敌人的思路一样 但是boss需要条件才可以出生 敌人是游戏开始的时候就出生 这一点注意以下就可以了
7)在游戏中添加道具
道具精灵 道具管理类
代码实现:
class PropSprite(BaseSprite):
def __init__(self, name, centerx, y, speed, type):
super().__init__(name)
self.rect.centerx = centerx
self.rect.top = y
self.speed = speed
self.time_count3 = 2
self.type = type
def update(self):
self.time_count3 -= 2
if self.time_count3 <= 0:
self.time_count3 = 2
self.rect.top += self.speed
if self.rect.y > 900:
self.kill()
class PropManage:
def __init__(self, gm):
self.gm = gm
self.prop_group = pygame.sprite.Group()
self.time_count4 = 6
def generate(self):
value = random.random()
if value > 0.9:
PropSprite("img/daojubaozha.png", random.randrange(50, 1450, 25), 0, 8, 1).add(self.prop_group)
elif value > 0.5:
PropSprite("img/jiaxie.png", random.randrange(75, 1450, 25), 0, 8, 2).add(self.prop_group)
else:
PropSprite("img/player1(1).png", random.randrange(50, 1450, 25), 0, 8, 3).add(self.prop_group)
def update(self):
self.time_count4 -= 0.2
if self.time_count4 <= 0:
self.time_count4 = 6
self.generate()
self.prop_group.update()
self.prop_group.draw(self.gm.screen)
道具和敌人思路也是一样的 不一样的是道具不会发生子弹
注意:道具的类型 后面的碰撞需要找到碰撞的是哪个道具 不同的道具实现不同的功能
8)在游戏中添加子弹(子弹包括玩家的 敌人的 boss的)
需要声明的是子弹是敌人 玩家 boss 都拥有的 所以没有具体的管理类 当想要使用子弹时候直接调用子弹精灵类实现 子弹管理类没有自己成一个类 而是在要使用子弹的精灵的精灵类里面方便每一个精灵对子弹进行管理。
class BulletSprite(BaseSprite):
def __init__(self, name, centerx, y, speed):
super().__init__(name)
self.rect.centerx = centerx
self.rect.top = y
self.speed = speed
self.time_count = 2
def update(self):
self.time_count -= 2
if self.time_count <= 0:
self.time_count = 2
self.rect.top += self.speed
if self.rect.top > 900 or self.rect.bottom < 0:
self.kill()
子弹每当出了窗口的范围我们要做到及时销毁 从而减轻我们精灵组的压力 敌人也是这样的
9) 给每个敌人 玩家 boss 加上血条
你会看到敌人 玩家 boss的管理类中都有一个draw_hp方法 这个就是血条 血条的方法就是绘制矩形 然后在矩形上面绘制不同于第一个颜色的矩形 从而达到血条 具体实现请看代码 也可根据自己的想法实现 代码仅供参考
10)实现游戏中的各种碰撞 (根据自己想要的去实现)
实现碰撞:实质上就是精灵组与精灵组进行碰撞 我们要用到groupcollider方法。
代码实现(根据我的功能实现的):
def check_collider(self):
# 玩家与道具
player_prop_collider = pygame.sprite.groupcollide(self.player_manage.player_group, self.prop_manage.prop_group,
False, True)
if player_prop_collider:
for props in player_prop_collider.values():
for prop in props:
if prop.type == 1:
self.enemy_manage.enemy_group.empty()
if prop.type == 2:
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
if prop.type == 3:
value = random.random()
if value > 0.5:
self.player_manage.player.super_bullet_num1 = 20
else:
self.player_manage.player.super_bullet_num2 = 20
# 玩家子弹与敌人
player_bullet_enemy_collider = pygame.sprite.groupcollide(self.player_manage.player.bullet_group,
self.enemy_manage.enemy_group, True, False)
if player_bullet_enemy_collider:
for enemys in player_bullet_enemy_collider.values():
for enemy in enemys:
enemy.hp -= 2
if enemy.hp <= 0:
self.player_manage.score += 1
enemy.kill()
# 玩家子弹与boss
player_bullet_boss_collider = pygame.sprite.groupcollide(self.player_manage.player.bullet_group,
self.boss_manage.boss_group, True, False)
if player_bullet_boss_collider:
self.boss_manage.boss.hp -= 2
if self.boss_manage.boss.hp <= 0:
self.die()
self.ui_manage.is_victory = True
self.state = "end"
# 玩家与敌人子弹
for enemy in self.enemy_manage.enemy_group.sprites():
player_enemy_bullet_collider = pygame.sprite.groupcollide(self.player_manage.player_group,
enemy.bullet_group, False, True)
if player_enemy_bullet_collider:
self.player_manage.player.hp -= 1
if self.player_manage.player.hp <= 0:
self.ui_manage.is_victory = False
self.die()
self.state = "end"
# 玩家子弹与敌人子弹
for enemy in self.enemy_manage.enemy_group.sprites():
player_bullet_enemy_bullet_collider = pygame.sprite.groupcollide(self.player_manage.player.bullet_group,
enemy.bullet_group, True, True)
# 玩家与敌人
player_enemy_group_collider = pygame.sprite.groupcollide(self.player_manage.player_group,
self.enemy_manage.enemy_group,
False, True)
if player_enemy_group_collider:
self.player_manage.player.hp -= 2
if self.player_manage.player.hp <= 0:
self.ui_manage.is_victory = False
self.die()
self.state = "end"
# 玩家子弹与boss子弹
player_bullet_boss_bullet_collider = pygame.sprite.groupcollide(self.player_manage.player.bullet_group,
self.boss_manage.boss.bullet_group, True, True)
# 玩家与boos子弹
player_boos_bullet_collider = pygame.sprite.groupcollide(self.player_manage.player_group,
self.boss_manage.boss.bullet_group, False, True)
if player_boos_bullet_collider:
self.player_manage.player.hp -= 1
if self.player_manage.player.hp <= 0:
self.ui_manage.is_victory = False
self.die()
self.state = "end"
# 玩家与boss
player_boss_body_collider = pygame.sprite.groupcollide(self.player_manage.player_group,
self.boss_manage.boss_group, False, False)
if player_boss_body_collider:
self.player_manage.player.hp -= 1
if self.player_manage.player.hp <= 0:
self.ui_manage.is_victory = False
self.die()
self.state = "end"
每次碰撞都会有想要达到的目的 所以在碰撞之后我们可以进行判断 然后实现我们自己的功能。
11) 实现各种的连接
各种的连接 就是比如怎么让游戏管理类去管理BGManage PlayerManage EnemyManage BossManage PropManage 等 我们需要使用 self.bg_manage = BGManage(self) 在游戏管理类的初始化中 还有就是怎么可以实现 BGManage 中调用游戏管理的内容 比如窗口 我们就要在BGManage中初始化函数中self.gm = gm 其中gm是游戏管理类的实例, 还有就是管理类通过创建精灵组去管理精灵类 从而达到我们先要的效果!!
12) 源代码
代码仅供参考:
import random
import sys
import pygame
class AudioMusic:
@staticmethod
def play_bg_music():
pygame.mixer.music.load("music/bg_music1.mp3")
pygame.mixer.music.play(-1)
@staticmethod
def begin_music(name):
sound = pygame.mixer.Sound(name)
sound.play()
@staticmethod
def button_music(name):
sound = pygame.mixer.Sound(name)
sound.play()
@staticmethod
def boss_bg():
pygame.mixer.music.load("music/boos_bg.mp3")
pygame.mixer.music.play(-1)
@staticmethod
def boss_begin(name):
sound = pygame.mixer.Sound(name)
sound.play()
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
class BaseSprite(pygame.sprite.Sprite):
def __init__(self, name):
super().__init__()
self.image = pygame.image.load(name)
self.rect = self.image.get_rect()
class BGSprite(BaseSprite):
def __init__(self, name, topleft):
super().__init__(name)
self.rect.topleft = topleft
def update(self):
self.rect.top += 2
if self.rect.top >= 900:
self.rect.top = -900
class BGManage:
def __init__(self, gm):
self.gm = gm
self.bg_group = pygame.sprite.Group()
BGSprite("img/gaming_bg.jpg", (0, 0)).add(self.bg_group)
BGSprite("img/gaming_bg.jpg", (0, -900)).add(self.bg_group)
def update(self):
self.bg_group.update()
self.bg_group.draw(self.gm.screen)
class BulletSprite(BaseSprite):
def __init__(self, name, centerx, y, speed):
super().__init__(name)
self.rect.centerx = centerx
self.rect.top = y
self.speed = speed
self.time_count = 2
def update(self):
self.time_count -= 2
if self.time_count <= 0:
self.time_count = 2
self.rect.top += self.speed
if self.rect.top > 900 or self.rect.bottom < 0:
self.kill()
class PlayerSprite(BaseSprite):
def __init__(self, name, center, speed, gm):
super().__init__(name)
self.gm = gm
self.rect.center = center
self.speed = speed
self.max_hp = 10
self.hp = 10
self.shoot_time = 2
self.bullet_group = pygame.sprite.Group()
self.super_bullet_num1 = 0
self.super_bullet_num2 = 0
def shoot(self):
BulletSprite("img/bullet.png", self.rect.centerx, self.rect.top - 50, -20).add(self.bullet_group)
def shoot1(self):
for i in range(5):
BulletSprite("img/bullet.png", self.rect.centerx - 20 + 10 * i, self.rect.top - 50, -20).add(
self.bullet_group)
def shoot2(self):
BulletSprite("img/bullet.png", self.rect.centerx, self.rect.top - 50, -20).add(self.bullet_group)
BulletSprite("img/bullet.png", self.rect.centerx - 75, self.rect.top - 50, -20).add(self.bullet_group)
BulletSprite("img/bullet.png", self.rect.centerx + 75, self.rect.top - 50, -20).add(self.bullet_group)
def shoot3(self):
for i in range(7):
BulletSprite("img/bullet.png", self.rect.centerx - 30 + 10 * i, self.rect.top - 50, -20).add(
self.bullet_group)
def draw_hp(self):
pygame.draw.rect(self.image, (127, 127, 127), (self.rect.width / 2 - 75, self.rect.height - 10, 150, 10))
pygame.draw.rect(self.image, (0, 255, 0),
(self.rect.width / 2 - 75, self.rect.height - 10, self.hp / self.max_hp * 150, 10))
def update(self):
self.draw_hp()
self.shoot_time -= 0.8
if self.shoot_time <= 0:
self.shoot_time = 2
value = random.random()
if value > 0.5:
if self.super_bullet_num1 > 0:
self.shoot1()
self.super_bullet_num1 -= 1
else:
self.shoot()
else:
if self.super_bullet_num2 > 0:
self.shoot2()
self.super_bullet_num2 -= 1
else:
self.shoot()
key_presses = pygame.key.get_pressed()
if key_presses[pygame.K_a] and self.rect.left > 0:
self.rect.left -= self.speed
if key_presses[pygame.K_d] and self.rect.right < 1500:
self.rect.right += self.speed
if key_presses[pygame.K_w] and self.rect.top > 0:
self.rect.top -= self.speed
if key_presses[pygame.K_s] and self.rect.bottom < 900:
self.rect.bottom += self.speed
self.bullet_group.update()
self.bullet_group.draw(self.gm.screen)
class PlayerManage:
def __init__(self, gm):
self.gm = gm
self.score = None
self.player_group = pygame.sprite.Group()
self.player = PlayerSprite("img/player1.png", (750, 825), 20, self.gm)
AudioMusic.play_bg_music()
def born(self):
self.player = PlayerSprite("img/player1.png", (750, 825), 20, self.gm)
self.player.hp = 10
self.score = 0
self.player.add(self.player_group)
def update(self):
self.player_group.update()
self.player_group.draw(self.gm.screen)
class EnemySprite(BaseSprite):
def __init__(self, name, centerx, y, speed, hp, gm):
super().__init__(name)
self.rect.centerx = centerx
self.rect.top = y
self.speed = speed
self.hp = hp
self.max_hp = hp
self.bullet_group = pygame.sprite.Group()
self.time_count2 = 2
self.time_move = 2
self.gm = gm
def shoot(self):
value = random.random()
if value > 0.7:
BulletSprite("img/enemybullet.png", self.rect.centerx - 20, self.rect.top + self.rect.height + 30, 10).add(
self.bullet_group)
else:
BulletSprite("img/enemybullet.png", self.rect.centerx - 20, self.rect.top + self.rect.height + 30, 10).add(
self.bullet_group)
def draw_hp(self):
pygame.draw.rect(self.image, (127, 127, 127), (self.rect.width / 2 - 40, self.rect.height - 78, 70, 15))
pygame.draw.rect(self.image, (0, 255, 0),
(self.rect.width / 2 - 40, self.rect.height - 78, self.hp / self.max_hp * 70, 15))
def update(self):
self.time_count2 -= 0.1
if self.time_count2 <= 0:
self.time_count2 = 2
self.shoot()
self.time_move -= 0.5
if self.time_move <= 0:
self.time_move = 2
value = random.random()
if value > 0.5:
self.rect.top += self.speed * 2
self.rect.centerx += self.speed
else:
self.rect.top += self.speed * 2
self.rect.centerx -= self.speed * 2
if self.rect.y > 900 or self.rect.right > 1500 or self.rect.left < 0:
self.kill()
self.draw_hp()
self.bullet_group.update()
self.bullet_group.draw(self.gm.screen)
class EnemyManage:
def __init__(self, gm):
self.gm = gm
self.enemy_group = pygame.sprite.Group()
self.time_count1 = 5
def generate(self):
value = random.random()
# if value > 0.9:
# EnemySprite("img/enemy3.png", random.randrange(25, 1500, 25), 0, 4, 8, self.gm).add(self.enemy_group)
if value > 0.5:
EnemySprite("img/enemy1.png", random.randrange(50, 1450, 25), 0, 6, 8, self.gm).add(self.enemy_group)
# if value > 0.3:
# EnemySprite("img/enemy4.png", random.randrange(25, 1500, 25), 0, 8, 4, self.gm).add(self.enemy_group)
if value > 0:
EnemySprite("img/enemy.png", random.randrange(50, 1450, 25), 0, 8, 6, self.gm).add(self.enemy_group)
def update(self):
self.time_count1 -= 0.2
if self.time_count1 <= 0:
self.time_count1 = 5
self.generate()
self.enemy_group.update()
self.enemy_group.draw(self.gm.screen)
class BossSprite(BaseSprite):
def __init__(self, name, center, hp, gm):
super().__init__(name)
self.rect.center = center
self.boss_speed = 5
self.hp = hp
self.max_hp = hp
self.bullet_group = pygame.sprite.Group()
self.gm = gm
self.time_count5 = 2
def shoot(self):
BulletSprite("img/boss_bullet.png", self.rect.centerx, self.rect.centery, 10).add(
self.bullet_group)
def draw_hp(self):
pygame.draw.rect(self.image, (127, 127, 127), (self.rect.width / 2 - 200, self.rect.height - 310, 400, 20))
pygame.draw.rect(self.image, (0, 255, 0),
(self.rect.width / 2 - 200, self.rect.height - 310, self.hp / self.max_hp * 400, 20))
def update(self):
self.rect.centerx -= self.boss_speed
if self.rect.centerx > 1300 or self.rect.centerx < 200:
self.boss_speed *= -1
self.time_count5 -= 0.2
if self.time_count5 <= 0:
self.time_count5 = 2
self.shoot()
self.draw_hp()
self.bullet_group.update()
self.bullet_group.draw(self.gm.screen)
class BossManage:
def __init__(self, gm):
self.gm = gm
self.boss_group = pygame.sprite.Group()
self.boss = BossSprite("img/boss.png", (random.randrange(200, 1300, 50), 200), 400, self.gm)
def born(self):
self.boss.hp = 400
def update(self):
if self.gm.player_manage.score >= 50:
self.boss.add(self.boss_group)
self.boss_group.update()
self.boss_group.draw(self.gm.screen)
class PropSprite(BaseSprite):
def __init__(self, name, centerx, y, speed, type):
super().__init__(name)
self.rect.centerx = centerx
self.rect.top = y
self.speed = speed
self.time_count3 = 2
self.type = type
def update(self):
self.time_count3 -= 2
if self.time_count3 <= 0:
self.time_count3 = 2
self.rect.top += self.speed
if self.rect.y > 900:
self.kill()
class PropManage:
def __init__(self, gm):
self.gm = gm
self.prop_group = pygame.sprite.Group()
self.time_count4 = 6
def generate(self):
value = random.random()
if value > 0.9:
PropSprite("img/daojubaozha.png", random.randrange(50, 1450, 25), 0, 8, 1).add(self.prop_group)
elif value > 0.5:
PropSprite("img/jiaxie.png", random.randrange(75, 1450, 25), 0, 8, 2).add(self.prop_group)
else:
PropSprite("img/player1(1).png", random.randrange(50, 1450, 25), 0, 8, 3).add(self.prop_group)
def update(self):
self.time_count4 -= 0.2
if self.time_count4 <= 0:
self.time_count4 = 6
self.generate()
self.prop_group.update()
self.prop_group.draw(self.gm.screen)
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.is_victory = None
self.font = pygame.font.Font("font/font.ttf", 32)
self.font1 = pygame.font.Font("font/font.ttf", 128)
# 游戏开始前的UI
self.ready_group = pygame.sprite.Group()
self.ready_btn1 = UISprite("img/bg.jpg", (750, 450))
self.ready_btn2 = UISprite("img/begin_gaming.png", (750, 450))
self.ready_over_image = UISprite("img/end.png", (750, 600))
self.ready_btn1.add(self.ready_group)
self.ready_btn2.add(self.ready_group)
self.ready_over_image.add(self.ready_group)
# 游戏中的UI
# self.gaming_group = pygame.sprite.Group()
# self.gaming_score = self.font.render(f"Score:{self.gm.player_manage.score}", True, "#FF4500")
# 游戏后的UI
self.end_group = pygame.sprite.Group()
self.end_bg_image = UISprite("img/bg.jpg", (750, 450))
self.end_fail_image = UISprite("img/fail.png", (750, 150))
self.end_btn = UISprite("img/rebegin.png", (750, 450))
self.end_end_image = UISprite("img/end.png", (750, 600))
self.end_victory_image = UISprite("img/victory.png", (750, 150))
self.end_bg_image.add(self.end_group)
self.end_btn.add(self.end_group)
self.end_end_image.add(self.end_group)
self.fail_group = pygame.sprite.Group()
self.end_fail_image.add(self.fail_group)
self.victory_group = pygame.sprite.Group()
self.end_victory_image.add(self.victory_group)
# 游戏暂停的UI
self.paused_group = pygame.sprite.Group()
self.paused_image = UISprite("img/continue.png", (750, 450))
self.paused_image.add(self.paused_group)
def update(self):
# 游戏前
if self.gm.state == "ready":
self.ready_group.draw(self.gm.screen)
if Util.click_check(self.ready_btn1):
AudioMusic.button_music("music/button.mp3")
self.gm.state = "gaming"
self.gm.boss_manage.born()
self.gm.player_manage.born()
if Util.click_check(self.ready_over_image):
AudioMusic.button_music("music/button.mp3")
pygame.quit()
sys.exit()
# AudioMusic.begin_music("music/begin_music.mp3")
elif self.gm.state == "gaming":
self.score_surface = self.font.render(f"Score:{self.gm.player_manage.score}", True, "#FF4500")
self.gm.draw_update()
self.gm.screen.blit(self.score_surface, (1350, 50))
elif self.gm.state == "end":
self.end_group.draw(self.gm.screen)
self.end_score_surface = self.font1.render(f"Score:{self.gm.player_manage.score}", True, "#7CFC00")
self.gm.screen.blit(self.end_score_surface, (550, 200))
if self.is_victory == False:
self.fail_group.draw(self.gm.screen)
elif self.is_victory == True:
self.victory_group.draw(self.gm.screen)
if Util.click_check(self.end_btn):
AudioMusic.button_music("music/button.mp3")
self.gm.die()
self.gm.state = "gaming"
self.gm.boss_manage.born()
self.gm.player_manage.born()
if Util.click_check(self.end_end_image):
AudioMusic.button_music("music/button.mp3")
pygame.quit()
sys.exit()
elif self.gm.state == "paused":
self.paused_group.draw(self.gm.screen)
if Util.click_check(self.paused_image):
AudioMusic.button_music("music/button.mp3")
self.gm.state = "gaming"
class GameManage:
def __init__(self):
pygame.init()
self.state = "ready"
self.is_paused = False
self.clock = pygame.time.Clock()
self.screen = pygame.display.set_mode((1500, 900))
self.rect = self.screen.get_rect()
pygame.display.set_caption("飞机")
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)
def die(self):
self.boss_manage.boss_group.empty()
self.player_manage.player_group.empty()
self.enemy_manage.enemy_group.empty()
self.player_manage.player.bullet_group.empty()
self.prop_manage.prop_group.empty()
def check_collider(self):
# 玩家与道具
player_prop_collider = pygame.sprite.groupcollide(self.player_manage.player_group, self.prop_manage.prop_group,
False, True)
if player_prop_collider:
for props in player_prop_collider.values():
for prop in props:
if prop.type == 1:
self.enemy_manage.enemy_group.empty()
if prop.type == 2:
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
if prop.type == 3:
value = random.random()
if value > 0.5:
self.player_manage.player.super_bullet_num1 = 20
else:
self.player_manage.player.super_bullet_num2 = 20
# 玩家子弹与敌人
player_bullet_enemy_collider = pygame.sprite.groupcollide(self.player_manage.player.bullet_group,
self.enemy_manage.enemy_group, True, False)
if player_bullet_enemy_collider:
for enemys in player_bullet_enemy_collider.values():
for enemy in enemys:
enemy.hp -= 2
if enemy.hp <= 0:
self.player_manage.score += 1
enemy.kill()
# 玩家子弹与boss
player_bullet_boss_collider = pygame.sprite.groupcollide(self.player_manage.player.bullet_group,
self.boss_manage.boss_group, True, False)
if player_bullet_boss_collider:
self.boss_manage.boss.hp -= 2
if self.boss_manage.boss.hp <= 0:
self.die()
self.ui_manage.is_victory = True
self.state = "end"
# 玩家与敌人子弹
for enemy in self.enemy_manage.enemy_group.sprites():
player_enemy_bullet_collider = pygame.sprite.groupcollide(self.player_manage.player_group,
enemy.bullet_group, False, True)
if player_enemy_bullet_collider:
self.player_manage.player.hp -= 1
if self.player_manage.player.hp <= 0:
self.ui_manage.is_victory = False
self.die()
self.state = "end"
# 玩家子弹与敌人子弹
for enemy in self.enemy_manage.enemy_group.sprites():
player_bullet_enemy_bullet_collider = pygame.sprite.groupcollide(self.player_manage.player.bullet_group,
enemy.bullet_group, True, True)
# 玩家与敌人
player_enemy_group_collider = pygame.sprite.groupcollide(self.player_manage.player_group,
self.enemy_manage.enemy_group,
False, True)
if player_enemy_group_collider:
self.player_manage.player.hp -= 2
if self.player_manage.player.hp <= 0:
self.ui_manage.is_victory = False
self.die()
self.state = "end"
# 玩家子弹与boss子弹
player_bullet_boss_bullet_collider = pygame.sprite.groupcollide(self.player_manage.player.bullet_group,
self.boss_manage.boss.bullet_group, True, True)
# 玩家与boos子弹
player_boos_bullet_collider = pygame.sprite.groupcollide(self.player_manage.player_group,
self.boss_manage.boss.bullet_group, False, True)
if player_boos_bullet_collider:
self.player_manage.player.hp -= 1
if self.player_manage.player.hp <= 0:
self.ui_manage.is_victory = False
self.die()
self.state = "end"
# 玩家与boss
player_boss_body_collider = pygame.sprite.groupcollide(self.player_manage.player_group,
self.boss_manage.boss_group, False, False)
if player_boss_body_collider:
self.player_manage.player.hp -= 1
if self.player_manage.player.hp <= 0:
self.ui_manage.is_victory = False
self.die()
self.state = "end"
def check_is_paused(self):
if self.is_paused == True:
self.state = "paused"
else:
self.state = "gaming"
def draw_update(self):
self.bg_manage.update()
self.player_manage.update()
self.enemy_manage.update()
self.prop_manage.update()
self.boss_manage.update()
self.check_collider()
def run(self):
while True:
self.clock.tick(24)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
self.is_paused = True
self.check_is_paused()
key_presses = pygame.key.get_pressed()
if key_presses[pygame.K_DOWN]:
self.player_manage.player.shoot3()
self.ui_manage.update()
pygame.display.flip()
gm = GameManage()
gm.run()