高层游戏引擎——基于OGRE所实现的高层游戏引擎框架(7)

本文介绍了游戏引擎框架的设计与实现过程,探讨了如何结合游戏逻辑与底层工具,通过使用设计模式确保框架的安全性,并分析了该框架在不同类型游戏开发中的局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第四部分 结论和展望  通过对游戏世界的演绎,对游戏逻辑的归纳,以及对游戏底层工具的融合,逐步诞生了我们现在的框架。为了使框架更能经得起检验,我们使用了一些设计模式提供的方法来保证框架的安全性。现在的高层游戏引擎说明了一点,对于这个游戏,我们的框架达标了。但用这个框架开发一个新的游戏是否也会达标?答案是否定的。如果用这个框架去开发一个RPG游戏,那我们还缺技能、道具等诸多系统;如果去开发一个纸牌游戏,似乎我们的框架对于规则支持还不是太方便;如果去开发一个足球游戏,似乎我们的框架对AI的支持太差劲……而且就OGRE本身也在不断更新、提供新的功能,甚至有时候否定原有的类和接口。不过把话说回来,现在什么游戏引擎没有这种问题呢?写底层引擎容易,但是写一个通用的高层引擎层却很复杂,因为底层引擎只是跟变化缓慢的平台技术相关,但高层引擎层却是跟丰富多彩的游戏相关的。不仅如此,高层引擎的存在同时受底层引擎的功能限制。   需要走的路还很长,即便是对于国际知名的大公司,也是在不断的探索和实践中。但这并不表明前途就是渺茫的,我们通过这次实践作出了一次从底而上和自上而下的归纳和演绎的过程,在变化多端的具体游戏和变化缓慢的引擎中间寻找到了一个引擎层契合点。内容繁复、采用的表现手段多姿多彩的游戏世界,即便是再复杂,也可以通过一定程度的归纳演绎得出适应其规则和表现的契合点和高层引擎层架构。  

附录

Terrain Example /* -----------------------------------------------------------------------------

This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright ?2000-2003 The OGRE Team Also see acknowledgements in Readme.html You may use this sample code for anything you like, it is not covered by the LGPL like the rest of the engine.

----------------------------------------------------------------------------- */

 /** /file Terrain.h /brief Specialisation of OGRE's framework application to show the terrain rendering plugin */

#include "ExampleApplication.h"

#include "OgreStringConverter.h"

#define FLOW_SPEED 0.2

#define FLOW_HEIGHT 0.8

