关闭

游戏状态管理之C++实现

标签: 游戏c++引擎vectormakefileclass
6282人阅读 评论(1) 收藏 举报
分类:

游戏状态管理之C++实现

Managing Game States in C++

 

文章来源:TonyandPaige.com

翻译: Mythma

 

多年前看的一个demo使我第一次完全明白了游戏中的不同状态。这个demo能够从一个特效平滑的过渡到另一个特效,并能从2D漩涡效果直接过渡到3D渲染环境,就像是几个不同的程序写成的。

 

多状态不仅在demo中重要,在游戏中也同样重要。每个游戏程序基本上都是从介绍开始,显示菜单,然后进行游戏。当被击败时,游戏就结束了(通常返回到菜单界面)。大多数游戏中,很可能会同时出现多个状态——比如游戏过程中弹出菜单。

 

传统的处理多状态的方式是使用一大堆的ifswitch loop语句。程序从介绍状态开始一直循环,直到按下一个键;然后菜单就显示了,直到完成了选择操作;游戏开始了,就一直循环,直到游戏结束。每一次游戏循环,程序还得检查是应该显示菜单还是简单的绘制下一帧。而且,处理事件的那部分程序还必须判断输入究竟是菜单来相应还是游戏来相应。所有的这些组合起来就形成了一个主循环,可以发现这个大杂烩很难理解,并且调试和维护起来也不方便。

 

状态是什么呢?(What’s a state?)

 

游戏状态就像是游戏的一个单独的程序。每个状态需要以不同的方式处理事件,需要在屏幕上绘制不同的内容。每个状态还需要处理它自己的事件、更新游戏场景、绘制下一帧等等。因此,我们可以确定状态应该至少拥有三个方法。

 

状态又应该能够加载图形、自初始化、释放资源。并且有时状态还需要暂停,还要能够恢复。

 

到此为止,状态类就应该看起来如下所示:

class CGameState
{
public:
  void Init();
  void Cleanup();

 

  void Pause();
  void Resume();

 

  void HandleEvents();
  void Update();
  void Draw();
};

 

上面的状态类设计应该能够满足游戏的状态需求。把它当作基类,从它可以派生出游戏所需要的每一种状态——介绍状态(intro state)、菜单状态(menu state)、游戏状态(play state)等等。

 

