状态模式复习

在游戏开发中,经常涉及到场景的转换,从本质上来说,场景的转换非常类似舞台剧。因此对于场景的控制,简单粗暴直观的写法:

class SceneManager(object):

    def __init__(self):
        self.m_state = None

    def change_scene(self, statename):
        self.m_state = statename

        if self.m_state == "菜单":
            print("LoadLevel MainMenuScene")
        elif self.m_state == "主场景":
            print("LoadLevel MainScene")

    def update_scene(self):
        if self.m_state == "开始":
            print("update 开始 scene")
        elif self.m_state == "菜单":
            print("update MainMenuScene")
        elif self.m_state == "主场景":
            print("update MainScene"

ok,这样简单粗暴的解决了问题,场景很少很简单,当然是没问题的。但有以下缺点:只要增加一个新的场景,就意味着change_scene函数和update_scene函数都需要加入对应的代码。每一个场景类继承的父类可能不同,容易造成SceneManager过度依赖其他类。为了解决这个问题,使用状态模式来解决,状态模式除了能解决场景切换的问题,其实当我们玩英雄联盟,接触豹女和杰斯,同理,也是这样的一个情况。

状态模式

在这里插入图片描述
看不懂箭头的线,可搜索设计模式UML图,即可了解关系。

StateOwner也就是对应图上的Context

class StateOwner:
    def __init__(self):
        self.m_state = None

    def request(self, value):
        self.m_state.handle(value)

    def setstate(self, state):
        print("steState-------->{}".format(state.__class__.__name__))
        self.m_state = state

各种状态的写法如下:

class State:
    def __init__(self, the_stateowner):
        self.m_stateowner = the_stateowner

    def handle(self, value):
        pass


class StateA(State):
    def handle(self, value):
        print("stateA Handle")
        if value > 10:
            print("value > 10 ,状态改变")
            self.m_stateowner.setstate(StateB(self.m_stateowner))


class StateB(State):
    def handle(self, value):
        print("stateB Handle")
        if value > 20:
            print("value > 20 ,状态改变")
            self.m_stateowner.setstate(StateC(self.m_stateowner))


class StateC(State):
    def handle(self, value):
        print("stateC Handle")
        if value > 30:
            print("value > 30 ,状态改变")
            self.m_stateowner.setstate(StateA(self.m_stateowner))

测试的案例如下:

def Test():
    """
    # 最简单的状态模式代码,可以比较简单的替代switch 模式下的状态转换
    :return: None
    """
    stateowner = Stateowner()
    stateowner.setstate(StateA(stateowner))
    stateowner.request(5)
    stateowner.request(15)
    stateowner.request(25)
    stateowner.request(35)

Test()

下面是游戏实战应用,某游戏把游戏进程分成了三个过程:开始场景、主画面场景、战斗场景。设计一个基础的场景类Scene,StartScene、MainMenuScene、BattleScene继承Scene,Scene有三个成员函数:scenebegin 、 sceneend、 sceneupdate。
scenebegin:负责资源的加载和游戏参数的设置;
sceneend:释放游戏不再使用的资源,重新设置游戏场景状态。
sceneupdate:该方法是在每一帧被调用,场景定时更新功能。下面是代码示例:

class Scene(object):
    def __init__(self, scene_mgr):
        self.scene_mgr = scene_mgr

    # 当前场景的名称
    @property
    def scenename(self):
        return self._scenename

    @scenename.setter
    def scenename(self, name):
        self._scenename = name

    def scenebegin(self):
        """子类重写"""
        pass

    def sceneend(self):
        """子类重写"""
        pass

    def update(self):
        """子类重写"""
        pass


class StartScene(Scene):

    def __init__(self):
        super(StartScene, self).__init__(self.scene_mgr)
        self.scenename = "StartScene"

    def scenebegin(self):
        print("Begin load StartScene model and res")
        print("Begin load ui")
        print("Begin bind ui")

    def sceneend(self):
        print("destroy StartScene model and res")
        print("destroy StartScene ui")

    def update(self):
        print("Update StartScene")


class MainMenuScene(Scene):

    def __init__(self):
        super(MainMenuScene, self).__init__(self.scene_mgr)
        self.scenename = "MainMenuScene"

    def scenebegin(self):
        print("Begin load MainMenuScene model and res")
        print("Begin load ui")
        print("Begin bind ui")

    def sceneend(self):
        print("destroy MainMenuScene model and res")
        print("destroy MainMenuScene ui")

    def update(self):
        print("Update MainMenuScene")


class BattleScene(Scene):
    def __init__(self):
        super(BattleScene, self).__init__(self.scene_mgr)
        self.scenename = "BattleScene"

    def scenebegin(self):
        print("Begin load BattleScene model and res")
        print("Begin BattleScene ui")
        print("Begin BattleScene ui")

    def sceneend(self):
        print("destroy BattleScene model and res")
        print("destroy BattleScene ui")

    def update(self):
        print("Update BattleScene")  # 输入


    def input_process(self):
        pass

除了以上的,还需要一个游戏主循环Game和场景管理器SceneMgr,在Game脚本中,定义并初始化SceneMgr,并且设置了第一个游戏的状态,StartScene,然后在Game中定时更新SceneMgr的update方法,并定时更新场景。

from Script.State_Patterns.Application import Scene


class SceneMgr:
    def __init__(self):
        self._scene = None
        self.is_scene_begin = False

    def setscene(self, scene, loadscenename):
        print("SetScene:".format(scene.scenename))
        if self._scene:  # 结束上一个scene
            self._scene.sceneend()
        self.is_scene_begin = False
        self._scene = scene
        self.loadscene(loadscenename)

    def scene_update(self):
        if self._scene:
            self._scene.sceneUpdate()

    def loadscene(self, loadsceneame):
        if not loadsceneame:
            return
        if self._scene and not self.is_scene_begin:
            self._scene.scenebegin()
            self.is_scene_begin = True


class Game(object):
    def __init__(self):
        self.scene_mgr = SceneMgr()

    def awake(self):
        pass

    def start(self):
        self.scene_mgr.setscene(Scene.StartScene(self.scene_mgr,""))

    def update(self):
        self.scene_mgr.scene_update()

以上就是状态模式的简单介绍,除了场景的管理使用该种模式,也可应用于

  • 角色AI:控制AI在不同状态下的行为
  • 关卡进行状态:通关类的游戏,包含数据加载、关卡信息显示、倒数通知、关卡进行、结束、分数计算。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值