class TerrainListener : public ExampleFrameListener { public: TerrainListener(RenderWindow* win, Camera* cam) :ExampleFrameListener(win, cam) { };

// Override frameStarted event to process that (don't care about frameEnded)

bool frameStarted(const FrameEvent& evt)

{ float moveScale; float rotScale;

float waterFlow; static float flowAmount = 0.0f;

static bool flowUp = true;

// local just to stop toggles flipping too fast

static Real timeUntilNextToggle = 0;

 if (timeUntilNextToggle >= 0)

timeUntilNextToggle -= evt.timeSinceLastFrame;

// If this is the first frame, pick a speed

if (evt.timeSinceLastFrame == 0)

{ moveScale = 1; rotScale = 0.1; waterFlow = 0.0f; }

// Otherwise scale movement units by time passed since last frame

else

  {

   // Move about 100 units per second,

moveScale = 10.0 * evt.timeSinceLastFrame;

// Take about 10 seconds for full rotation

rotScale = 36 * evt.timeSinceLastFrame;

 // set a nice waterflow rate

waterFlow = FLOW_SPEED * evt.timeSinceLastFrame;

  }

// Grab input device state

mInputDevice->capture();

SceneNode *waterNode =

static_cast( mCamera->getSceneManager()->getRootSceneNode()->getChild("WaterNode"));

if(waterNode) { if(flowUp)

flowAmount += waterFlow;

else

flowAmount -= waterFlow;

if(flowAmount >= FLOW_HEIGHT)

flowUp = false;

else if(flowAmount <= 0.0f)

flowUp = true;

waterNode->translate(0, (flowUp ? waterFlow : -waterFlow), 0); }

static Vector3 vec; vec = Vector3::ZERO;

 if (mInputDevice->isKeyDown(KC_A))

 { // Move camera left vec.x = -moveScale; }

if (mInputDevice->isKeyDown(KC_D))

{

// Move camera RIGHT

vec.x = moveScale;

}

if (mInputDevice->isKeyDown(KC_UP) || mInputDevice->isKeyDown(KC_W))

{

// Move camera forward

vec.z = -moveScale;

}

if (mInputDevice->isKeyDown(KC_DOWN) || mInputDevice->isKeyDown(KC_S))

{

 // Move camera backward

vec.z = moveScale;

}

if (mInputDevice->isKeyDown(KC_PGUP))

{

// Move camera up

 vec.y = moveScale;

}

 if (mInputDevice->isKeyDown(KC_PGDOWN))

{ // Move camera down

vec.y = -moveScale;

}

if (mInputDevice->isKeyDown(KC_RIGHT))

{ mCamera->yaw(-rotScale); }

if (mInputDevice->isKeyDown(KC_LEFT))

{ mCamera->yaw(rotScale); }

if( mInputDevice->isKeyDown( KC_ESCAPE) )

{ return false; }

// Rotate view by mouse relative position float rotX, rotY; rotX = -mInputDevice->getMouseRelativeX() * 0.13;

rotY = -mInputDevice->getMouseRelativeY() * 0.13;

 // Make all the changes to the camera

// Note that YAW direction is around a fixed axis (freelook stylee) rather than a natural YAW (e.g. airplane)

mCamera->yaw(rotX);

mCamera->pitch(rotY);

mCamera->moveRelative(vec);

// Rotate scene node if required

SceneNode* node = mCamera->getSceneManager()->getRootSceneNode();

if (mInputDevice->isKeyDown(KC_O))

{ node->yaw(rotScale); }

if (mInputDevice->isKeyDown(KC_P))

 { node->yaw(-rotScale); }

 if (mInputDevice->isKeyDown(KC_I))

{ node->pitch(rotScale); }

if (mInputDevice->isKeyDown(KC_K))

{ node->pitch(-rotScale); }

if (mInputDevice->isKeyDown(KC_F) && timeUntilNextToggle <= 0)

{ mStatsOn = !mStatsOn;

//Root::getSingleton().showDebugOverlay(mStatsOn); showDebugOverlay(mStatsOn); timeUntilNextToggle = 1; }

// Return true to continue rendering

return true; } };

class TerrainApplication : public ExampleApplication

{ public: TerrainApplication() {}

protected: virtual void createFrameListener(void) { mFrameListener= new TerrainListener(mWindow, mCamera);

mFrameListener->showDebugOverlay(true);

mRoot->addFrameListener(mFrameListener);

}

virtual void chooseSceneManager(void)

{ // Get the SceneManager, in this case a generic one mSceneMgr = mRoot->getSceneManager( ST_EXTERIOR_CLOSE );

}

virtual void createCamera(void)

{

 // Create the camera mCamera = mSceneMgr->createCamera("PlayerCam");

// Position it at 500 in Z direction

mCamera->setPosition(Vector3(128,25,128));

// Look back along -Z

mCamera->lookAt(Vector3(0,0,-300));

mCamera->setNearClipDistance( 1 );

mCamera->setFarClipDistance( 384 );

}

virtual void createViewports(void)

{

// Create one viewport, entire window

Viewport* vp = mWindow->addViewport(mCamera);

vp->setBackgroundColour(ColourValue::White); }

// Just override the mandatory create scene method

void createScene(void)

{ Entity *waterEntity;

Plane waterPlane;

// Set ambient light mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));

// create a water plane/scene node

waterPlane.normal = Vector3::UNIT_Y;

waterPlane.d = -1.5;

MeshManager::getSingleton().createPlane( "WaterPlane", waterPlane, 2800, 2800, 20, 20, true, 1, 10, 10, Vector3::UNIT_Z );

waterEntity = mSceneMgr->createEntity("water", "WaterPlane");

 waterEntity->setMaterialName("Examples/TextureEffect4"); SceneNode *waterNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("WaterNode");

waterNode->attachObject(waterEntity);

 waterNode->translate(1000, 0, 1000);

 // Create a light

Light* l = mSceneMgr->createLight("MainLight");

// Accept default settings: point light, white diffuse, just set position

// NB I could attach the light to a SceneNode if I wanted it to move automatically with

// other objects, but I don't

l->setPosition(20,80,50);

mSceneMgr -> setWorldGeometry( "terrain.cfg" ); mSceneMgr->setFog( FOG_EXP2, ColourValue::White, .008, 0, 250 );

//mRoot -> showDebugOverlay( true ); } };

/* -----------------------------------------------------------------------------

This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright ?2000-2003 The OGRE Team Also see acknowledgements in Readme.html You may use this sample code for anything you like, it is not covered by the LGPL like the rest of the engine.

----------------------------------------------------------------------------- */

/** @file Terrain.cpp @brief Shows OGRE's terrain rendering plugin. */

#include "Ogre.h"

#include "Terrain.h"

#if OGRE_PLATFORM == PLATFORM_WIN32

#define WIN32_LEAN_AND_MEAN

#include "windows.h"

#endif

#if OGRE_PLATFORM == PLATFORM_WIN32 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )

#else int main(int argc, char *argv[])

#endif {

// Create application object TerrainApplication app; SET_TERM_HANDLER;

try { app.go();

} catch( Ogre::Exception& e )

{

#if OGRE_PLATFORM == PLATFORM_WIN32 MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl; #endif

}

return 0;

}

 

参考

(1)《游戏之王》——孙百英主编,科学普及出版社,ISBN:7-110-04493-9

(2)《设计模式》——Erich Gamma等,机械工业出版社,ISBN:7-111-07575-7

(3)OGRE文档和源代码——Ogre制作组(英国)

(4)《游戏引擎剖析》——Jake Simpson

(5)《圣剑群英传》文档和源代码——金点工作室(中国)

(6)《Ogre使用指南》——mage工作室(中国)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值