一个多态性的游戏状态机系统

状态机(有限状态机、并发状态机、层次状态机) 2. 可以知道状态from-to,知道是从哪个状态向哪个状态进行切换,可以进行一些前置操作,例如在游戏暂停时重新开始游戏,可以在切换前重置游戏数据。使用状态机,可以避免使用if-else/switch-case进行逻辑的条件判断,导致代码臃肿,难以维护,扩展性差。游戏状态:初始化、开始、暂停、恢复、下一波敌人、3选1技能、失败、胜利、退出游戏等。但是角色的状态,行走、攻击、跳跃等是可以并行的,例如行走并攻击,跳跃并攻击。游戏流程的状态是单一的,从初始化,开始,结束等状态都只会同时存在一个。 阅读详情

-潘宏

-2012年12月

-本人水平有限,疏忽错误在所难免,还请各位高手不吝赐教

-email: popyy@netease.com

-weibo.com/panhong101

任何一款游戏产品,都需要在几种界面之间进行转换:logo、trailer、main menu、in-game、settings menu等等,并且会在这些转换之间处理资源问题。对于实现这样的转换,不同的游戏做法有所差异,但基本上会实现一个游戏状态机系统。状态机系统在游戏开发中根深蒂固,以至于该系统应该是游戏引擎不可或缺的一个核心部件。


简单游戏状态机结构

状态机的实现方法有很多。相对简单的有switch-case方法,它通过对游戏状态进行枚举化来进行选择判断。下面的示例代码展示了这一点:


    enum GameState  
    {  
        GAME_STATE_LOGO = 0,  
        GAME_STATE_TRAILER,  
        GAME_STATE_MAIN_MENU,  
        GAME_STATE_INGAME,  
        GAME_STATE_SETTINGS_MENU,  
    };  
      
    void gameCycle( int gameState )  
    {  
        switch( gameState )  
        {  
            case GAME_STATE_LOGO: {...}  
            case GAME_STATE_TRAILER: {...}  
            case GAME_STATE_MAIN_MENU: {...}  
            case GAME_STATE_INGAME: {...}  
            case GAME_STATE_SETTINGS_MENU: {...}  
        }  
    }  

这就是一个相当简单的游戏状态机系统,实现起来很直接、简洁。我们在几年前的一个Java引擎中就使用了这样的一个状态机系统(当然,实际代码要比这复杂一些,但结构是这样的)。它表现得很好,能够满足大多数的需求——有好几个商业游戏都使用了这个结构。


可是,在那之后,我们在一个新的C++引擎中,却放弃了这种方法。我们的理由主要有以下几点:


1)该方法不是OO的,我们的引擎是完全OO的。

2)该系统难以维护——所有的状态判断都在gameCycle的switch-case中,我们每增加或者修改一个状态,都需要在enum和gameCycle中增加新的代码,这会导致大量的重新编译。

3)大量的状态逻辑被集中到了switch-case中,导致代码臃肿,难以维护。

4)我们希望把每一个game state逻辑交给一个工程师来编写,这让我们很难做到。

5)“switch-case在OO中是一种‘坏味道’”思潮影响。


考虑到上面的几个原因,我们开始探索新的实现方式,然后,我们就有了一个新的、基于多态性的游戏状态机系统。



状态机基本结构设计


该系统的一个基本结构如下所示:


State manager就是状态管理器(后面简称manager),它聚合并管理多个game state(后面简称state)。注意,Manager只聚合state的基类指针,而state拥有自己的类体系。因此,manager通过多态的方式处理各种state。


该方法实际上实际上是一种state模式(如果对该模式感兴趣,请参考GoF的《设计模式》)。这里StateMgr相当于该模式的Context类,而GameState相当于该模式的State类。


