A quick overview of the basic setup

Published September 06, 2016
Advertisement

Ok, in this post I will go quickly over gameApp.cpp and .h. This is the main game entry and that is where the main game loop sits.

Lets first look at the header file:[code=:0]namespace GAME {class GameApp;extern GameApp app;class GameApp : public irr::IEventReceiver{public:enum SceneState{CM_NORMAL = 0,CM_UNLOAD,CM_LOAD,CM_UNLOADANDLOAD,CM_NEWGAME};GameApp(): m_loadFile(""), m_sceneState(CM_NORMAL), m_newGameLoad(true){}bool Init();void Done();int Run();irr::IrrlichtDevice* GetDevice() { return m_device;}irr::video::IVideoDriver* GetDriver() { return m_driver;}irr::gui::IGUIEnvironment* GetUIEnv() { return m_ui_env;}irr::scene::ISceneManager* GetSceneManager() { return m_smgr;}CameraAnimator* GetCameraAnimator() { return m_cameraAnim;}Camera* GetCamera() { return m_cmr;}DebugText* GetDebugText() { return m_debugText;}void AddEventReceiver(irr::IEventReceiver* er);void RemoveEventReceiver(irr::IEventReceiver* er);void NewGame();void SaveGame(char* name);void LoadGame(char* name);void HandleCollisions();protected:typedef std::vector EventReceivers;irr::IrrlichtDevice* m_device;irr::video::IVideoDriver* m_driver;irr::gui::IGUIEnvironment* m_ui_env;irr::scene::ISceneManager* m_smgr;CameraAnimator* m_cameraAnim;Camera* m_cmr;EventReceivers m_eventReceivers;DebugText* m_debugText;DebugGrid* m_debugGrid;bool m_newGameLoad;bool OnEvent(const irr::SEvent& event);private:void DoLoadGame();SceneState m_sceneState;StringId m_loadFile;};} // namespace GAME


As you can see this class keeps all of the major components - IrrlichtDevice, IVideoDriver, IGUIEnvironment, ISceneManager. This is all needed to setup an empty irrLitch scene. gameApp creates them, sets them up and then allows other object to access them. Also I create camera and camera animator in there.

Main functions are of course Init(), Done() and Run(). There other functions but they are empty for now. GameApp also inherits irr::IEventReceiver and can handle input, but that too is for future use.

