Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 12 kết quả

Đề tài: Ogre, Lập trình game với Ogre graphic engine

  1. #1
    Ngày gia nhập
    09 2008
    Nơi ở
    Kĩ viện
    Bài viết
    169

    Mặc định Ogre, Lập trình game với Ogre graphic engine

    Homepage: ogre3d.org
    Là một trong 2 ông vua của graphic engine mã nguồn mở.

    Ogre và Irrlicht.

    Ông vua thứ hai Irrlicht thì đã được bạn Trần Đức Huy(hay Huy đọt nét, huytd gì đấy, lắm nick thế ko biết) giới thiệu rồi. Bây giờ mình sẽ giới thiệu với các bạn về ông vua thứ nhất. OGRE.

    Hiện tại đã có phiên bản 1.6(khiếp, nó lên như ăn cướp, mới hôm nào 1.48, 1.49. Chú Irrlicht thì vẫn dậm chân tại chỗ 1.4.9 từ hôm nảo hôm nào :( )

    Download
    (mình sẽ hướng dẫn trên Visual C++ 2005 Express nên các bạn nên down phiên bản cho Visual C++ 2005 Express SP1 .

    Sau khi down SDK của nó về thì cài thôi .

    Sau khi cài thì bạn tạo một project mới(win32 console, emty project).
    Add 1 cái header và 2 cái CPP code cho nó OOP nào .



    Game.h
    C++ Code:
    1. #ifndef _Game_H_
    2. #define _Game_H_
    3.  
    4. class Game
    5. {
    6. public:
    7.     Game();
    8.     ~Game();
    9. public:
    10.     void Run();
    11. };
    12.  
    13. #endif

    Game.cpp
    C++ Code:
    1. #include "Game.h"
    2.  
    3. Game::Game()
    4. {
    5. }
    6.  
    7. Game::~Game()
    8. {
    9. }
    10.  
    11. void Game::Run()
    12. {
    13. }

    main.cpp
    C++ Code:
    1. #include "Game.h"
    2.  
    3. int main()
    4. {
    5.     Game game;
    6.     game.Run();
    7.     return 0;
    8. }

    Hô hô, vẫn chưa có gì cả .

    Bây giờ ta link cái OgreMain.lib và include cái Ogre.h. Những thứ cần thiết cho một chương trình sử dụng Ogre đơn giản.

    Thêm đoạn sau vào file Game.h

    C++ Code:
    1. //! Sau #define _Game_H_
    2.  
    3. #include <Ogre.h>
    4. #pragma comment(lib,"OgreMain.lib")

    Nhưng một vấn đề sảy ra là chúng ta đang sài bản Express nên phải link thêm cái User32.lib vào.

    C++ Code:
    1. //!Sau #pragma comment(lib,"OgreMain.lib")
    2. #pragma comment(lib,"User32.lib")

    Rồi, song phần chuẩn bị .
    Đã được chỉnh sửa lần cuối bởi NamVoDang : 20-09-2008 lúc 06:32 PM. Lý do: Sao bây giờ mình mới biết highlight code thế này!
    Phá toái hư không - Bạch nhật thăng thiên.

  2. #2
    Ngày gia nhập
    09 2008
    Nơi ở
    Kĩ viện
    Bài viết
    169

    Hãy chắc chắn là bạn đã build được cái bên trên(thằng này build lâu kinh khủng luôn ).

    Có một cái sơ đồ to vật trong manual của nó nhưng NVD thấy có đọc bây giờ cũng ứ hiểu gì nên thôi ko đưa lên(học dần rồi sẽ giới thiệu).

    The Root object
    Dịch thẳng. Cái object này là entry point của Ogre System. Nó PHẢI được tạo đầu tiên và bị khử cuối cùng.

    Thêm vào Game một con trỏ kiểu Ogre::Root.
    C++ Code:
    1. private:
    2.     Ogre::Root* Root;
    Rồi thêm vào Constructor của Game
    C++ Code:
    1. Root = NULL;
    2. Root = new Ogre::Root("plugins.cfg", "ogre.cfg", "Ogre.log");

    Tham số đầu tiên là path của file cấu hình plugin(nạp những plugin nào), cái thứ hai là file cấu hình game, cái thứ 3 là file log.

    Rứa rồi thêm vào Destructor của Game.

    Code:
    if(Root)
    	delete Root;
    Vậy là xong, chúng ta đã thỏa mãn yêu cầu tạo đầu tiên và xóa cuối cùng của nó .

    Bây giờ chúng ta sẽ hiện hộp thoại để người dùng cấu hình game, tạo một cửa sổ tự động và bắt đầu vòng lặp render.

    method Run().

    C++ Code:
    1.     if(!Root)
    2.         return;//!Error
    3.     if(!Root->showConfigDialog())
    4.         return;
    5.     Root->initialise(true, "OgreWindow");
    6.     Root->startRendering();

    Vậy là bạn đã tạo được một cửa sổ game với Caption "OgreWindow", nhưng khi bạn close cái cửa sổ đó thì game vẫn chạy tiếp . Lý do là tuy cái cửa sổ đó đóng nhưng vòng lặp game vẫn chạy(thằng Ogre này render được một lúc vài cái cửa sổ luôn). Ở đây chúng ta chỉ cần một cửa sổ game nên yêu cầu là game phải kết thúc khi cái cửa sổ đó đóng.

    Nhưng phần này lại liên quan tới FrameListener nên phải đợi đến phần sau mình nói tiếp, bây giờ phải đi ngủ .

    Edit: Bạn phải vào C:\OgreSDK\bin\release copy hết cái mớ hổ lốn của nó vào cùng thư mục của cái project của bạn(lắm của thế).
    Đã được chỉnh sửa lần cuối bởi NamVoDang : 20-09-2008 lúc 06:31 PM.
    Phá toái hư không - Bạch nhật thăng thiên.

  3. #3
    Ngày gia nhập
    09 2008
    Nơi ở
    Kĩ viện
    Bài viết
    169



    Cái sơ đồ bự chảng này nếu ko phải dân từng học làm game rồi thì nhìn vào phần lớn là..chả hiểu mô tê gì luôn.

    Bây giờ zoom vào cái(trông như cái foder) SceneManagement.
    Trong đó gồm các phần sau.
    Fixed text Code:
    1. SceneManager
    2. SceneNode
    3. MovableObject
    4.         +Entity.
    5.         +Camera.
    6.         +Light.
    Còn quả Material thì cứ kệ nó đã.

    SceneManager làm cái gì?
    Tất cả những gì xuất hện trên màn hình được quản lý bởi "trình quản lý cảnh" SceneManager.

    MovableObject là cái gì?
    Là một trong những thứ xuất hiện trên màn hình. Gồm các loại là Entity, Camera, Light, Billboard(Cái ảnh 2 chiều luôn luôn quay mặt về phía camera), Particle(hệ thống hạt). (Nếu xem source thì sẽ thấy tất cả đều được kế thừa từ MovableObject).

    SceneNode là cái gì?
    Là cái "nút cảnh" . Cứ tưởng tượng như thế này, nó như một điểm trong không gian, nơi mà có một cái gì đó(nhà cửa, cây cối V.v..). Khi di chuyển cái điểm đó thì cái gì đó cũng đi theo luôn, nói chung nó có cấu trúc dạng cây với một cái Node cao nhất là RootSceneNode. Mỗi node lại có các node con của nó. Khi di chuyển một node thì các node con của nó cũng di chuyển theo, khi một node bị xóa thì các node con cũng theo đó mà đi đời(tận trung với chủ ).

    Nói mãi rồi, chán vãi. Nhưng thôi nói thêm một đoạn nữa rồi đi vào thực hành cho nó dễ hiểu, học phải đi đôi với hành, các cụ biểu rứa.

    RenderWindow?
    SceneManager chứa những thứ để render, vậy những thứ đó sẽ được render vào đâu?. Câu trả lời là vào các render target, RenderWindow là một trong số đó(RenderWindow kế thừa từ render target). Đến đây có thể bạn tự hỏi, thế chả render vào window thì vào cái gì?, thằng nói ngu vãi!. Nhưng thực ra thì ngoài render vào một window thì Ogre còn có thể render vào một cái texture nữa. Ví dụ trong game bạn có một cái tivi, bạn sẽ có hai SceneManager, một cái để chứa thế giới nơi mà cái tivi đó được đặt, cái kia chứa những thứ mà cái tivi đó hiển thị, khi đó thì cái scene manager thứ nhất sẽ render ra cửa sổ, thể hiện cái tivi và cái bàn, còn cái scene manager thứ hai sẽ render "thẳng" vào màn hình cái tivi trong game. Vậy là nhân vật của chúng ta có thể ngồi xem tivi như ai.

    Viewport?
    Cổng nhìn. Các bạn đã chơi game dạng split screen bao giờ chưa?. Need For Speed chẳng hạn. Vấn đề là đôi khi chúng ta không muốn render lên cả một cái window(chỉ một nửa thôi chẳng hạn). Chúng ta có thể có hai cái camera, một cái bám theo người chơi số một, cái còn lại bám theo người chơi số hai. Và mỗi nửa màn hình sẽ vẽ một camera. Khái niệm viewport được đưa vào, viewport là một phần trên render target, nơi mà ta có thể render vào đó.

    Vậy cuối cùng chúng ta có các bước để render một cảnh từ SceneManager ra RenderWindow như sau.

    B1.Tạo một cái window, trên cái window đó lại tạo một viewport.
    B2. Tạo một scene manager, trong scene manager đó lại tạo một camera.
    B3. Attach cái camera đó vào viewport, từ bây giờ, mỗi lần loop, viewport trên window sẽ thể hiện những thứ mà camera thấy.

    Oáp!. thực hành!

    Game.h
    C++ Code:
    1. #ifndef _Game_H_
    2. #define _Game_H_
    3.  
    4. #include <Ogre.h>
    5. #pragma comment(lib,"OgreMain_d.lib")
    6.  
    7. class Game
    8. {
    9. public:
    10.     Game();
    11.     ~Game();
    12. public:
    13.     void Run();
    14. private:
    15.     void LoadResource();
    16.     void CreateScene();
    17. private:
    18.     Ogre::Root* Root;
    19.     Ogre::RenderWindow* RenderWindow;
    20.     Ogre::Camera* Camera;
    21. private:
    22.     Ogre::SceneManager* SceneManager;
    23.     Ogre::SceneNode* OgreHeadNode;
    24.  
    25. };
    26.  
    27. #endif

    Có một số thay đổi, thêm vào vài con trỏ và một method.

    Game.cpp
    C++ Code:
    1. #include "Game.h"
    2.  
    3. Game::Game()
    4. {
    5.     Root = NULL;
    6.     Root = new Ogre::Root();
    7. }
    8.  
    9. Game::~Game()
    10. {
    11.     if(Root)
    12.         delete Root;
    13. }
    14.  
    15. void Game::Run()
    16. {
    17.     if(!Root)
    18.         return;//!Error
    19.     if(!Root->showConfigDialog())
    20.         return;
    21.     RenderWindow = Root->initialise(true, "OgreWindow");//!Tự động tạo một window có caption là OgreWindow.
    22.     SceneManager = Root->createSceneManager(Ogre::SceneType::ST_EXTERIOR_REAL_FAR);//!Tạo một scene manager kiểu EXTERIOR_REAL_FAR.
    23.     Camera = SceneManager->createCamera("ExampleCamera");//!Tạo một camera có tên là ExampleCamera(các camera trong một scene manager ko được trùng tên).
    24.     Ogre::Viewport* Viewport = RenderWindow->addViewport(Camera);//Thêm một viewport vào window(ở đây chiếm full luôn), và attach cho nó cái camera vừa tạo ở trên.
    25.     Viewport->setBackgroundColour(Ogre::ColourValue::Black);//!Đặt màu nền cho cái viewport vừa tạo là màu đen.
    26.  
    27.     this->LoadResource();
    28.  
    29.     this->CreateScene();
    30.  
    31.     Root->startRendering();//!Begin loop.
    32. }
    33.  
    34. void Game::CreateScene()
    35. {
    36. }
    37.  
    38. void Game::LoadResource()//!Load các resource chỉ định trong file resources.cfg (Đừng quan tâm nó làm thế nào vội)
    39. {
    40.     Ogre::ConfigFile cf;
    41.     cf.load("resources.cfg");
    42.     Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
    43.     Ogre::String secName, typeName, archName;
    44.     while (seci.hasMoreElements())
    45.     {
    46.         secName = seci.peekNextKey();
    47.         Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
    48.         Ogre::ConfigFile::SettingsMultiMap::iterator i;
    49.         for (i = settings->begin(); i != settings->end(); ++i)
    50.         {
    51.             typeName = i->first;
    52.             archName = i->second;
    53.             Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
    54.         }
    55.     }
    56.     Ogre::ResourceGroupManager::getSingletonPtr()->initialiseAllResourceGroups();
    57. }

    main.cpp vẫn thế. Build và run cái nào.




    Chả có cái gì mà xem , lần này chạy có vẻ lâu hơn lần trước(tại nó phải load mấy cái resource. Nhớ là khi close cái window đó thì game vẫn chạy, bạn phải close cả cái console nữa thì game mới dừng.

    Bây giờ thử mần thêm một số trò nữa cho vui cái nào .
    trong method CreateScene()
    C++ Code:
    1. Camera->setPosition(200, 0, 0);//!Đặt lại vị trí camera.
    2.     Camera->lookAt(0, 0, 0);//! Camera nhìn tới gốc tọa độ.
    3.     SceneManager->setAmbientLight(Ogre::ColourValue(1, 1, 1));
    4.  
    5.     Ogre::Entity* entity = SceneManager->createEntity("OgreHeadMesh", "ogrehead.mesh");//!Tạo một entity có mesh là hình cái đầu(hình như là đầu trâu, chả biết nữa).
    6.     OgreHeadNode = SceneManager->getRootSceneNode()->createChildSceneNode();//!Tạo một scene node con từ RootSceneNode.
    7.              OgreHeadNode->setPosition(0, 0, 0);//!Đặt vị trí của cái node này ở gốc tọa độ.
    8.     OgreHeadNode->attachObject(entity);//!Attach cái đầu ogre vào node vừa tạo.
    À! Entity, cái gì ấy nhỉ?

    Bạn có thể ngĩ entity như một cái vật thể 3D được load từ một mesh(định dạng model của Ogre, tạo = các chương trình như 3dsMax hay Maya hay V.v..). Nó có thể là cái đầu trâu như trên, có thể là con cá, nhân vật, hay thảo nguyên mà nhân vật chạy trên đó(một cái mesh siêu lớn). Entity là một MovableObject, và một movableobject chỉ tham gia vào scene khi nó được attach vào một node. bây giờ bạn di chuyển cái OgreHeadNode thì cái đầu ogre cũng di chuyển theo.

    Build and run.



    Xuất hiện một cái đầu xấu òm trong không gian, nhưng thôi, khởi đầu thế đã, từ từ rồi nó sẽ đẹp dần.
    Attached Files Attached Files
    Đã được chỉnh sửa lần cuối bởi NamVoDang : 20-09-2008 lúc 06:29 PM.
    Phá toái hư không - Bạch nhật thăng thiên.

  4. #4
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Cho tui hỏi tí là :
    - Cái này có cần kiến thức về graphics nhiều không ?
    - Trong Orge có sử dụng nhiều macro không ?
    - Cảm giác bài đầu tiên thấy mã code rất sáng( pure C++ ), tuy vậy không biết nó có 1 set các container riêng biệt hay ta có thể sử dụng STL container ?
    - Cậu có ebook nào về Orge này không ?
    ps : Tut viết rất hay và hấp dẫn !

  5. #5
    Ngày gia nhập
    09 2008
    Nơi ở
    Kĩ viện
    Bài viết
    169

    Trích dẫn Nguyên bản được gửi bởi rox_rook Xem bài viết
    Cho tui hỏi tí là :
    - Cái này có cần kiến thức về graphics nhiều không ?
    Mù tịt như tớ học còn được .

    - Trong Orge có sử dụng nhiều macro không ?
    không đâu, mà con này hướng đối tượng toàn tập, code thích lắm .

    không biết nó có 1 set các container riêng biệt hay ta có thể sử dụng STL container ?
    Không, dùng STL chứ.

    Cậu có ebook nào về Orge này không ?
    Đây đây!

    http://forum.gamedev.vn/index.php?showtopic=1259
    Phá toái hư không - Bạch nhật thăng thiên.

  6. #6
    Ngày gia nhập
    09 2008
    Nơi ở
    Kĩ viện
    Bài viết
    169

    Mặc định Ogre, Lập trình game với Ogre graphic engine

    À! chúng ta tiếp tục.

    Trước hết ....bạn nào có acc premium megaupload thì get direct link hộ mình cái này(cắm torrent từ sáng về được 26 % 2kb/s ?) http://www.megaupload.com/?d=KQP8PLKS

    Hô hô, giờ vào chuyên môn.

    FrameListener
    Trong method Run của class Game, bạn để ý dòng cuối cùng, khi mà chúng ta đã khởi tạo engine và add một cái đầu trâu có dòng này.
    C++ Code:
    1. Root->startRendering();//!Begin loop.
    Đây chính là nơi mà vòng lặp game bắt đầu, mỗi lần lặp sẽ như sau.

    -Giai đoạn 1. Root gọi method "frameStarted" trên tất cả các frameListener được đăng ký.
    -Giai đoạn 2. Xóa màn hình và vẽ cảnh mới(render một khung hình mới).
    -Giai đoạn 3. Root gọi method "frameEnded" trên tất cả các frameListener

    Chúng ta sẽ can thiệp vào game qua hai giai đoạn. Là "tiền render" và "hậu render"(xài hẳn từ hán-việt cho mấu ).

    Class Ogre::FrameListener.
    C++ Code:
    1. class _OgreExport FrameListener
    2.     {
    3.     public:
    4.         virtual bool frameStarted(const FrameEvent& evt) { return true; }
    5.        
    6.     virtual bool frameRenderingQueued(const FrameEvent& evt) { return true; }
    7.         virtual bool frameEnded(const FrameEvent& evt) { return true; }
    8.  
    9.     virtual ~FrameListener() {}
    10. };

    Nó để lại cho các class thừa kế từ nó hai method là bool frameStarted(const FrameEvent& evt) và bool frameEnded(const FrameEvent& evt). Hai method này trả về giá trị kiểu bool, nếu true thì loop tiếp, false thì dừng loop.

    Bây giờ ta sẽ giải quyết vấn đề trong các ví dụ trước, khi close window thì thoát game. Ý tưởng là mỗi lần loop lại kiểm tra trạng thái cái window xem nó close chưa, nếu close rồi thì return false.

    Game.h
    C++ Code:
    1. class Game: public Ogre::FrameListener //! <---------------Chú ý
    2. {
    3. public:
    4.     Game();
    5.     ~Game();
    6. public:
    7.     void Run();
    8. private:
    9.     void LoadResource();
    10.     void CreateScene();
    11. private:
    12.     Ogre::Root* Root;
    13.     Ogre::RenderWindow* RenderWindow;
    14.     Ogre::Camera* Camera;
    15. private:
    16.     Ogre::SceneManager* SceneManager;
    17.     Ogre::SceneNode* OgreHeadNode;
    18. protected:
    19.     bool frameStarted(const Ogre::FrameEvent &evt);//! <---------------Chú ý
    20.     bool frameEnded(const Ogre::FrameEvent &evt);//! <---------------Chú ý
    21. };

    C++ Code:
    1. #include "Game.h"
    2.  
    3. Game::Game()
    4. {
    5.     Root = NULL;
    6.     Root = new Ogre::Root();
    7. }
    8.  
    9. Game::~Game()
    10. {
    11.     if(Root)
    12.         delete Root;
    13. }
    14.  
    15. void Game::Run()
    16. {
    17.     if(!Root)
    18.         return;//!Error
    19.     if(!Root->showConfigDialog())
    20.         return;
    21.     RenderWindow = Root->initialise(true, "OgreWindow");//!Tự động tạo một window có caption là OgreWindow.
    22.     SceneManager = Root->createSceneManager(Ogre::SceneType::ST_EXTERIOR_REAL_FAR);//!Tạo một scene manager kiểu EXTERIOR_REAL_FAR.
    23.     Camera = SceneManager->createCamera("ExampleCamera");//!Tạo một camera có tên là ExampleCamera(các camera trong một scene manager ko được trùng tên).
    24.     Ogre::Viewport* Viewport = RenderWindow->addViewport(Camera);//Thêm một viewport vào window(ở đây chiếm full luôn), và attach cho nó cái camera vừa tạo ở trên.
    25.     Viewport->setBackgroundColour(Ogre::ColourValue::Black);//!Đặt màu nền cho cái viewport vừa tạo là màu đen.
    26.  
    27.     this->LoadResource();
    28.  
    29.     this->CreateScene();
    30.  
    31.         Root->addFrameListener(this);//! <-----------------Chú ý
    32.  
    33.     Root->startRendering();//!Begin loop.
    34. }
    35.  
    36. void Game::CreateScene()
    37. {
    38.     Camera->setPosition(200, 0, 0);//!Đặt lại vị trí camera.
    39.     Camera->lookAt(0, 0, 0);//! Camera nhìn tới gốc tọa độ.
    40.     SceneManager->setAmbientLight(Ogre::ColourValue(1, 1, 1));
    41.  
    42.     Ogre::Entity* entity = SceneManager->createEntity("OgreHeadMesh", "ogrehead.mesh");//!Tạo một entity có mesh là hình cái đầu(hình như là đầu trâu, chả biết nữa).
    43.     OgreHeadNode = SceneManager->getRootSceneNode()->createChildSceneNode();//!Tạo một scene node con từ RootSceneNode.
    44.     OgreHeadNode->setPosition(0, 0, 0);//!Đặt vị trí của cái node này ở gốc tọa độ.
    45.     OgreHeadNode->attachObject(entity);//!Attach cái đầu ogre vào node vừa tạo.
    46. }
    47.  
    48. void Game::LoadResource()//!Load các resource chỉ định trong file resources.cfg (Đừng quan tâm nó làm thế nào vội)
    49. {
    50.     Ogre::ConfigFile cf;
    51.     cf.load("resources.cfg");
    52.     Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
    53.     Ogre::String secName, typeName, archName;
    54.     while (seci.hasMoreElements())
    55.     {
    56.         secName = seci.peekNextKey();
    57.         Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
    58.         Ogre::ConfigFile::SettingsMultiMap::iterator i;
    59.         for (i = settings->begin(); i != settings->end(); ++i)
    60.         {
    61.             typeName = i->first;
    62.             archName = i->second;
    63.             Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
    64.         }
    65.     }
    66.     Ogre::ResourceGroupManager::getSingletonPtr()->initialiseAllResourceGroups();
    67. }
    68.  
    69. bool Game::frameStarted(const Ogre::FrameEvent &evt)//! <-----------------Chú ý
    70. {
    71.     return true;
    72. }
    73.  
    74. bool Game::frameEnded(const Ogre::FrameEvent &evt)//! <-----------------Chú ý
    75. {
    76.     return true;
    77. }

    Có lẽ đến đây bạn đã hiểu cách reg một FrameListener rồi nhỉ .

    Trong method frameStarted() thêm vào.
    C++ Code:
    1.     if(RenderWindow->isClosed())
    2.         return false;

    Nhìn quá dễ hiểu phải ko (ogre là thế đấy, dễ như ăn cháo ấy mà), Nếu RenderWindow đã đóng thì return false -> vòng lặp kết thúc -> end program.

    Các bạn có thể ngịch thêm cho quen với hệ thống này như mỗi giây di chuyển cái đầu Ogre đi n đơn vị lên trên chẳng hạn(trục Y). Coi như làm một bài kiểm tra kiến thức .

    Gợi ý.
    struct "evt" trong frameStarted() và frameEnded() có chứa thời gian kể từ lần render trước.

    Tiếp sau sẽ là hệ thống Input.
    Đã được chỉnh sửa lần cuối bởi NamVoDang : 22-09-2008 lúc 02:00 PM.
    Phá toái hư không - Bạch nhật thăng thiên.

  7. #7
    Ngày gia nhập
    09 2008
    Nơi ở
    Kĩ viện
    Bài viết
    169

    Về cái vấn đề Input. Một sự thật phũ phàng là thằng Ogre này ứ có hệ thống Input :((. Ô thế nhưng mà xét lại thì đấy không những không phải nhược điểm mà lại còn là ưu điểm . Vì sao?.

    Vì ku Ogre này nó quá nổi tiếng, quá hầm hố trong cái vương quốc FOS mà nó đang trị vì. Thế cho nên..thế cho nên rất nhiều các vương hầu quý tộc muốn về dưới trướng của nó. Về phần Input, nó không cần trực tiếp ra tay, mà chỉ đợi thằng khác ra tay hộ . Thậm chí, nó được quyền chọn lựa xem nên cho thằng nào ra tay, thằng nào không đủ tuổi .

    Và trong đám chư hầu của nó về phần Input. Đáng chú ý nhất là OIS.

    Thằng này đi kèm Ogre khi release luôn, ngĩa là có sẵn trong SDK của nó, khỏi down chi mất công . Bây giờ, header Game.h được viết lại như sau.

    C++ Code:
    1. #ifndef _Game_H_
    2. #define _Game_H_
    3.  
    4. #include <Ogre.h>
    5. #include <OIS/OIS.h>//<---------------Chú ý
    6. #pragma comment(lib,"OgreMain_d.lib")
    7. #pragma comment(lib,"OIS.lib")//<---------------Chú ý
    8.  
    9. class Game: public Ogre::FrameListener
    10. {
    11. public:
    12.     Game();
    13.     ~Game();
    14. public:
    15.     void Run();
    16. private:
    17.     void LoadResource();
    18.     void CreateScene();
    19. private:
    20.     Ogre::Root* Root;
    21.     Ogre::RenderWindow* RenderWindow;
    22.     Ogre::Camera* Camera;
    23. private:
    24.     Ogre::SceneManager* SceneManager;
    25.     Ogre::SceneNode* OgreHeadNode;
    26. protected:
    27.     bool frameStarted(const Ogre::FrameEvent &evt);
    28.     bool frameEnded(const Ogre::FrameEvent &evt);
    29. private://<---------------Chú ý, từ đây xuống.
    30.     OIS::Mouse* Mouse;
    31.     OIS::Keyboard* Keyboard;
    32.     OIS::InputManager* InputManager;
    33. private:
    34.     void InputCreate();
    35.     void InputDestroy();
    36.     void InputCapture();
    37. };
    38.  
    39. #endif

    Game.cpp
    C++ Code:
    1. #include "Game.h"
    2.  
    3. Game::Game()
    4. {
    5.     Root = NULL;
    6.     Root = new Ogre::Root();
    7. }
    8.  
    9. Game::~Game()
    10. {
    11.     this->InputDestroy();//<---------------Chú ý
    12.  
    13.     if(Root)
    14.         delete Root;
    15. }
    16.  
    17. void Game::Run()
    18. {
    19.     if(!Root)
    20.         return;//!Error
    21.     if(!Root->showConfigDialog())
    22.         return;
    23.     RenderWindow = Root->initialise(true, "OgreWindow");//!Tự động tạo một window có caption là OgreWindow.
    24.     SceneManager = Root->createSceneManager(Ogre::SceneType::ST_EXTERIOR_REAL_FAR);//!Tạo một scene manager kiểu EXTERIOR_REAL_FAR.
    25.     Camera = SceneManager->createCamera("ExampleCamera");//!Tạo một camera có tên là ExampleCamera(các camera trong một scene manager ko được trùng tên).
    26.     Ogre::Viewport* Viewport = RenderWindow->addViewport(Camera);//Thêm một viewport vào window(ở đây chiếm full luôn), và attach cho nó cái camera vừa tạo ở trên.
    27.     Viewport->setBackgroundColour(Ogre::ColourValue::Black);//!Đặt màu nền cho cái viewport vừa tạo là màu đen.
    28.  
    29.     this->InputCreate();//<---------------Chú ý
    30.  
    31.     this->LoadResource();
    32.  
    33.     this->CreateScene();
    34.  
    35.     Root->addFrameListener(this);
    36.  
    37.     Root->startRendering();//!Begin loop.
    38. }
    39.  
    40. void Game::CreateScene()
    41. {
    42.     Camera->setPosition(200, 0, 0);//!Đặt lại vị trí camera.
    43.     Camera->lookAt(0, 0, 0);//! Camera nhìn tới gốc tọa độ.
    44.     SceneManager->setAmbientLight(Ogre::ColourValue(1, 1, 1));
    45.  
    46.     Ogre::Entity* entity = SceneManager->createEntity("OgreHeadMesh", "ogrehead.mesh");//!Tạo một entity có mesh là hình cái đầu(hình như là đầu trâu, chả biết nữa).
    47.     OgreHeadNode = SceneManager->getRootSceneNode()->createChildSceneNode();//!Tạo một scene node con từ RootSceneNode.
    48.     OgreHeadNode->setPosition(0, 0, 0);//!Đặt vị trí của cái node này ở gốc tọa độ.
    49.     OgreHeadNode->attachObject(entity);//!Attach cái đầu ogre vào node vừa tạo.
    50. }
    51.  
    52. void Game::LoadResource()//!Load các resource chỉ định trong file resources.cfg (Đừng quan tâm nó làm thế nào vội)
    53. {
    54.     Ogre::ConfigFile cf;
    55.     cf.load("resources.cfg");
    56.     Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
    57.     Ogre::String secName, typeName, archName;
    58.     while (seci.hasMoreElements())
    59.     {
    60.         secName = seci.peekNextKey();
    61.         Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
    62.         Ogre::ConfigFile::SettingsMultiMap::iterator i;
    63.         for (i = settings->begin(); i != settings->end(); ++i)
    64.         {
    65.             typeName = i->first;
    66.             archName = i->second;
    67.             Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
    68.         }
    69.     }
    70.     Ogre::ResourceGroupManager::getSingletonPtr()->initialiseAllResourceGroups();
    71. }
    72.  
    73. bool Game::frameStarted(const Ogre::FrameEvent &evt)
    74. {
    75.     if(RenderWindow->isClosed())
    76.         return false;
    77.     this->InputCapture();//<---------------Chú ý, mỗi lần lặp phải gọi là "cướp" event(dịch ngu :( ). Nôm na là xem có nút gì được bấm không.
    78.     return true;
    79. }
    80.  
    81. bool Game::frameEnded(const Ogre::FrameEvent &evt)
    82. {
    83.     return true;
    84. }
    85.  
    86. void Game::InputCreate()
    87. {
    88. }
    89.  
    90. void Game::InputDestroy()
    91. {
    92. }
    93.  
    94. void Game::InputCapture()
    95. {
    96. }

    method InputCreate.//!Không cần quan tâm kĩ làm gì =)). Các bước nó cố định thế, nhưng nếu thích tìm hiểu thì cũng không hại gì.
    C++ Code:
    1.         OIS::ParamList pl;
    2.     size_t windowHnd = 0;
    3.     std::ostringstream windowHndStr;
    4.  
    5.     RenderWindow->getCustomAttribute("WINDOW", &windowHnd);
    6.     windowHndStr << windowHnd;
    7.     pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
    8.  
    9.     InputManager = OIS::InputManager::createInputSystem( pl );
    10.  
    11.     //!Create all devices.
    12.     Keyboard = static_cast<OIS::Keyboard*>(InputManager->createInputObject( OIS::OISKeyboard, true ));
    13.     Mouse = static_cast<OIS::Mouse*>(InputManager->createInputObject( OIS::OISMouse, true ));
    14.  
    15.     unsigned int width, height, depth;
    16.     int left, top;
    17.     RenderWindow->getMetrics(width, height, depth, left, top);
    18.     Mouse->getMouseState().width = width;
    19.     Mouse->getMouseState().height = height;
    method InputDestroy.
    C++ Code:
    1. if(InputManager)
    2.     {
    3.         if(Mouse)
    4.             InputManager->destroyInputObject(Mouse);
    5.         if(Keyboard)
    6.             InputManager->destroyInputObject(Keyboard);
    7.  
    8.         OIS::InputManager::destroyInputSystem(InputManager);
    9.         InputManager = 0;
    10.     }
    method InputCapture.
    C++ Code:
    1. if(Mouse)
    2.         Mouse->capture();
    3.     if(Keyboard)
    4.         Keyboard->capture();

    Build and run. Điều dễ nhận thấy nhất là con trỏ chuột đã biến mất =)). Kệ nó, sau cho GUI vào là ngon hết.

    Chúng ta đã tạo được một hệ thống input với OIS, phần tiếp theo sẽ ứng dụng OIS để làm một cái FPS camera.
    (Third Person Camera có thể xem tại đây).
    http://forum.gamedev.vn/index.php?showtopic=1776

    Hix, check code của VHFOS mới được 33/hơn 80 mb :((. Viết tiếp phần sau luôn .
    Đã được chỉnh sửa lần cuối bởi NamVoDang : 01-10-2008 lúc 06:47 AM.
    Phá toái hư không - Bạch nhật thăng thiên.

  8. #8
    Ngày gia nhập
    09 2008
    Nơi ở
    Kĩ viện
    Bài viết
    169

    Thêm cái này vào nào .
    game.h
    C++ Code:
    1. #ifndef _Game_H_
    2. #define _Game_H_
    3.  
    4. #include <Ogre.h>
    5. #include <OIS/OIS.h>
    6. #pragma comment(lib,"OgreMain_d.lib")
    7. #pragma comment(lib,"OIS_d.lib")
    8.  
    9. #include "CameraControler.h"//<---------------Chú ý
    10.  
    11. class Game: public Ogre::FrameListener
    12. {
    13. public:
    14.     Game();
    15.     ~Game();
    16. public:
    17.     void Run();
    18. private:
    19.     void LoadResource();
    20.     void CreateScene();
    21. private:
    22.     Ogre::Root* Root;
    23.     Ogre::RenderWindow* RenderWindow;
    24.     Ogre::Camera* Camera;
    25. private:
    26.     Ogre::SceneManager* SceneManager;
    27.     Ogre::SceneNode* OgreHeadNode;
    28. protected:
    29.     bool frameStarted(const Ogre::FrameEvent &evt);
    30.     bool frameEnded(const Ogre::FrameEvent &evt);
    31. private:
    32.     OIS::Mouse* Mouse;
    33.     OIS::Keyboard* Keyboard;
    34.     OIS::InputManager* InputManager;
    35. private:
    36.     void InputCreate();
    37.     void InputDestroy();
    38.     void InputCapture();
    39. private:
    40.     CameraControler* cameraControl;//<---------------Chú ý
    41. };
    42.  
    43. #endif

    game.cpp
    C++ Code:
    1. #include "Game.h"
    2.  
    3. Game::Game()
    4. {
    5.     InputManager = NULL;
    6.     Mouse = NULL;
    7.     Keyboard = NULL;
    8.     cameraControl = NULL;//<---------------Chú ý
    9.     Root = NULL;
    10.     Root = new Ogre::Root();
    11. }
    12.  
    13. Game::~Game()
    14. {
    15.     if(cameraControl)//<---------------Chú ý
    16.         delete cameraControl;
    17.  
    18.     this->InputDestroy();
    19.  
    20.     if(Root)
    21.         delete Root;
    22. }
    23.  
    24. void Game::Run()
    25. {
    26.     if(!Root)
    27.         return;//!Error
    28.     if(!Root->showConfigDialog())
    29.         return;
    30.     RenderWindow = Root->initialise(true, "OgreWindow");//!Tự động tạo một window có caption là OgreWindow.
    31.     SceneManager = Root->createSceneManager(Ogre::SceneType::ST_EXTERIOR_REAL_FAR);//!Tạo một scene manager kiểu EXTERIOR_REAL_FAR.
    32.     Camera = SceneManager->createCamera("ExampleCamera");//!Tạo một camera có tên là ExampleCamera(các camera trong một scene manager ko được trùng tên).
    33.     Ogre::Viewport* Viewport = RenderWindow->addViewport(Camera);//Thêm một viewport vào window(ở đây chiếm full luôn), và attach cho nó cái camera vừa tạo ở trên.
    34.     Viewport->setBackgroundColour(Ogre::ColourValue::Black);//!Đặt màu nền cho cái viewport vừa tạo là màu đen.
    35.  
    36.     this->InputCreate();
    37.  
    38.     this->LoadResource();
    39.  
    40.     this->CreateScene();
    41.  
    42.     Root->addFrameListener(this);
    43.  
    44.     Root->startRendering();//!Begin loop.
    45. }
    46.  
    47. void Game::CreateScene()
    48. {
    49.     Camera->setPosition(200, 0, 0);//!Đặt lại vị trí camera.
    50.     Camera->lookAt(0, 0, 0);//! Camera nhìn tới gốc tọa độ.
    51.     SceneManager->setAmbientLight(Ogre::ColourValue(1, 1, 1));
    52.  
    53.     Ogre::Entity* entity = SceneManager->createEntity("OgreHeadMesh", "ogrehead.mesh");//!Tạo một entity có mesh là hình cái đầu(hình như là đầu trâu, chả biết nữa).
    54.     OgreHeadNode = SceneManager->getRootSceneNode()->createChildSceneNode();//!Tạo một scene node con từ RootSceneNode.
    55.     OgreHeadNode->setPosition(0, 0, 0);//!Đặt vị trí của cái node này ở gốc tọa độ.
    56.     OgreHeadNode->attachObject(entity);//!Attach cái đầu ogre vào node vừa tạo.
    57.  
    58.     cameraControl = new CameraControler(this->Keyboard, this->Mouse, this->Root, this->Camera);//<---------------Chú ý
    59. }
    60.  
    61. void Game::LoadResource()//!Load các resource chỉ định trong file resources.cfg (Đừng quan tâm nó làm thế nào vội)
    62. {
    63.     Ogre::ConfigFile cf;
    64.     cf.load("resources.cfg");
    65.     Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
    66.     Ogre::String secName, typeName, archName;
    67.     while (seci.hasMoreElements())
    68.     {
    69.         secName = seci.peekNextKey();
    70.         Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
    71.         Ogre::ConfigFile::SettingsMultiMap::iterator i;
    72.         for (i = settings->begin(); i != settings->end(); ++i)
    73.         {
    74.             typeName = i->first;
    75.             archName = i->second;
    76.             Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
    77.         }
    78.     }
    79.     Ogre::ResourceGroupManager::getSingletonPtr()->initialiseAllResourceGroups();
    80. }
    81.  
    82. bool Game::frameStarted(const Ogre::FrameEvent &evt)
    83. {
    84.     if(RenderWindow->isClosed())
    85.         return false;
    86.     this->InputCapture();
    87.     return true;
    88. }
    89.  
    90. bool Game::frameEnded(const Ogre::FrameEvent &evt)
    91. {
    92.     return true;
    93. }
    94.  
    95. void Game::InputCreate()
    96. {
    97.     OIS::ParamList pl;
    98.     size_t windowHnd = 0;
    99.     std::ostringstream windowHndStr;
    100.  
    101.     RenderWindow->getCustomAttribute("WINDOW", &windowHnd);
    102.     windowHndStr << windowHnd;
    103.     pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
    104.  
    105.     InputManager = OIS::InputManager::createInputSystem( pl );
    106.  
    107.     //!Create all devices.
    108.     Keyboard = static_cast<OIS::Keyboard*>(InputManager->createInputObject( OIS::OISKeyboard, true ));
    109.     Mouse = static_cast<OIS::Mouse*>(InputManager->createInputObject( OIS::OISMouse, true ));
    110.  
    111.     unsigned int width, height, depth;
    112.     int left, top;
    113.     RenderWindow->getMetrics(width, height, depth, left, top);
    114.     Mouse->getMouseState().width = width;
    115.     Mouse->getMouseState().height = height;
    116. }
    117.  
    118. void Game::InputDestroy()
    119. {
    120.     if(InputManager)
    121.     {
    122.         if(Mouse)
    123.             InputManager->destroyInputObject(Mouse);
    124.         if(Keyboard)
    125.             InputManager->destroyInputObject(Keyboard);
    126.  
    127.         OIS::InputManager::destroyInputSystem(InputManager);
    128.         InputManager = 0;
    129.     }
    130. }
    131.  
    132. void Game::InputCapture()
    133. {
    134.     if(Mouse)
    135.         Mouse->capture();
    136.     if(Keyboard)
    137.         Keyboard->capture();
    138. }



    Ô!.

    Cái class CameraControler ở đâu ra thế này .

    Đây đây.
    CameraControler.h
    C++ Code:
    1. #ifndef _CameraControler_H_
    2. #define _CameraControler_H_
    3.  
    4. #include <OIS/OIS.h>
    5. #include <Ogre.h>
    6.  
    7. class CameraControler: public OIS::MouseListener, public OIS::KeyListener, public Ogre::FrameListener
    8. {
    9. public:
    10.     CameraControler(OIS::Keyboard* Keyboard, OIS::Mouse* Mouse, Ogre::Root* Root, Ogre::Camera* Camera);
    11. protected:
    12.     bool mouseMoved(const OIS::MouseEvent &arg);
    13.     bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID ID);
    14.     bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID ID);
    15.  
    16.     bool keyPressed(const OIS::KeyEvent &arg);
    17.     bool keyReleased(const OIS::KeyEvent &arg);
    18.  
    19.     bool frameStarted(const Ogre::FrameEvent &evt);
    20. private:
    21.     OIS::Keyboard* Keyboard;
    22.     OIS::Mouse* Mouse;
    23.  
    24. };
    25.  
    26. #endif

    Nếu chịu khó nhìn chút thì cũng chả có gì khó hiểu phải không . MouseListener với KeyListener về bản chất cũng từa tựa FrameListener.

    CameraControler.cpp
    C++ Code:
    1. #include "CameraControler.h"
    2.  
    3. CameraControler::CameraControler(OIS::Keyboard* Keyboard, OIS::Mouse* Mouse, Ogre::Root* Root, Ogre::Camera* Camera)
    4. {
    5.     this->Keyboard = Keyboard;
    6.     this->Mouse = Mouse;
    7.  
    8.     Keyboard->setEventCallback(this);
    9.     Mouse->setEventCallback(this);
    10.     Root->addFrameListener(this);
    11. }
    12.  
    13. bool CameraControler::mouseMoved(const OIS::MouseEvent &arg)
    14. {
    15.     return true;
    16. }
    17. bool CameraControler::mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID ID)
    18. {
    19.     return true;
    20. }
    21. bool CameraControler::mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID ID)
    22. {
    23.     return true;
    24. }
    25.  
    26. bool CameraControler::keyPressed(const OIS::KeyEvent &arg)
    27. {
    28.     return true;
    29. }
    30. bool CameraControler::keyReleased(const OIS::KeyEvent &arg)
    31. {
    32.     return true;
    33. }
    34.  
    35. bool CameraControler::frameStarted(const Ogre::FrameEvent &evt)
    36. {
    37.     return true;
    38. }

    Bây giờ, để coi nào. Bắn CS nó thế nào ấy nhỉ. À, khi mouse "di chuyển" thì camera xoay.
    C++ Code:
    1. bool CameraControler::mouseMoved(const OIS::MouseEvent &arg)
    2. {
    3.     Camera->pitch(Ogre::Radian(Ogre::Degree(-arg.state.Y.rel)));//!pitch thì quay quanh Z.
    4.     Camera->yaw(Ogre::Radian(Ogre::Degree(-arg.state.X.rel)));//!yaw xoay node quanh trục y của chính nó. Local Y-Axis, còn tại sao arg.state.X.rel âm. :) vì thế xoay nó mới thuận. Không quay mouse sang trái mà camera sang phải thì buồn cười.
    5.     return true;
    6. }

    Run đi nào .


    Quá đã!, dễ hơn cả ăn cháo, ngĩ gì, code nấy . Bây giờ tiếp.

    À, khi ấn WASD thì nó thế nào ấy nhỉ?.

    C++ Code:
    1. bool CameraControler::frameStarted(const Ogre::FrameEvent &evt)
    2. {
    3.     float speed = 100;//!100 đơn vị trên giây.
    4.  
    5.     if(Keyboard->isKeyDown(OIS::KeyCode::KC_A))
    6.     {
    7.         Camera->moveRelative(Ogre::Vector3(-speed, 0, 0)*evt.timeSinceLastFrame);
    8.     }
    9.     if(Keyboard->isKeyDown(OIS::KeyCode::KC_D))
    10.     {
    11.         Camera->moveRelative(Ogre::Vector3(speed, 0, 0)*evt.timeSinceLastFrame);
    12.     }
    13.     if(Keyboard->isKeyDown(OIS::KeyCode::KC_W))
    14.     {
    15.         Camera->moveRelative(Ogre::Vector3(0, 0, -speed)*evt.timeSinceLastFrame);
    16.     }
    17.     if(Keyboard->isKeyDown(OIS::KeyCode::KC_S))
    18.     {
    19.         Camera->moveRelative(Ogre::Vector3(0, 0, speed)*evt.timeSinceLastFrame);
    20.     }
    21.     return true;
    22. }
    moveRelative? Di chuyển tương đối ạ . Build cái build cái.

    À, nếu có thấy camera xoay nhanh quá thì giảm cái hệ số của nó đi nhá. VD.
    C++ Code:
    1. Camera->pitch(Ogre::Radian(Ogre::Degree(-0.5*arg.state.Y.rel)));//!pitch thì quay quanh Z.
    2.     Camera->yaw(Ogre::Radian(Ogre::Degree(-0.5*arg.state.X.rel)));//!yaw xoay node quanh trục y của chính nó. Local Y-Axis, còn tại sao arg.state.X.rel âm. :D vì thế xoay nó mới thuận.

    Phần tiếp theo là GUI.

    Hô hô check được hơn 70mb rồi .
    Attached Files Attached Files
    Đã được chỉnh sửa lần cuối bởi NamVoDang : 30-09-2008 lúc 03:59 PM.
    Phá toái hư không - Bạch nhật thăng thiên.

  9. #9
    Ngày gia nhập
    10 2006
    Nơi ở
    In Your Bugs
    Bài viết
    823

    Xin lỗi vì spam

    @ NVD: Cố lên Võ Đang, Kid đang cố dịch directX, kill nó xong sẽ vọc Orge Hi vọng những bài viết của NVD hôm nay, sẽ là tiền đề cho rất nhiều người mai sau.

  10. #10
    Ngày gia nhập
    02 2012
    Bài viết
    1

    anh NamVoDanh ơi anh có tài liệu nào về ogre ko anh shear lại cho em vói link kia die rồi. thank a nhiều

Các đề tài tương tự

  1. Lập trình Game trên C++ | Game engine programming
    Gửi bởi hpcloud22 trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 3
    Bài viết cuối: 19-02-2013, 11:13 PM
  2. Gamelof tổ chức ngày hội việc làm cho Graphic Artist (2D/3D) và Game Designer
    Gửi bởi vntaster trong diễn đàn Tuyển dụng - Việc làm CNTT
    Trả lời: 3
    Bài viết cuối: 15-10-2010, 02:36 PM
  3. Lập trình engine game Unreal 3
    Gửi bởi chuong01 trong diễn đàn Giải trí - Thư giãn
    Trả lời: 5
    Bài viết cuối: 25-08-2010, 12:35 AM
  4. Giới thiệu Irrlicht - 3D Game Engine mã nguồn mở
    Gửi bởi huytd trong diễn đàn Tutorials và Thủ thuật Visual C++
    Trả lời: 0
    Bài viết cuối: 27-09-2007, 06:36 AM
  5. [C# + XNA] 2D XNA Game Engine của nhóm VGroup
    Gửi bởi huytd trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 4
    Bài viết cuối: 21-05-2007, 07:20 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn