【译】一个基于Ogre和ODE的3D RPG

发表于2016-03-10
评论0 2.9k浏览

原文地址:http://www.codeproject.com/Articles/479054/A-D-RPG-Based-on-Ogre-and-ODE

版权:作者版权声明为http://www.codeproject.com/info/cpol10.aspx,可以翻译


简介

  在这篇文章里,我介绍一个用Ogre图形引擎、ODE物理引擎和CEGUI等开发的3DRPG。框架和源代码资源在这里https://github.com/lxdfigo/Space-Knight


背景

  太空骑士是一个我孩子时期看的动画片,我还是一个游戏粉丝。所以我用我学到的知识把这个卡通开发成了RPG。这里是我用在游戏里面的Lib:

· Ogre : 我用它作为图形引擎。它可以选择DirectX或是OpenGL来绘制屏幕。

· OED:我用它和Ogre一起来构建游戏的物理世界。

· CEGUI:它用来做游戏的主菜单、交易菜单和功能菜单。

· 3D Max:游戏中的模型是在3DMax里面做的然后通过插件导出

· DirectShow and Fmod: 它们用来播放音频和视频


使用代码

  下面是游戏框架的UML图。



  游戏有几个模块,分别是任务、角色、AIUI、工具和媒体模块。

  任务模块控制着游戏的任务并且它有BaseMission FirstMission 等类。每一个类代表游戏的一个任务。基类控制着主要模块。

  角色模块控制着游戏的角色比如主玩家、太空骑士、怪物LadaNPC等等。他们是由entitymanager管理的并会在每一帧检测是否发生碰撞。角色模块也受到AI模块的控制;

  AI模块使用状态机来模拟角色的人工智能。每个有AI的角色拥有人工智能有其自己的状态类和行为。它可以很容易地改变和扩展。

  UI模块使用CEGUI显示游戏的UI。它接收来自用户的输入,把消息传递其他模块。它使用OIS接收键盘消息和鼠标消息。每个被CEGUI绘制在屏幕上的菜单都是一个脚本文件。

  媒体模块就是FmodDirectShow的一个简单适配器。播放战斗和背景的声音和开场动画。



  任务的基类包含一大堆成员和函数。它使用了UI模块来展示菜单,媒体模块来播放声音,角色模块来更新实体。它还构建了图形世界和物理世界。它还有函数来跳到下一个任务,加载保存的任务或者结束游戏。

  状态机有3个主要状态:过去态、现在态和全局态。每个状态有4个行为EnterExitExecute OnMessage。如果一个角色收到一条消息,会让状态机的当前状态执行并且转到下一个状态去。

//

//Here is the Base Mission class

//

class BaseMission:         

    public OgreOde::CollisionListener, 

    public OgreOde::StepListener, 

    public OgreOde::TriangleMeshRayListener

{

public:

        ....

    OgreOde::World                       *mWorld;

    OgreOde::Space                       *mSpace;

    OgreOde::StepHandler                 *mStepper;

    OgreOde::TriangleMeshGeometry* terrainTriMeshGeom;

    OgreOde::InfinitePlaneGeometry *mGround; 

    GameFrame *gameFrame;

    Ogre::Root*              mRoot;

    Ogre::Camera*          mCamera;

    Ogre::SceneManager*      mSceneMgr;

    Ogre::RenderWindow*      mWindow;

    CEGUI::System*   mGUISystem;

    FrameListener* mFrameListener;

    BaseMissionListener* mMissionListener;

    GuiListener *mGuiListener;

    Overlay *talkOverlay,*gameOverlay,*blackOverlay,*loadingOverlay,*missionIntruOverlay;

    CEGUI::Window* gameSheet,* opSheet,* quitSheet,

        * gameOverSheet,* loadSheet,* intruduceSheet,

        * useButton,*noUseButton,* currentPackage;

    std::vector animationStates;

    std::vector mModels;

    std::vector mGeoms;

    std::vector nodes;

    std::vector staticThings;

    std::vector monsters;

    Role *mainModel;

    BaseSound *mSound    

    SceneNode * _rocket_node_explosion;

    ParticleSystem * _rocketParticles_explosion;

public :

    BaseMission(Ogre::RenderWindow* mW, Ogre::Root* mR, Ogre::Camera* mC, 

                 Ogre::SceneManager* mS,CEGUI::System*   mG,GameFrame *);

    virtual void Render();

    virtual void Clean();

    virtual void InitObjects();

    virtual void createFrameListener();

    virtual void NextMission();

    virtual void upDate();

    virtual void createScene();

    virtual void UpdateGUI(void);

    virtual void initDemoEventWiring(void);

        ...

    Ogre::SceneManager* getSceneManager(void) const { return mSceneMgr; }

    Ogre::RenderWindow* getRenderWindow(void) const { return mWindow; }

    void resetParticleSystem(Ogre::ParticleSystem *ps, bool enable, const Ogre::Real delay);

    virtual void GameOver();

    void LoadGame(int i);

};

//

// Here is part of the state machine of the AI in the game.

//

template

class StateMachine

{

private:

    entity_type *m_pOwner;

    State *m_pCurrentState;

    State *m_pPreviousState;

    State *m_pGlobalState;

public:

    StateMachine(entity_type *owner):m_pOwner(owner),

       m_pCurrentState(NULL),m_pPreviousState(NULL),m_pGlobalState(NULL){}

    void SetCurrentState(State *s){m_pCurrentState = s;}

    void SetPreviousState(State *s){m_pPreviousState = s;}

    void SetGlobalState(State *s){m_pGlobalState = s;}

...

};

template

class State

{

public:

    virtual bool OnMessage(entity_type *,Telegram &msg) = 0;

    virtual void Enter(entity_type *) = 0;

    virtual void Exit(entity_type *) = 0;

    virtual void Execute(entity_type *) = 0;

    virtual ~State(){}

};


操作和结果

游戏操作:

l  移动:W, A, S, D

l  开火: 鼠标, Z, C, V

l  任务通关: Y

l  菜单: F1 

游戏一共有7个任务,2boss任务还有一个运送任务。下面是一些游戏的截图。


游戏的主菜单


玩家击败了一个怪兽



如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引