目录
前言
我在使用Pygame制作一款游戏时,需要使用场景系统。不过Pygame官方好像没有制作场景模块。所以我打算自己写一个简单的场景系统并分享到CSDN。
您也可以把这篇文章的pygame项目当作您的pygame项目的起始模板。
文件结构
首先,先写一个空Pygame项目,settings.py声明了常量。main.py调用settings.py的常量
Game
├─ settings.py
└─ main.py
常量设置
将常量分文件,以免过于杂乱
# settings.py
WINDOWWIDTH = 300
WINDOWHEIGHT = 300
WINDOWTITLE = '场景测试'
FPS = 60
场景系统实现
设计
在开始写代码之前,我们先确认需要什么功能,场景模块应该是什么样的
我的想法是:每个场景使用独立的类。而且这个场景类不需要继承其他的类。所有函数(比如切换场景)都将在SceneManager中运行。每个场景的类只需要被SceneManager所调用,自身除了该场景的游戏代码之外无需运行其他代码。所以我将KeyGet放入SceneManager。因为SceneManager要是调用场景类的KeyDown,KeyUp等函数
SceneManager类需要做的事情清单
SceneManager
├─ ChangeScene # 切换场景
├─ KeyGet # 按键获取
└─ Loop # 游戏循环
场景类的所有将被SceneManager所调用的函数(SceneManager有判定场景类是否有即将调用的函数)
class Scene2():
def __init__(self):
pass
def Update(self):
pass
def Render(self):
pass
def Close(self):
pass
def KeyUp(self,Key):
pass
def KeyDown(self,Key):
pass
实现
接下来开始实现SceneManager,首先先导入所需库
import pygame
from pygame.locals import *
from settings import *
然后写SceneManager类,初始化时启动游戏窗口,常量在settings.py里面设置了
class SceneManager():
def __init__(self,Scene):
# 参数说明 —— Scene: 起始场景
# 初始化Pygame
pygame.init()
# 窗口标题
pygame.display.set_caption(WINDOWTITLE)
# Fps时钟
self.FpsClock = pygame.time.Clock()
# 设置窗口大小
self.DisplaySurf = pygame.display.set_mode((WINDOWWIDTH ,WINDOWHEIGHT))
# 当前场景
self.CurrentScene = Scene()
# 已按下的按键,Pygame没有这个接口,自己用其他接口实现
self.KeyPressed = []
然后,SceneManager类还需要做两件事,分别是:修改当前场景 按键获取 游戏循环 。我们一个一个实现,首先先实现修改当前场景。
def ChangeScene(self,Scene):
# 参数说明 —— Scene: 将当前场景替换为该场景
# 执行该场景的Close函数
if hasattr(self.CurrentScene,'Close'):self.CurrentScene.Close()
# 切换成新场景
self.CurrentScene = Scene()
接着是GetKey,这个函数需要调用场景类的KeyUp和KeyDown。还需要设置KeyPressed(那些按键是被按下状态)
def GetKey(self):
for event in pygame.event.get():
# 退出事件
if event.type == QUIT:
pygame.quit()
sys.exit()
# 按键按下
if event.type == KEYDOWN:
# 在KeyPressed里添加按键
self.KeyPressed.append(event.key)
# 判断是否存在函数后调用按键按下函数
if hasattr(self.CurrentScene,'KeyDown'): self.CurrentScene.KeyDown(event.key)
# 按键松开
if event.type == KEYUP:
# 删除KeyPressed里的按键
self.KeyPressed.remove(event.key)
# 判断是否存在函数后调用按键松开函数
if hasattr(self.CurrentScene,'KeyUp'): self.CurrentScene.KeyUp(event.key)
最后,是游戏的循环。循环需要按顺序执行: 获取按键 ——> 调用当前场景的Update函数 ——> 调用当前场景的Render函数 ——> fps控制
def Loop(self):
while True:
# 获取按键
self.GetKey()
# 调用
if hasattr(self.CurrentScene,'Update'):self.CurrentScene.Update()
if hasattr(self.CurrentScene,'Render'):self.CurrentScene.Render()
pygame.display.update()
# Fps控制
self.FpsClock.tick(FPS)
好了,现在就SceneManager的全部功能了,场景类可以调用SceneManager的函数分别是:
GAME.ChangeScene(场景类名称) # 切换场景
GAME.KeyPressed # 返回按下的按钮
全部代码:
# main.py
import pygame
from pygame.locals import *
from settings import *
class SceneManager():
def __init__(self,Scene):
pygame.init()
pygame.display.set_caption(WINDOWTITLE)
self.FpsClock = pygame.time.Clock()
self.DisplaySurf = pygame.display.set_mode((WINDOWWIDTH ,WINDOWHEIGHT))
self.CurrentScene = Scene()
self.KeyPressed = []
def ChangeScene(self,Scene):
if hasattr(self.CurrentScene,'Close'):self.CurrentScene.Close()
self.CurrentScene = Scene()
def GetKey(self):
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
self.KeyPressed.append(event.key)
if hasattr(self.CurrentScene,'KeyDown'): self.CurrentScene.KeyDown(event.key)
if event.type == KEYUP:
self.KeyPressed.remove(event.key)
if hasattr(self.CurrentScene,'KeyUp'): self.CurrentScene.KeyUp(event.key)
def Loop(self):
while True:
self.GetKey()
if hasattr(self.CurrentScene,'Update'):self.CurrentScene.Update()
if hasattr(self.CurrentScene,'Render'):self.CurrentScene.Render()
pygame.display.update()
self.FpsClock.tick(FPS)
class Scene1():
def __init__(self):
print("Scene1 启动")
def Update(self):
# 切换到Scene2
GAME.ChangeScene(Scene2)
def Render(self):
print("Scene1 Render")
def Close(self):
print("Scene1 被关闭")
def KeyUp(self,Key):
print("在 Scene1 时按下按钮")
def KeyDown(self,Key):
print("在 Scene1 时松开按钮")
class Scene2():
def __init__(self):
print("我是 Scene2")
def Update(self):
print("按下的按键有",GAME.KeyPressed)
GAME = SceneManager(Scene1)
GAME.Loop()
# settings.py
WINDOWWIDTH = 300
WINDOWHEIGHT = 300
WINDOWTITLE = 'Pygame 场景测试'
FPS = 60
你可以使用该项目作为您的Pygame起始项目。建议收藏备用