引言
在本博客中,我们将探讨如何使用Pygame库来制作一个简单的2D射击游戏。通过这个示例,我们将学习如何使用面向对象的编程方法来构建游戏中的各种元素,包括玩家飞船、敌人、背景、音效等。
基本结构
首先,我们导入了需要的模块:random
、sys
和pygame
。接着定义了一个工具类Utils
,其中包含了一些静态方法,用于实现点击检测。此外,我们还定义了一个音频管理类AudioManage
,用于处理游戏中的声音效果。
import random, sys, pygame
class Utils:
"""
提供一些静态方法
"""
@staticmethod
def click_check(sprite):
if pygame.mouse.get_pressed()[0]:
if sprite.rect.collidepoint(pygame.mouse.get_pos()):
return True
return False
class AudioManage:
@staticmethod
def start_music():
pygame.mixer.music.load("sound/start.wav")
pygame.mixer.music.play(loops=-1)
@staticmethod
def play_bg_music():
pygame.mixer.music.load("sound/background.wav")
pygame.mixer.music.play(loops=-1)
@staticmethod
def bullet(name):
sound = pygame.mixer.Sound(name)
channel = pygame.mixer.Channel(4)
channel.play(sound)
@staticmethod
def killing(name):
sound = pygame.mixer.Sound(name)
channel = pygame.mixer.Channel(5)
channel.play(sound)
游戏元素类
接下来,我们定义了一些游戏元素的类:
BaseSprite
:这是所有精灵类的基类,包含了精灵的基本属性和方法。EnemySprite
:敌人飞船类,继承自BaseSprite
,表示游戏中的敌人。BulletSprite
:子弹类,用于表示玩家飞船发射的子弹。PlayerSprite
:玩家飞船类,继承自BaseSprite
,表示玩家操控的飞船。class BaseSprite(pygame.sprite.Sprite): def __init__(self, image_name): super().__init__() self.image = pygame.image.load(image_name) self.rect = self.image.get_rect() class EnemySprite(BaseSprite): def __init__(self, image_name, center): super().__init__(image_name) self.rect.center = center class BulletSprite(BaseSprite): def __init__(self, image_name, center): super().__init__(image_name) self.rect.center = center def update(self): self.rect.top -= 1 if self.rect.bottom < 0: self.kill() class PlayerSprite(BaseSprite): def __init__(self, image_name, center): super().__init__(image_name) self.rect.center = center self.bullet_group = pygame.sprite.Group() self.bullet_gap = 5 def shot(self): key_pressed = pygame.key.get_pressed() if key_pressed[pygame.K_SPACE]: self.bullet_gap -= 0.1 if self.bullet_gap <= 0: self.bullet_gap = 5 AudioManage.bullet("sound/bullet2.wav") BulletSprite("img/bullet.png", (self.rect.centerx, self.rect.centery)).add(self.bullet_group) self.bullet_group.update()
管理类
然后,我们定义了一些管理类:
EnemyManage
:管理敌人的生成、移动和碰撞检测等逻辑。PlayerManage
:管理玩家飞船的移动、射击和碰撞检测逻辑。BGManage
:管理游戏背景的移动和更新逻辑。UIManage
:管理游戏界面的显示和状态切换。
class EnemyManage:
def __init__(self, gm):
self.gm = gm
self.init_enemy_num = 4
# 生成敌人组
self.enemy_group = pygame.sprite.Group()
# 生成敌人计时器
self.count_time = 10
def generate_enemy(self):
self.count_time -= 0.1
if self.count_time <= 0:
self.count_time = 10
enemy = EnemySprite("img/enemy.png", ((random.randint(0, 736), 0)))
enemy.add(self.enemy_group)
def update(self):
self.enemy_group.draw(self.gm.screen)
self.generate_enemy()
self.move()
def move(self):
for every_enemy in self.enemy_group.sprites():
every_enemy.rect.top += 1
if every_enemy.rect.bottom > 600:
every_enemy.kill()
class PlayerManage:
def __init__(self, gm):
self.gm = gm
self.player_group = pygame.sprite.Group()
self.player = PlayerSprite("img/player.png", (400, 568))
self.player.add(self.player_group)
def player_move(self):
keyword_pressed = pygame.key.get_pressed()
if keyword_pressed[pygame.K_LEFT] and self.player.rect.left > 0:
self.player.rect.left -= 5
if keyword_pressed[pygame.K_RIGHT] and self.player.rect.right < 800:
self.player.rect.left += 5
if keyword_pressed[pygame.K_UP] and self.player.rect.top > 0:
self.player.rect.top -= 5
if keyword_pressed[pygame.K_DOWN] and self.player.rect.bottom < 600:
self.player.rect.top += 5
def is_kill(self):
if pygame.sprite.groupcollide(self.player.bullet_group, self.gm.enemy_manage.enemy_group, True, True):
AudioManage.killing("sound/explosion.wav")
self.gm.score += 50
return True
return False
def update(self):
self.player_group.draw(self.gm.screen)
self.player.add(self.player_group)
self.player.shot()
self.player_move()
self.player.bullet_group.update()
self.is_kill()
self.player.bullet_group.draw(self.gm.screen)
class BGManage:
def __init__(self, gm):
self.gm = gm
self.bg_group = pygame.sprite.Group()
self.bg_image_1 = BGSprite("img/background.png", (0, 0))
self.bg_image_2 = BGSprite("img/background.png", (0, -600))
self.bg_image_1.add(self.bg_group)
self.bg_image_2.add(self.bg_group)
def update(self):
self.bg_group.update()
self.bg_group.draw(self.gm.screen)
class UIManage:
def __init__(self, gm):
self.gm = gm
self.score_surface = self.gm.game_font.render(f"score:{self.gm.score}", True, "red")
# 设置游戏开始组
self.start_group = pygame.sprite.Group()
self.start_button = UISprite("img/start_but.png", (400, 300))
self.start_button.add(self.start_group)
# 设置游戏结束组
self.end_group = pygame.sprite.Group()
self.restart_button = UISprite("img/restart_but.png", (400, 250))
self.exit_button = UISprite("img/exit_but.png", (400, 350))
self.exit_button.add(self.end_group)
self.restart_button.add(self.end_group)
def update(self, state):
if state == "ready":
self.start_group.draw(self.gm.screen)
if Utils.click_check(self.start_button):
AudioManage.play_bg_music()
self.gm.player_manage.update()
self.gm.state = "gaming"
if state == "gaming":
self.score_surface = self.gm.game_font.render(f"score:{self.gm.score}", True, "red")
self.gm.screen.blit(self.score_surface, (0, 0))
for i in self.gm.enemy_manage.enemy_group.sprites():
if pygame.sprite.groupcollide(self.gm.enemy_manage.enemy_group, self.gm.player_manage.player_group,
True, True):
AudioManage.killing("sound/isdead.wav")
if not self.gm.player_manage.player_group:
AudioManage.start_music()
self.gm.state = "end"
if state == "end":
self.end_group.draw(self.gm.screen)
if Utils.click_check(self.exit_button):
pygame.quit()
sys.exit()
elif Utils.click_check(self.restart_button):
self.gm.player_manage.player_group.empty()
self.gm.enemy_manage.enemy_group.empty()
self.end_group.empty()
self.gm.score = 0
self.gm.state = "gaming"
AudioManage.play_bg_music()
self.gm.player_manage = PlayerManage(self.gm)
self.gm.enemy_manage = EnemyManage(self.gm)
self.exit_button.add(self.end_group)
self.restart_button.add(self.end_group)
游戏管理类
最后,我们定义了GameManage
类,该类负责游戏的初始化、运行和主循环。在主循环中,我们检测退出事件,然后根据游戏状态更新背景、界面以及各个元素的状态。
class GameManage:
def __init__(self):
# 初始化pygame
pygame.init()
# 游戏状态有三种:ready,gaming和end,初始化游戏状态为ready
self.state = "ready"
self.score = 0
# 初始化背景音乐
AudioManage.start_music()
# 设置游戏图标
self.icon = pygame.image.load("img/ufo.png")
pygame.display.set_icon(self.icon)
# 设置帧数
self.clock = pygame.time.Clock()
# 设置游戏字体
self.game_font = pygame.font.Font("font/game.ttf", 30)
# 初始化主屏幕
self.screen = pygame.display.set_mode((800, 600))
# 设置游戏窗口标题
pygame.display.set_caption("AIR_WAR")
# 导入UIManage类
self.ui_manage = UIManage(self)
# 导入BGManage类
self.bg_manage = BGManage(self)
# 导入PlayerManage类
self.player_manage = PlayerManage(self)
# 导入EnemyManage类
self.enemy_manage = EnemyManage(self)
def exit_detect(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
def updating(self):
self.bg_manage.update()
self.player_manage.update()
self.enemy_manage.update()
# 定义运行函数
def run(self):
while True:
self.exit_detect()
# 设置主屏幕背景图
self.bg_manage.update()
self.ui_manage.update(self.state)
if self.state == "gaming":
self.updating()
self.ui_manage.update("gaming")
pygame.display.flip()
游戏展示
接下来我们可以创建一个游戏类的实例来用于启动这个游戏
gm = GameManage()
gm.run()
图片展示
视频展示
AIR_WAR
结尾
通过这段代码,我们展示了如何使用Pygame库和面向对象的编程方法来制作一个简单的2D射击游戏。每个类都有其独特的功能,通过组合它们,我们可以构建出一个完整的游戏。
附录
最后,我会将这个项目上传到免费资源中,对这个项目感兴趣的读者可以进入我的个人主页进行获取,我也会将相关下载链接加入下方使读者方便获取可以在需要时进行获取并可以根据实际操作。