我们的类初步设计如下:

    class GameState  
    {  
    public:  
        virtual ~GameState() {}  
      
        virtual void cycle() = 0;  
        virtual void draw( GraphicsContext& g ) = 0;  
    };  
      
    class StateMgr  
    {  
    public:  
        void addState( GameState* state )  
        {  
            m_states.push_back( state );  
        }  
      
          
        void cycle()  
        {  
            m_curState->cycle();  
        }  
      
        void draw( GraphicsContext& g )  
        {  
            m_curState->draw( g );  
        }  
          
      
    private:  
        std::set< GameState* >        m_states;  
        GameState*              m_curState;  
    };  

从代码中可以很容易看出该系统的工作原理。


GameState是state的base class,提供了GameState::cycle和GameState::draw两个方法,分别处逻辑更新和渲染两种工作。该base class是抽象的——只允许完成具体工作的derived class进行实例化。


StateMgr就是manager类,它通过m_states保存所有状态,并对当前状态m_curState进行更新和渲染。StateMgr::addState方法用语增加新的游戏状态。


我们看GameState的具体类的一个例子:

    class GameState_Logo : public GameState  
    {  
    public:  
        GameState_Logo()  
        {  
            Init m_logoImage and m_logoPos...  
        }  
      
        virtual void cycle()  
        {  
            if( m_logoPos is not identical to the screen center )  
            {  
                make m_logoPos close to the screen center...  
            }  
        }  
      
        virtual void draw( GraphicsContext& g )  
        {  
            draw m_logoImage at m_logoPos...  
        }  
      
    private:  
        Image*      m_logoImage;  
        Point2D     m_logoPos;  
    };  

上面的类处理进入游戏之后的logo界面。GameState_Logo的ctor初始化logo图片和位置这两个成员。GameState_Logo::cycle将logo的位置逐帧移动到屏幕中心。GameState_Logo::draw则在当前位置画出logo图片。


基本结构就是这样,简单吧!对于游戏不同状态的编写,基本上就是对不同的GameState子类进行实现。一个典型的游戏状态体系如下所示:



这样一个结构设计的好处是什么呢?


1)StateMgr只依赖GameState,和GameState的derived class没有耦合。

2)增加任何一个新的state,都不会影响manager,不会导致额外的重新编译。

3)state模式的全部优势。

4)该方法是完全OO的。


坏处呢?


1)使用了virtual function抽象,增加了间接层开销。

2)增加了大量的类源文件,实现起来不够紧凑。


现在,我们已经有了基本的结构。接下来要做的,就是在这些state之间进行转换。



游戏状态转换设计


游戏中的状态转换都会形成一个树形结构——游戏状态树。下图就是一个典型的游戏状态树:


在游戏中,某个时刻只有当前state在运行。因此,游戏将会在树上进行状态转换。比如我们刚刚进入游戏之后,会进入logo界面,然后转到trailer界面,接下来是主菜单,这几步都是不可逆的。然后玩家可以选择in-game(进入游戏)、credits(制作团队介绍)和settings(设置)这三个状态,并且可以从这三个状态返回主菜单状态。在in-game状态下可以进入pause menu(暂停菜单)并返回。


此外,我们有时候需要在一种状态下显示另一种状态。比如在pause menu中显示暂停选项的时候仍然显示游戏背景(用某种颜色的全屏幕半透明矩形覆盖使其暗化,并且游戏逻辑此时不会更新),如下图所示:



这意味着给state增加一个parent pointer会很方便:

    class GameState  
    {  
      
    // ...as above  
      
    public:  
        void setParent( GameState* state ) { m_parent = state; }  
        GameState* getParent() { return m_parent; }  
    private:  
        GameState*      m_parent;  
    };  

这样,我们可以这样实现pause menu的draw方法:

    void GameState_PauseMenu::draw( GraphicsContext& g )  
    {  
        m_parent->draw( g );  
        draw the transparent mask layer...  
        draw pause menu items...  
    }  

我们首先渲染parent,对于pause menu状态来说,它的parent就是in-game状态。然后渲染半透明覆盖层。最后渲染pause menu的选项。