Lets take a look at two interesting functions. First Init():[code=:0] bool GameApp::Init() { //preferencies registration and installation Spark::Options::Register("Client preferences") ("video.mode", Spark::Options::Preference(&preferences.screenRect), "screen rect") ("video.windowed", Spark::Options::Preference(&preferences.windowed), "windowed or full screen") ("audio.soundVolume", Spark::Options::Preference(&preferences.soundVolume), "sound volume") ("audio.musicVolume", Spark::Options::Preference(&preferences.musicVolume), "music volume") ("audio.sound", Spark::Options::Preference(&preferences.sound), "sound") ("audio.music", Spark::Options::Preference(&preferences.music), "music") ("avatar.name", Spark::Options::Preference(&preferences.name), "avatar nickname") ("network.ServerIp", Spark::Options::Preference(&preferences.address), "master server address") ("debug.bullet", Spark::Options::Preference(&preferences.bullet), "show bullet debug") ; Options::SetRT("app.title", "Space Adventures"); Options::SetRT("file.mount", "path:data ra", -1); // parse options Spark::Options::Init(GetCommandLine(), "SA", "game.ini"); // initialize log system Spark::Log::Init(); // log banner SLOG_BANNER << "application: " << "Space Adventures"; char time_buffer[32]; struct _timeb t; _ftime(&t); tm details; details = *localtime(&t.time); sprintf(time_buffer, "%02d/%02d/%04d %02d:%02d:%02d.%03hu", details.tm_mon+1, details.tm_mday, details.tm_year+1900, details.tm_hour, details.tm_min, details.tm_sec, t.millitm); SLOG_BANNER << "date : " << time_buffer; OSVERSIONINFO ver; ver.dwOSVersionInfoSize = sizeof(ver); GetVersionEx(&ver); SLOG_BANNER << "host : Windows " << ver.dwMajorVersion << '.' << ver.dwMinorVersion << '.' << ver.dwBuildNumber; MEMORYSTATUS mem; GlobalMemoryStatus(&mem); SLOG_BANNER << "memory : " << mem.dwTotalPhys/1024 << "K total, " << mem.dwAvailPhys/1024 << "K free"; // Create Irrlicht devise Spark::VideoMode videoMode = Spark::Options::GetValue("video.mode"); irr::SIrrlichtCreationParameters cp; cp.DriverType = (irr::video::E_DRIVER_TYPE)Options::GetValue("video.driver", irr::video::EDT_DIRECT3D9); cp.Fullscreen = !Spark::Options::GetValue("video.windowed", true); cp.WindowSize = irr::core::dimension2d(videoMode.width, videoMode.height); cp.Bits = (irr::u8)videoMode.bpp; cp.EventReceiver = this; m_device = irr::createDeviceEx(cp); if(!m_device) { SLOGS_ERR(app, ("Cannot create Irrlicht device: driver type = %d", cp.DriverType)); return false; } m_driver = m_device->getVideoDriver(); if(!m_driver) { SLOGS_ERR(app, ("Invalid video driver %d", cp.DriverType)); return false; } m_device->setWindowCaption(L"Space Adventures"); m_device->setEventReceiver(this); m_ui_env = m_device->getGUIEnvironment(); //add all data folders m_smgr = m_device->getSceneManager(); m_smgr->getFileSystem()->addFolderFileArchive("data/"); m_smgr->getFileSystem()->addFolderFileArchive("data/meshes"); m_smgr->getFileSystem()->addFolderFileArchive("data/fonts"); m_smgr->getFileSystem()->addFolderFileArchive("data/pfx"); m_smgr->getFileSystem()->addFolderFileArchive("data/sprites"); //add a basic lightning to the scene m_smgr->addLightSceneNode(0, core::vector3df(200,200,200), video::SColorf(1.0f,1.0f,1.0f),2000); m_smgr->setAmbientLight(video::SColorf(0.1f,0.3f,0.3f)); m_cmr = new Camera(m_smgr->getRootSceneNode(), m_smgr, -1); m_smgr->setActiveCamera(m_cmr); m_cmr->setTarget(core::vector3df(0,0,0)); m_cmr->setPosition(core::vector3df(3,3,3)); m_cmr->setFarValue(42000.0f); m_cmr->setNearValue(0.5f); m_cmr->setFOV(core::PI*0.25f); m_cameraAnim = new CameraAnimator(m_device->getCursorControl(), 10.0f, 10.0f, 10.0f); m_cmr->addAnimator(m_cameraAnim); m_device->getCursorControl()->setVisible(false); m_debugGrid = new DebugGrid(0.0f, 50, 1.0f, SColor(255,128,128,128), m_smgr->getRootSceneNode(), m_smgr, -2); if(!EntityDB::Ref().LoadResources("entities")) { SLOGS_ERR(app, ("Cannot load entities DB")); return false; } // new game NewGame(); //--------DEBUG CONSOLE STUFF--------------- m_debugText = new DebugText(); //--------DEBUG CONSOLE STUFF--------------- return true; }


As you can see, beside creating every major component, it also reads game.ini and handles all of the options. Options are handled by Spark::Options, which is just a nifty little class. I think the whole function is quite self descriptive, just tons of inits. Also all the logs are handled by Spark too. It is quite flexible logging system, with many levels and targets for log.

Init() also adds some simple light to the scene:[code=:0]m_smgr->addLightSceneNode(0, core::vector3df(200,200,200), video::SColorf(1.0f,1.0f,1.0f),2000);m_smgr->setAmbientLight(video::SColorf(0.1f,0.3f,0.3f));


I think in future I will make it data driven for each sector, so light can actually come from a star or some other source.

Also you can see the data structure for the project:[code=:0]m_smgr->getFileSystem()->addFolderFileArchive("data/");m_smgr->getFileSystem()->addFolderFileArchive("data/meshes");m_smgr->getFileSystem()->addFolderFileArchive("data/fonts");m_smgr->getFileSystem()->addFolderFileArchive("data/pfx");m_smgr->getFileSystem()->addFolderFileArchive("data/sprites");


I think I might move materials out of "data/meshes", but for now, when I barely got any objects, that should suffice.[code=:0]m_debugGrid = new DebugGrid(0.0f, 50, 1.0f, SColor(255,128,128,128), m_smgr->getRootSceneNode(), m_smgr, -2);
DebugGrid is a debug class that draws a infinite grid over x,y plane. It is used to better see positioning of object in the space.

Now onto Run() function:[code=:0]int GameApp::Run(){scene::ICameraSceneNode* fixedCam = m_smgr->addCameraSceneNode(m_smgr->getRootSceneNode(), core::vector3df(0,50,0),core::vector3df(0,0,0));int lastFPS = -1;while(m_device->run() && m_driver){// renderif (m_device->isWindowActive()){Time::Update();switch(m_sceneState){case CM_NORMAL:EntityManager::Ref().Update(Time::GetElapsedTime());break;case CM_UNLOAD:EntityManager::Ref().Deactivate();m_sceneState = CM_NORMAL;break;case CM_UNLOADANDLOAD:EntityManager::Ref().Deactivate();EntityManager::Ref().Clear();DoLoadGame();m_sceneState = CM_NORMAL;break;}m_driver->beginScene(true, true, irr::video::SColor(0,100,100,200));////TEST MAP RENDER// set render target texture// make cube invisible and set fixed camera as active cameram_smgr->setActiveCamera(fixedCam);// set back old render target// The buffer might have been distorted, so clear itm_driver->setRenderTarget(0, true, true, 0);// make the cube visible and set the user controlled camera as active onem_smgr->setActiveCamera(m_cmr);////TEST MAP RENDERm_smgr->drawAll();if(m_sceneState == CM_NORMAL){HandleCollisions();}//draw a orientation triangle at 0,0 ,0 coordsm_driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);video::SMaterial m;m.Lighting = false;m_driver->setMaterial(m);m_driver->draw3DLine(core::vector3df(0,0,0), core::vector3df(5,0,0), video::SColor(255,255,0,0));m_driver->draw3DLine(core::vector3df(0,0,0), core::vector3df(0,5,0), video::SColor(255,0,255,0));m_driver->draw3DLine(core::vector3df(0,0,0), core::vector3df(0,0,5), video::SColor(255,0,0,255));m_driver->draw3DLine(core::vector3df(0,5,0), core::vector3df(5,0,0), video::SColor(255,255,255,255));m_driver->draw3DLine(core::vector3df(0,0,5), core::vector3df(0,5,0), video::SColor(255,255,255,255));m_driver->draw3DLine(core::vector3df(5,0,0), core::vector3df(0,0,5), video::SColor(255,255,255,255));m_ui_env->drawAll();m_driver->endScene();int fps = m_driver->getFPS();if (lastFPS != fps){core::stringw str = L"Space Adventures [";str += m_driver->getName();str += "] FPS:";str += fps;m_device->setWindowCaption(str.c_str());lastFPS = fps;m_debugText->SetText(str.c_str());}}}return 0;}


Inside of the While loop we got a small state machine that switches between scene states - normal, unload, and unloadandload (I think that should just be called reload).

Then there is this:[code=:0]m_driver->draw3DLine(core::vector3df(0,0,0), core::vector3df(5,0,0), video::SColor(255,255,0,0));m_driver->draw3DLine(core::vector3df(0,0,0), core::vector3df(0,5,0), video::SColor(255,0,255,0));m_driver->draw3DLine(core::vector3df(0,0,0), core::vector3df(0,0,5), video::SColor(255,0,0,255));m_driver->draw3DLine(core::vector3df(0,5,0), core::vector3df(5,0,0), video::SColor(255,255,255,255));m_driver->draw3DLine(core::vector3df(0,0,5), core::vector3df(0,5,0), video::SColor(255,255,255,255));m_driver->draw3DLine(core::vector3df(5,0,0), core::vector3df(0,0,5), video::SColor(255,255,255,255));


This is a cool trick to see the orientation of a scene. Again can be used for positioning and sorting out loading objects after exporting them from graphical editors or simply to see the origin of the scene. Each line is color coded to see where is x,y,z points to.

The last bit is a simple fps counter, which is very important when you hacking stuff up. Always make sure that you hit your FPS cap! If you do not, it is time to investigate and optimize![code=:0]if (lastFPS != fps){core::stringw str = L"Space Adventures [";str += m_driver->getName();str += "] FPS:";str += fps;m_device->setWindowCaption(str.c_str());lastFPS = fps;m_debugText->SetText(str.c_str());}


I think I covered everything worth covering. I am still working out how to do these posts in an interesting way. I will try to cover other interesting bits separately and in more depth. In the next post I will take a look at graphics editors I want to use for this project. Currently there are two but I will settle for one.

And here is a screenshot of an empty scene! That what those Init() and Run() do right now!

first_Scene.png

Previous Entry Just a quick test!
1 likes 2 comments

Comments

evolutional

If you use the code tags instead of quotes, the journal system will give you nice syntax highlighting for your code :)

September 19, 2016 06:48 PM
Bigdogco

Thanks, I will try it!

September 20, 2016 04:18 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement