高層游戲引擎——基于OGRE所實現(xiàn)的高層游戲引擎框架(7) 收藏第四部分 結論和展望 通過對游戲世界的演繹,,對游戲邏輯的歸納,以及對游戲底層工具的融合,,逐步誕生了我們現(xiàn)在的框架,。為了使框架更能經得起檢驗,我們使用了一 些設計模式提供的方法來保證框架的安全性?,F(xiàn)在的高層游戲引擎說明了一點,,對于這個游戲,我們的框架達標了,。但用這個框架開發(fā)一個新的游戲是否也會達標,? 答案是否定的。如果用這個框架去開發(fā)一個RPG游戲,,那我們還缺技能,、道具等諸多系統(tǒng);如果去開發(fā)一個紙牌游戲,,似乎我們的框架對于規(guī)則支持還不是太方 便;如果去開發(fā)一個足球游戲,,似乎我們的框架對AI的支持太差勁……而且就OGRE本身也在不斷更新,、提供新的功能,甚至有時候否定原有的類和接口,。不過 把話說回來,,現(xiàn)在什么游戲引擎沒有這種問題呢,?寫底層引擎容易,但是寫一個通用的高層引擎層卻很復雜,,因為底層引擎只是跟變化緩慢的平臺技術相關,但高層 引擎層卻是跟豐富多彩的游戲相關的,。不僅如此,,高層引擎的存在同時受底層引擎的功能限制。 需要走的路還很長,,即便是對于國際知名的大公司,,也是在不斷的探索和實踐中。但這并不表明前途就是渺茫的,,我們通過這次實踐作出了一次從底而上和自上 而下的歸納和演繹的過程,,在變化多端的具體游戲和變化緩慢的引擎中間尋找到了一個引擎層契合點。內容繁復,、采用的表現(xiàn)手段多姿多彩的游戲世界,,即便是再復 雜,,也可以通過一定程度的歸納演繹得出適應其規(guī)則和表現(xiàn)的契合點和高層引擎層架構,。 附錄 Terrain Example /* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www./ 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./ 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等,,機械工業(yè)出版社,ISBN:7-111-07575-7 (3)OGRE文檔和源代碼——Ogre制作組(英國) (4)《游戲引擎剖析》——Jake Simpson (5)《圣劍群英傳》文檔和源代碼——金點工作室(中國) (6)《Ogre使用指南》——mage工作室(中國) |
|