此外,parent pointer对于状态的转换也是非常方便的。


为了能够方便地操纵游戏状态在状态树上进行转换,我们扩展manager类:

    class StateMgr  
    {  
      
    // ...as above  
      
    public:  
        enum StateOP  
        {  
            STATE_OP_PUSH = 0,  
            STATE_OP_POP,  
        };  
          
    public:  
        void changeState( GameState* newState, int op )  
        {  
            if( op == STATE_OP_PUSH )  
            {  
                newState->setParent( m_curState );  
                m_curState = newState;  
            }  
            else if( op == STATE_OP_POP )  
            {  
                m_curState = m_curParent->getParent();  
            }  
        }  
    };  


我们增加了state操作方法StateMgr::changeState并通过两个操作类型:push和pop,可以很方便地在状态树上移动,如下图所示:




Loading状态


以上设计有一个很大的问题,你能看出来吗?似乎所有的state同时存在,这将导致大量的资源存在于内存中。就算是当进入到main menu状态之后,我们再也无法返回trailer或者logo状态,它们的资源也还驻留在内存里。因此,我们需要把这些状态划分阶段(phase),只让当前一个phase内的所有state留在内存里。当游戏从一个phase转到另一个phase的时候,会释放旧phase资源,然后载入新phase资源。这通过一个叫做GameState_Loading的类来实现。在释放旧资源和载入新资源的过程中,GameState_Loading将接管局面,并显示载入进度界面。我们先把目前的状态树划分phase如下:



整个状态树被划分为4个phase:


logo(logo)

trailer(trailer)

main menu(main menu, credits, settings menu)

in-game(in-game, pause menu)


括号里面的就是该phase所包含的状态,会在一个loading过程中全部驻留内存。每一个phase实际上都形成一个子树,通过一个stack结构和上面的push、pop操作进行转换。我们扩展上面的类如下:

    class GameState  
    {  
    // ...as above  
      
    public:  
        int getStateOP() const { return m_stateOP; }  
        int getNextPhase() const { return m_phaseToLoad; }  
      
    protected:  
        int m_stateOP;  
        int m_phaseToLoad;  
      
    };  
      
    class GameState_Loading : public GameState  
    {  
    public:  
        enum Phase  
        {  
            PHASE_LOGO = 0,  
            PHASE_TRAILER,  
            PHASE_MAIN_MENU,  
            PHASE_INGAME,  
        };  
      
    public:  
        void setNextPhase( int phase ) { m_phaseToLoad = phase; }  
        GameState* getNextState() { return m_nextState; }  
      
        virtual void cycle()  
        {  
            free the old phase...  
            init the new phase frame by frame...  
            save the new states to StateMgr::m_states...  
      
            if( initialization is completed )  
            {  
                m_nextState = default state of the phase  
                m_stateOP = StateMgr::STATE_OP_NEW_STACK;  
            }  
        }  
      
        virtual void draw( GraphicsContext& g )  
        {  
            draw the progress interface...  
        }  
      
    private:  
        int m_phaseToLoad;  
        GameState* m_nextState;  
    };  
      
    class StateMgr  
    {  
      
    // ...as above  
      
    public:  
        enum StateOP  
        {  
            STATE_OP_NONE = -1,  
            STATE_OP_PUSH = 0,  
            STATE_OP_POP,  
            STATE_OP_LOAD,  
            STATE_OP_NEW_STACK,  
        };  
    public:  
        void cycle()  
        {  
            // ...as above  
      
            leaveFrame();  
        }  
      
    private:  
        void leaveFrame()  
        {  
            if( m_curState->getStateOP() != STATE_OP_NONE )  
            {  
                if( m_curState->getStateOP() == STATE_OP_LOAD )  
                {  
                    GameState_Loading* state = new GameState_Loading;  
                    state->setNextPhase( m_curState->getNextPhase() );  
                    m_curState  = state;  
                }  
                else if( m_curState->getStateOP() == STATE_OP_NEW_STACK )  
                {  
                    GameState_Loading* state = static_cast< GameState_Loading*>( m_curState );  
                    changeState( state->getNextState(), STATE_OP_PUSH );  
                    delete state;  
                }  
            }  
        }  
    };  


GameState_Loading类处理所有的状态转换工作,这当然包括旧资源释放和新资源初始化,同时绘制loading界面。


StateMgr新增了两个操作方式。StateMgr::STATE_OP_LOAD就是开始建立一个新的phase,也就是从旧phase进入loading状态,然后进行资源载入和新phase中各个state的建立等工作,这些工作在GameState_Loading::cycle中逐帧完成。StateMgr::STATE_OP_NEW_STACK表示从当前loading状态进入到新建立的phase的默认state中。


StateMgr::cycle方法中新增加调用一个新加入的方法StateMgr::leaveFrame。该方法用于在离开当前帧的时候做一些事情。在这里我们主要处理state转换。


GameState增加了两个成员,m_stateOP用于告诉StateMgr是否需要转换到另一个phase,默认值是StateMgr::STATE_OP_NONE——什么也不做。m_phaseToLoad告诉StateMgr它要转换到哪一个phase。这些phase都定义在GameState_Loading中。比如在logo状态中需要转换到trailer状态,我们可以在GameState_Logo::cycle中写:


m_stateOP = StateMgr::STATE_OP_LOAD;

m_phaseToLoad = GameState_Loading::PHASE_TRAILER;


StateMgr::leaveFrame就会建立一个loading状态来进行状态转换。当GameState_Loading::cycle完成了初始化,它就会通过StateMgr::STATE_OP_NEW_STACK让流程进入新的phase的默认state中,正如上面代码所示。


(我在程序中使用了一些伪码来避免陷入过多细节,目的是更好的表达出这个结构的思路。如果你非常需要了解该系统的具体实现,可以和我联系)




改进方向


好了!我们已经完成了该系统的基本框架。读者完全可以根据该框架实现一个自己的游戏状态机,并取得良好的运行效果。但我还是要说,这和真正游戏中使用的工程级别代码比,还差一些!下面我会指出一些设计上的改进和扩展,让该系统更容易在游戏产品中使用。感兴趣的读者可以自行实现。


1 给GameState加上自定义“构造函数”和“析构函数”


如果能给state增加方法:


GameState::onActive

GameState::onUnactive


会让很多事情事半功倍,且可以得到良好的结构和健壮性。 在StateMgr::changeState中进行state转换(push和pop)的时候, 给即将停止的state调用onUnactive,给即将运行的state调用onActive,可以给这些state一个机会做一些构造和析构工作(比如释放和申请一些小资源,或重新初始化一些数据等等)。我们的代码就强烈地依赖这些方便的小方法。


2 增加state之间的界面过渡


很多游戏在界面过渡之间都使用了一些特效,最常见的就是淡入淡出效果。令人兴奋的是,通过上面的状态机系统增加这样的过渡效果非常方便。比如我们自己设计了一个叫做FullScreenEffect的基类,通过设计不同的子类来完成不同的过渡效果。


提示:在StateMgr里面合成该类的一个实例,然后在StateMgr::cycle和StateMgr::draw中调用FullScreenEffect::cycle和FullScreenEffect::draw方法,并通过一些标志来禁止和启动StateMgr::m_curState的更新和渲染。


3 通过事件分发系统进行状态改变通知