状态管理器(The State Manager

 

接下来,我们需要一个管理状态的方法——状态管理器。状态管理器是游戏引擎本身的一部分。别人可能会选择创建一个单独的状态管理类,而我只是把它直接加到引擎中。我们先来看看一个游戏引擎能做什么,然后再设计一个类来完成这些功能。

 

我们的这个例子很简单,整个引擎需要做到是初始化SDL和完成后的清理工作。由于在主循环需要用到这个引擎,因此需要检查引擎是否仍然在运行、是否退出,以及处理事件、更新游戏、绘制帧序列。

 

状态管理器实际上很简单。我们用 “状态栈”来管理各种不同的游戏状态。在此用STLvector来实现状态栈。除此之外,还需要改变状态的方法,以及入栈和出栈方法。

 

至此,游戏引擎类就如下所示:

class CGameEngine
{
public:

 

  void Init();
  void Cleanup();

 

  void ChangeState(CGameState* state);
  void PushState(CGameState* state);
  void PopState();

 

  void HandleEvents();
  void Update();
  void Draw();

 

  bool Running() { return m_running; }
  void Quit() { m_running = false; }

 

private:
  // the stack of states
  vector<CGameState*> states;

 

  bool m_running;
};

 

这些成员函数中有几个非常简单的——HandleEvents(), Update() Draw()。它们只需简单的调用栈顶状态对象相应的成员函数即可。由于需要经常访问游戏引擎中的数据,因此需要在以上三个成员函数中加一个指向引擎指针的参数。

 

最后需要考虑的是状态之间的切换。引擎如何知道状态何时切换到另一个状态?答案是:它不知道。只有当前的状态知道什么时候转向下一个状态。于是,我们又需要为状态类加一个改变状态的成员函数。

 

对于状态类时,我们把它设计为一个抽象基类——它的大部分成员函数设计为纯虚函数。这就保证了它的子类都必须得实现这些方法。经过这些更改后,最后的游戏状态类如下所示:

class CGameState
{
public:
  virtual void Init() = 0;
  virtual void Cleanup() = 0;

 

  virtual void Pause() = 0;
  virtual void Resume() = 0;

 

  virtual void HandleEvents(CGameEngine* game) = 0;
  virtual void Update(CGameEngine* game) = 0;
  virtual void Draw(CGameEngine* game) = 0;

 

  void ChangeState(CGameEngine* game, 
                   CGameState* state) {
    game->ChangeState(state);
  }

 

protected:
  CGameState() { }
};

 

现在要为游戏增加状态就非常简单了,只需从基类继承一个子类,实现那几个纯虚函数就可以了。对于某种状态,在游戏中只需一个实例,因此把它们设计成Singleton模式是个不错的选择。

 

这种方法究竟能够把游戏简化到什么程度,如下所示的main.cpp中包含的所有代码可以说明:

int main ( int argc, char *argv[] )
{
  CGameEngine game;

 

  // initialize the engine
  game.Init( "Engine Test v1.0" );

 

  // load the intro
  game.ChangeState( CIntroState::Instance() );

 

  // main loop
  while ( game.Running() )
  {
    game.HandleEvents();
    game.Update();
    game.Draw();
  }

 

  // cleanup the engine
  game.Cleanup();

 

  return 0;
}

 

下载(Downloads

 

这个例子里包含了三个不同的状态——introduction stateplaying statepauses state。每种状态都用一幅背景图片来表示。

·              stateman.zip - Tutorial Source, Graphics, and Project files for Visual C++ 6.

·              stateman.tar.gz - Tutorial Source, Graphics, and Makefile for Linux.

这个例子的代码用的是SDL。如果你不熟悉,可以看一下这篇文章:Getting Started with SDL

0
0
查看评论

C++游戏系列6:自己动起来

知识点:(1)对象数组,自动生成了很多个“玩家”(角色类的对象),自动玩;(2)使用文件:武器要从文件中读,玩的过程,写入到了文件。【项目-让玩家自己动起来】 (与前几个版本相比,主要变化在main.cpp中) 1.game.h:类声明#ifndef GAME_H_INCLUDED #defin...
  • sxhelijian
  • sxhelijian
  • 2016-04-13 22:54
  • 4365

DirectDraw里自定义控件的开发(Demo和源代码)

先放上Demo和源代码,有时间再放上完整教程下载地址:http://www.successheartpower.com/fish/SourceCode/CustomControl_Source.rar
  • kittyfish
  • kittyfish
  • 2005-01-25 09:43
  • 1180

中原之霸者游戏源码(stl,directdraw)

  • 2010-07-09 22:19
  • 452KB
  • 下载

用C++实现跨平台游戏引擎开发

你是否梦想写一部格斗游戏但却无从着手呢?是否你只因游戏开发好玩而对之感兴趣?本文我们将分析一个通用的跨平台游戏引擎,每个游戏开发新手都可以自由地使用它。  1. 3D游戏引擎的简短历史  在游戏开发中,从一开始就确定正确的开发平台是很重要的。是否你的游戏支持Windows,Linux和OS X?是否...
  • pizi0475
  • pizi0475
  • 2010-05-19 22:45
  • 987

Gamebryo2.3

  • 2009-07-24 20:15
  • 1.53MB
  • 下载

Visual C++网络游戏建模与实现pdf+源码

  • 2011-02-21 15:01
  • 11.26MB
  • 下载

值得学习的C/C++语言开源项目,以及好多资源整理

值得学习的C/C++语言开源项目 (1)ACE 庞大、复杂,适合大型项目。开源、免费,不依赖第三方库,支持跨平台。 http://www.cs.wustl.edu/~schmidt/ACE.html (2)Asio Asio基于Boost开发的异步IO库,封...
  • KiTok
  • KiTok
  • 2017-12-21 15:47
  • 956

用C++实现的扑克二十一点游戏源代码

2006年08月03日 星期四 23:20 //程序作者:魏洪源//版权所有,转载请联系:why2942@163.com#include#include#includeusing namespace std...
  • NelsonHongHexin
  • NelsonHongHexin
  • 2006-12-11 16:14
  • 6133

用C++语言写游戏——打飞机

想玩游戏吗? 就到某位神犇这来吧! 这会告诉你很多游戏写法! 今天,神犇就开始书写第三期——打飞机!!! 很容易,只需要用脑袋想想即可,READY——GO! 我也希望大家多多捧场哦~~~
  • cnyali_ljf
  • cnyali_ljf
  • 2016-05-07 22:03
  • 19997

【贪吃蛇,C++实现】,由简单游戏开始学习OOP,的编程新手

{我又来写黑历史了}.... 以前学习C语言的时候,老是感觉只能做点数学题什么的(事实程序就是由许多道数学题构成)。 然后最近两个月开始学习C++,接触到OOP,然后感觉视界扩大了(误)特别是最近突然发现好像可以写些小游戏了(大误)。 前天埋头几个小时写了个贪吃蛇,而且成功运行了,但是回头看看...
  • lu3664198
  • lu3664198
  • 2015-05-07 16:07
  • 2332
    个人资料
    • 访问:537146次
    • 积分:7138
    • 等级:
    • 排名:第3785名
    • 原创:173篇
    • 转载:4篇
    • 译文:2篇
    • 评论:187条
    最新评论