通过我们之前介绍的事件分发系统(http://blog.youkuaiyun.com/popy007/article/details/8242787)来通知系统进行state转换是个很不错的设计思路!


4 把StateMgr写成一个singleton


StateMgr应该只有一个且可以被方便地访问,写成一个singleton吧!(关于singleton模式,可以参考GoF的著作)


5 给loading状态增加一个资源载入管理器


在loading状态中,我们有时候需要画出当前的进度比例,这个比例如何计算出呢?很多游戏用的是假数据——只体现一个递增的效果。但还有些用的是真实数据,对于真实数据来说,该机制和你游戏的资源管理系统有很大关系,这里我提供一个简单思路。


我们将需要载入或申请的所有资源进行分类,比如:


字符串

纹理

关卡数据

逻辑脚本

缓存

自定义回调函数

...


给这些资源定义一个通用的结构,并用一个ID来区分。然后这些资源就有了一个统一的表示结构,比如


struct Res;


然后建立一个(你喜欢的任何容器都可以)


std::list< Res >


把所有要载入的资源全部放到这个list中,之后list.size()就是你要载入的所有资源数。在loading状态里面,每帧只处理一个Res。处理完毕后,就从这个list中把该Res删除。在这个过程中,你就可以知道当前的载入进度了。这个方法的好处在于避免了资源加载过程中多线程的使用。


总结


以上我们设计并实现了一个基本的游戏状态机系统——它很清晰、简洁,并有很强的扩展性。它基于state模式,提供了易于维护的系统结构。当然,该系统还有很大的提升空间,这完全取决于开发者的积累。

该系统已经在多个实际项目中使用,并获得了不错的效果。希望开发者能够从中得到设计灵感。

原文地址:http://blog.youkuaiyun.com/popy007/article/details/8287444

Unity2D - 状态机(State Machine)详解 在角色的生成中,由于事件的不同,动作的不同,角色会处于不同的状态中,例如对战冒险游戏,面临Boss的攻击,角色会受到例如中毒,恐惧等Debuff效果,若单纯的在一个脚本中使用if等语句进行事件处理,往往会比较冗杂,程序出现bug后也无法及时排查出问题。定义状态机作用类似于一个机器,将player的各个状态进行调配,例如类中的方法初始化状态,以及改变当前状态。 阅读详情

相关推荐

游戏状态机的设计与实现

状态机的模型是非常简单,但并不是每个人都能设计好的状态机。因为好的状态机不仅需要对程序的把握要比较到位,同时需要对整个业务的理解比较到位。好的状态机使程序变的更加简洁,易扩展,容易查找bug,还非常稳定。坏得状态分割只会让程序晦涩难懂。

武龙飞的空中楼阁 9494

状态模式:游戏、工作流引擎中常用的状态机是如何实现的?

有限状态机,英文翻译是Finite State Machine,缩写为FSM,简称为状态机。状态机有3个组成部分:状态(State)、事件(Event)、动作(Action)。其中,事件也称为转移条件(Transition Condition)。事件触发状态的转移及动作的执行。不过,动作不是必须的,也可能只转移状态,不执行任何动作。马里奥形态的转变就是一个状态机。其中,马里奥的不同形态就是状态机中的“状态”,游戏情节(比如吃了蘑菇)就是状态机中的“事件”,加减积分就是状态机中的“动作”。

abc123mma的博客 3395

分层状态机学习

转载:原创作者 参考:参考作者 日志: 21.8.24:组内同事分享了一个多状态的项目,其中用到了分层状态机的概念,蛮有兴趣的,前来学习一下 决策方法: 有限状态机(Finite-State Machines) 分层状态机(Hierarchical Finite-State Machines) 行为树(Behavior Trees) 效用系统(Utility Systems) 目标导向型行动计划(Goal-Oriented Action Planners) 分层任务网络(Hierarchical Task

欢迎访问方偲的博客 2484

[游戏架构] 有限状态机的实际应用

有限状态机(Finite State Machine,简称FSM)是一种常用的计算机科学中的建模工具,用于描述由离散状态和状态之间的转换组成的系统。它主要由一个有限的状态集合、一个初始状态、一个输入事件集合、状态之间的转换以及与每个状态相关联的输出动作组成。

hhh314159的博客 1619

谈一谈游戏AI -状态机

郑重说明:本文适合对游戏开发感兴趣的小白初学者,本人力图将事物用简单的语言表达清楚,但水平有限,能力一般,文章如有错漏之处,还望批评指正。

afriedegg的博客 745

Python Pygame 游戏开发中的状态机设计

在游戏开发中,一个游戏往往包含多个不同的场景和状态,例如主菜单、游戏关卡、暂停界面、游戏结束界面等。状态机设计的目的就是为了有效地管理这些不同的状态,使得游戏的逻辑更加清晰、易于维护和扩展。本文的范围主要聚焦于如何在 Python Pygame 这个游戏开发库中实现和应用状态机设计,涵盖了从基本概念到实际项目应用的各个方面。本文将按照以下结构进行组织:首先介绍状态机的核心概念和联系,包括其原理和架构;接着详细讲解核心算法原理和具体操作步骤,并通过 Python 代码进行说明;

AI Python 编程之道的博客 1236

HarmonyOS 游戏运行态的完整状态机图

本文系统阐述了HarmonyOS游戏开发中的运行状态机模型。作者指出传统"Init→Running→Pause→Exit"的心智模型在HarmonyOS上存在不足,提出包含6个关键状态(Created、Ready、Running、Suspended、Frozen、Destroyed)的完整状态机,详细解析了每个状态的职责边界和转换条件。文章强调状态机作为"安全网"的重要性,能有效解决前后台切换、资源管理、进程回收等场景下的稳定性问题,并提供了状态映射关系和代码实现示例

qq_36863796的博客 2万+

状态图在游戏开发中的应用:角色AI状态机实现

核心挑战状态机解决方案具体优势行为一致性明确定义的状态转换规则确保角色行为符合设计意图,避免"精神分裂"式行为情境适应性条件驱动的状态转换使角色能根据游戏世界状态调整行为资源限制轻量级状态管理在有限CPU周期内实现复杂行为开发效率模块化状态设计支持并行开发和测试,简化迭代调试难度可预测的状态路径提供清晰的行为追踪和错误定位设计迭代松耦合的状态组件允许设计师调整行为而不破坏核心逻辑游戏AI与传统AI的关键区别在于:游戏AI通常是"看起来智能"而非"真正智能"。

软件工程实践的博客 897

FPS射击游戏状态机验证技术探秘

FPS射击游戏GamePlay开发中,状态机验证机制是核心技术难点。文章分析了并行分层状态机设计、状态步长验证和武器状态帧序列化回退三大挑战,涉及状态同步、网络异常处理和性能优化等问题。典型方案包括拆解独立状态机、帧级状态校验和局部回退机制。伪代码展示了客户端-服务器同步流程,并提出了优化输入同步、平滑回退等建议。该机制能有效保障游戏一致性,但需持续优化扩展性和性能表现。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 1101

C++实现有限状态机游戏编程项目

有限状态机(FSM)是计算机科学中一种抽象的数学模型,用于设计和分析具有有限个状态的系统。在游戏开发中,FSM扮演着至关重要的角色,它使得角色和游戏世界的行为表现得更加丰富和复杂。本章节通过深入探讨”Mao”类的设计原理和核心行为方法,为实现一个基于状态机的游戏实体奠定了基础。”Mao”类通过其内部状态机精确地控制游戏逻辑的动态变化,不仅展现了状态机与类设计之间的紧密关系,而且展示了如何通过面向对象的方法来封装和管理复杂的游戏行为。

weixin_31974443的博客 1044

SpringBoot状态机

Spring Boot 状态机(State Machine)是 Spring Framework 提供的一种用于实现复杂业务逻辑的状态管理工具。它基于有限状态机(Finite State Machine, FSM)的概念,允许开发者定义一组状态、事件以及它们之间的转换规则。这在处理具有多个步骤或条件的工作流时特别有用。

编码浪子的专栏 2589

【模式】状态机(有限状态机、并发状态机、层次状态机)

2. 可以知道状态from-to,知道是从哪个状态向哪个状态进行切换,可以进行一些前置操作,例如在游戏暂停时重新开始游戏,可以在切换前重置游戏数据。使用状态机,可以避免使用if-else/switch-case进行逻辑的条件判断,导致代码臃肿,难以维护,扩展性差。游戏状态:初始化、开始、暂停、恢复、下一波敌人、3选1技能、失败、胜利、退出游戏等。但是角色的状态,行走、攻击、跳跃等是可以并行的,例如行走并攻击,跳跃并攻击。游戏流程的状态是单一的,从初始化,开始,结束等状态都只会同时存在一个。

gamedaybyday2的博客 1469

lisp方格网法计算土方量_分享:两期土方工程量计算(方格网法)实例例题

最近遇到一个飞时达土方软件试用版客户,咨询怎么根据平整前的原始地形图和平整后的现状地形图来计算产生的土方工程量,也就是两期土方量,且需要用方格网法来计算,作为一个老道的工程设计人员,博主对这类的项目实例例题简直太熟悉了,用飞时达土方计算软件V13.0可以很方便的计算出来。 方格网法计算两期土方量流程 一、软件安装及注册 专业的飞时达土方计算软件FastTFT,请到飞时达软件官方网站去下载,注册完...

weixin_35131425的博客 1698

FSM(状态机)、HFSM(分层状态机)、BT(行为树)的区别

游戏人工智能AI中最常听见的就是这三个词拉: FSM 这个不用说拉,百度一大堆解释, 简单将就是将游戏AI行为分为一个一个的状态,状态与状态之间的过渡通过事件的触发来形成。 比如士兵的行为有“巡逻”,“追击敌人”,“攻击敌人”,“逃跑”等行为, 响应的事件就有“发现敌人”,“追到敌人”,“敌人逃跑”,“敌人死亡”,“自己血量不足”等。 那么可以写成这样一个状态机: 1.士兵 “巡逻”,如果 “发现...

昔拉的博客 1万+

信息化建设项目前期方案编制4:如何画好四张图

这里探讨以下具体的总体设计操作层面的工作。总体设计主要是完成四张图,总体架构(逻辑架构)、应用架构、网络拓扑、系统部署图。对于一些单一的系统,往往总体架构和应用架构可以合一。网络拓扑画好了,系统部署图也可以省略。有些项目还会在这之外,有所谓的技术架构图。对应用系统、数据存储等各个部分各自用的主要技术、服务等,给出总体设计图。但通常来说,这四张图在一个中等规模(200~500万,软件...

Leonardo的博客 4636

DRAM知识整理系列(三):部分时序参数整理

一、tCL-tRCD-tRP-tRAS(第一时序) 内存是根据行和列寻址的,当请求触发后,最初是tRAS(Active to precharge Delay),预充电后,内存才真正开始初始化RAS(Row Address Strobe)。一旦tRAS激活后,RAS开始进行需要数据的寻址。首先是行地址,然后初始化tRCD(RAS to CAS Delay),周期结束,接着通过CAS(Column Address Strobe)访问所需数据的十六进制地址。其中,从CAS开始到CAS结束,就是CAS延迟(即t

不吃鱼的猫的博客 7万+

游戏算法-游戏AI状态机,python实现

python实现AI状态机算法、例子

巴山夜雨 1367

【Audio】基于STM32 I2S移植WM8978 Audio Codec驱动

1. WM8978简介 WM8978是一款低功耗,高质量的立体声编解码器,专为便携式应用,如数码相机或数码摄像机等。 该芯片集成了立体声差分麦克风的前置放大器,并包括扬声器、耳机和差分或立体声线输出的驱动器。外部组件要求减少,因为不需要单独的麦克风或耳机放大器。 WM8978的功能框图如下所示: 2. WM8978硬件连接 使用STM32F429+WM8978硬件平台,通过I2S接口来读写音频数据,I2C接口发送写命令控制WM8978相关功能。 STM32F429与WM8978的引脚连接如下:

ZHONGCAI0901的博客 1万+

在游戏中看状态机与状态模式

状态机与状态模式 状态机 最早接触状态机这个词来自编译原理的学习,在词法分析中,通过有限状态机来进行单词识别。状态机在里面被定义为一个数学模型,一个五元组。 截图来自维基百科 对于Android开发者,可能最为熟知的就是MediaPlayer的状态机图了 状态机一般有四个要素 现态:状态机当前所处的状态 条件:触发动作或者状态迁移的条件(在按键系统中,就是指按键的值) 动作:条件满足后执行的动作(也就是响应各个任务,在代码中往往一个动作对应一个方法) 次态:动作完成后要迁移的下个状态 上图中蓝色圆圈

skateboard1的专栏 560

激光雷达-IMU标定工具lidar_imu_calib保姆级教程(VLP-16实测)

本文提供激光雷达与IMU联合标定的详细实战教程,重点解析lidar_imu_calib工具在VLP-16上的应用。从环境部署、数据采集技巧到参数配置与结果验证,手把手指导完成标定全流程,并详解如何在LIO-SAM等SLAM系统中应用标定结果,确保传感器融合精度。

food6的博客 475

【机器学习-17】数据变换---小波变换特征提取及应用案列介绍

小波变换作为一种前沿的数据分析工具,近年来在信号分析领域崭露头角。小波分析的理论和方法凭借其独特优势,在信号处理、图像处理、语音处理、模式识别以及量子物理等多个领域得到了广泛的应用,堪称近年来在工具及方法上的重大突破。小波变换以其多分辨率的特性,在时域和频域均展现出对信号局部特征的强大表征能力。通过伸缩和平移等运算过程,小波变换能够对信号进行多尺度聚焦分析,为非平稳信号的时频分析提供了一种有效手段。它允许我们由粗及细地逐步观察信号,从而精准地提取出有用信息。

qq_38614074的博客 2万+

从有限状态机到无限可能:状态机思想在复杂系统设计中的哲学启示

本文探讨状态机思想如何从有限状态机演化为复杂系统设计的哲学工具,涵盖其在游戏AI、工作流引擎和分布式系统中的应用。通过状态机模型,开发者能够将混沌业务流程分解为清晰的状态转移规则,提升系统可维护性和可靠性,为51单片机等嵌入式系统到现代软件架构提供统一方法论。

x1y2z的博客 903

《多模态融合改进》支持目标检测、目标分割、OBB、姿态估计,配置教程

本文以为例,讲解如何配置,支持替换专栏里所有的改进方式。

Limiiiing的博客 795

【友晶科技】基于FPGA的贪吃蛇游戏设计(八)——状态机设计

写法就是有三个always 块,一个时序逻辑采用同步时序的方式描述状态转移,一个采用组合逻辑的方式判断状态转移条件、描述状态转移规律,第三个模块使用同步时序的方式描述每个状态的输出。三段式代码容易维护,时序逻辑的输出解决了两段式组合逻辑的毛刺问题,但是从资源消耗的角度上看,三段式的资源消耗多一些。Verilog语言可以依靠不同的always语句块实现硬件电路的并行执行,但在实际工程中,不仅需要并行执行电路,偶尔也会遇到需要串行执行的电路。在当前状态下,根据当前的输入转换为下一状态的组合逻辑。

weixin_47841246的博客 2691

【QNX+Android虚拟化方案】125 - 如何创建android-spare镜像

【QNX+Android虚拟化方案】125 - 如何创建android-spare镜像

|~~~热爱生活、努力学习的小伙汁~~~| 1092

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

上一篇: 一个基于组合模式的游戏地图系统
下一篇: 一个C++多继承带来的游戏开发陷阱
cbbbc
博客等级 码龄15年 609粉丝 37原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值