(C++) HOW TO: use .irr scene + a game manager Class

A forum to store posts deemed exceptionally wise and useful
Athlon_Jedi
Posts: 156
Joined: Wed Jul 21, 2004 4:29 am
Location: Mishawaka, In

(C++) HOW TO: use .irr scene + a game manager Class

Post by Athlon_Jedi »

Ok guys , I have been using IrrEdit in my project and im sure more of you would love to know how you can do this with a game manager in your project and still load scene data generated by IrrEdit and display it as you would with out it.

so having found the solution by trying various methods I have come upon a solution that works perfectly for this .

This is my first How To and I have tested this throughly in my project and so far it works perfectly, but as with most things in development resaults may vary depending on your OS , Complier and Compiler options . this example compiles and runs under Visual studio 2003 under windows server 2003 and should be fine under XP as well.

Right so off we go.

Step 1 - Create your meshes in 3dsmax or similar modeling program and import them into IrrEdit , then arrange your scene, lightmap, and save as a .irr file. this is the easy part lol

now to the code.


the first thing we want to do is tell the engine we want the game manager to be responsible for creating the Irrlicht device and that we want all of our functionality to be availibe via this game manager so we create a class for the game manger that will contain poiners to all the stuff we want to use easyly with out haveing to explicitly call the functions in our code over and over each time we want to use them.

so create a new file and make sure it is of type .h ( right click your project->add new item->somename.h->open.)

i call mine core.h but you may name it what ever you feel is apropreate.

now on to the class

the first thing to do is tell the compiler we want to include this file at compile time sooo..........


Code: Select all


#ifndef _CORE_H_ 
#define _CORE_H_ 

these preprocessor directives accomplish this.

now since we want all the engine fuctionality availible to the class, what would we put in there next ?

breif pause for thinking.........

well we need the namespaces irrlicht uses right ?


Code: Select all


//engine namespaces 
using namespace irr; 
using namespace core; 
using namespace scene; 
using namespace video; 
using namespace io; 
using namespace gui; 

Wait, Stop you say, what about other classes and fuctions we may have in our code?

well in between the preprocessor directives and the namspace list you can forward declare those classes but that is beyond the scope of this how to

ok so now we have our directives and our namspaces time to start the class.!!!

now since the goal of this class is to make our coding much simpler and shorter what we do next is to create the pointers we need that point back to all our standard Irrlicht functions like so.


Code: Select all


class CGameCore   //here we define the class and create our poiners
{ 
public: 
   //functions providing acess to engine componants. 
  
   //GUI Environment 
    IGUIEnvironment* getGUIEnv(); 

   //Scene Manager 
   ISceneManager* getSceneMngr(); 

   //video driver 
   IVideoDriver* getVideo(); 

   //Engine core device 
   IrrlichtDevice* getDevice(); 
    
   //constructor 
   CGameCore(); 

   //destructor 
   virtual ~CGameCore(); 


private: 

   //used to insanianate device 
   void InitalizeDevice(); 

   //corisponding pointers to engine core functions 
   IrrlichtDevice* pDevice; 
   IVideoDriver* pDrv; 
   ISceneManager* pSceneMngr; 
   IGUIEnvironment* pGUIEnv; 
}; 

#endif 


and that finishes the basic class definition, keep in mind we can add pointers for what ever we want to use easyly here, this will get ya started though.

ok now we need a source file to use these pointers in and to create the game manager object, initialize it and finaly keep track of everthing .


core.cpp

Code: Select all


#include "core.h" 
#include <iostream> 



//constructor 
CGameCore::CGameCore() 
{ 
   InitalizeDevice(); 
   std::cout<<"Game Manager Created !\n"; 
} 

//Default Constructor 
CGameCore::~CGameCore() 
{ 
   std::cout<<"Game Manager Shut Down!!\n"; 
} 

/* in thefuntion below we have 2 device types one that uses a directx  
    device with decent resolution settings and one using OpenGL with
    minimal settings set up in an if statment. one cool thing about 
    doing ot this way is that if you have another app running that
    wont release the directx driver, the game manager object
    will automagicly use the openGL device instead and tell you
    that its using it if you have a console app or a drop down style
    console in your app ( quake style ) */
  
void CGameCore::InitalizeDevice() 
{ 
   pDevice = createDevice(EDT_DIRECT3D9, core::dimension2d<s32>(1024,768), 32, true, true, true); 
   std::cout<<"Device Creation Success !!\n";

   //if above fails, use minimal config below 
   if(pDevice==NULL) 
      pDevice = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(1024,768),32,false,false,false); 
  std::cout<<"Warning : Minimal Device Config In Use !!\n";


   //Init engine functions and store the pointers to them 
   pSceneMngr = pDevice->getSceneManager(); 
   pDrv = pDevice->getVideoDriver(); 
   pGUIEnv = pDevice->getGUIEnvironment(); 

    //load scene using our pointer we made for the scene manager
    pSceneMngr->loadScene("G:/ada1/ada1/debug/maps/home.irr"); 
	std::cout<<" Scene 1 Loaded......\n";

/* one thing to note about Irredit is the fact that once the scene file
    gets written out , upon loading it into the engine , you have to access
    the nodes you want to work with by name, Id, or type, the commented  
    line below accesses the scene node named "home" by casting it as an
    animated mesh scene node, then returning the name of the node 
    in question via getSceneNodeByName() then we can use the returned 
    node we cast it as to change material flag settings and the like. */
 
//IAnimatedMeshSceneNode* hnode = (IAnimatedMeshSceneNode*)pSceneMngr->getSceneNodeFromName("home");

//here we use the node name we casted above to change material flags 
//hnode->setMaterialFlag(video::EMF_LIGHTING, false);



	//add a light
	scene::ISceneNode* lnode = 0;
	lnode = pSceneMngr->addLightSceneNode(0, core::vector3df(200.0f,0,0));


	//camera scene node
	scene::ICameraSceneNode* player = pSceneMngr->addCameraSceneNodeFPS(0,100.0f,300.0f);
	player->setPosition(core::vector3df(695.0f,119.0f,275.0f));
        
	//disable mouse pointer
    pDevice->getCursorControl()->setVisible(false);
	std::cout<<"Mouse Pointer Disabled\n";
} 


      //return a funtion to engine core fuctions here 
      IrrlichtDevice* CGameCore::getDevice() 
   { 
      return pDevice; 
   } 
  
      // GUI 
   IGUIEnvironment* CGameCore::getGUIEnv() 
   { 
      return pGUIEnv; 
   } 

   //Video 
   IVideoDriver* CGameCore::getVideo() 
   { 
      return pDrv; 
   } 

   //Scene Manager 
   ISceneManager* CGameCore::getSceneMngr() 
   { 
      return pSceneMngr; 
   } 



ok one more important thing to add is that if you use the Editor to add a camera, you must also add a camera scene node for it in your code in the EXACT and i do mean EXACT same position you put it in the editor, otherwise, the camera no matter what type of camera it may be will be static , you will be able to see your scene but not move the camera.....at all. also handy to have , you notice couts after each important fuction is either successful or fails , this can help you determine where your code starts misbehaving if something goes awry ( thank you to Vitek for that sugestion :wink: )

ok now that we have our game manager class and our implementation, we need our main function and you guessed it , entry point that tells the app where to start excuting code.

so main.cpp looks like this

Code: Select all


#include <irrlicht.h>
#include <iostream>

//new classes
#include "core.h"
#include "Game.h"



using namespace irr;

#pragma comment(lib, "Irrlicht.lib")

//this will disable the console window on startup when implemented
//#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup") 



int main()
{

	CGame game;
	game.run();

}

But WAIT we dont have a CGame class or a run() fuction yet!!! well as you may have guessed, we create that next like so


game.h

Code: Select all


#ifndef _GAME_H_ 
#define _GAME_H_ 


#include <irrlicht.h> 
#include "core.h" 

using namespace irr; 

//! Main entry point to game 
class CGame 
{ 
public: 

   CGame(); 

   bool run(); 

private: 
    
   CGameCore pManager; 
}; 
#endif
 
now basicly all this class does is tells the app "ok there is a run function, its a boolian value ( true or false) and this fuction can only be accessed by ............ " yep you guessed it , the game manager because we want only the game manager to start the engine and thus the app so we can keep track of things and make our life easyer. :)

but wait , no where do we have a draw loop as of yet so how can we see our scene in action and doesnt that defeat the purpose of all this nifty stuff?

no, in the implementation for Game.cpp we will put our nifty pointers to work for us like this:

game.cpp

Code: Select all


#include "Game.h" 
#include "core.h"

CGame::CGame() 
{ 
} 

//! Main game loop 
bool CGame::run() 
{ 
   IrrlichtDevice* pDevice = 0; 
   IVideoDriver* pDrv = 0; 
   ISceneManager* pSceneMngr = 0; 
   IGUIEnvironment* pGUIEnv = 0; 

// Name of game, displayed in window if windowed 
pManager.getDevice()->setWindowCaption(L"some app name here"); 
   
int lastFPS = -1; //<-----doesnt work because there is no code to display   
                        // fps in this example but needed to compile sucessfuly
  
// Keep running game loop if device exists 
   while(pManager.getDevice()->run()) 
      {
	   pManager.getVideo()->beginScene(true,true, SColor(255, 100, 101, 140));
       pManager.getSceneMngr()->drawAll();
	   pManager.getGUIEnv()->drawAll();
	   pManager.getVideo()->endScene();
    } 
   
   {
   pManager.getDevice()->drop(); 
}
    
   return 0; 
} 

and there ya have it, an example of not only how to use a .irr scene file generated by IrrEdit as per a request in the IrrEdit forum but how to implement a game manager using it as well see not so bad was it?

thankx to Vitek for his help whilst tying to figure this stuff out and to the Guy that wrote the tutorial on how to add a game manager to use with irrlicht in which my game manager code is based on( lol cant remember your name ) as well as Niko for the excellent engine and editor and anyone else that answered my sometimes dingy posts i may have missed :lol: :lol:

please feel free to use this in your projects and modify it as needed:)
noreg
Posts: 158
Joined: Fri Jun 23, 2006 6:01 pm
Location: continental europe

Post by noreg »

:?: :?: :?: What does this do? What do you mean with "game manager"? Why do i need this? Is there any problem using Irredit without your confusing explanation?
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

noreg wrote::?: :?: :?: What does this do? What do you mean with "game manager"? Why do i need this? Is there any problem using Irredit without your confusing explanation?
What the hells your problem dude, Hes only trying to help...

Nice tut Jedi :D This would be helpful for noobs that wanna keep their games nice and Object Orientated. I am guilty of just doing it like the examples and sometimes I even use quite a bit of global pointers :oops: So maybe this will get people starting in the right track so they do not develop bad habits :)

PS: I didnt read this but a glance shows that he is accesing all his device pointers using a class which is the best idea offcourse. Why did you need "in lastfps = -1" to compile?! I dont see it referenced anywhere in your code...
noreg
Posts: 158
Joined: Fri Jun 23, 2006 6:01 pm
Location: continental europe

Post by noreg »

Yeah, bash the newbs if they ask "stupid" questions, instead of helping them. They only disturb anyway. Rather spend your time helping some pros. This way you get a faster return. You´re doin´alright man.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

You did not only ask a stupid question you asked a stupid question in an offensive manner to someone who is only trying to help. And noone was bashing you, I merely asked why you would act like that. Don't hide behind the word "newb". You are just an idiot my friend.
noreg
Posts: 158
Joined: Fri Jun 23, 2006 6:01 pm
Location: continental europe

Post by noreg »

Not your friend. WHO is offensive and uses pejoratives? How old are you? :lol: But we should not be taking everything that serious. Joke: How do you call a Kiwi with a thousand girl friends?
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Haha all good mate...PM me the answer to that joke eh :P

PS: I hope you read that tutorial it shows good programming practice. Most new people would just lump everything in one CPP file for their projects, but this shows you how to utilize headers, includes and classes for an optimum object orientated enviroment. Object orientated programming is essential for C++, it keeps it thread safe (Which is slightly pointless since irrlicht itself isnt) but most importantly is just more professional overall because if you dont use it its practically just plain C. It is not really something very hard, but might be useful to see for new people because it provides a better framework than the examples to base their project on.

Oh yeah i guessed the answer is "a farmer" :D

Sadly I am not a farmer :P

PPS: Is this not a pejorative?:
Is there any problem using Irredit without your confusing explanation?
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

OOP [Object Oriented Programming] has nothing to do with thread safety. You can write thread safe or unsafe code with or without OOP.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Yes you are right Enet is written in pure C and it is somewhat thread safe. I forgot...
KG
Posts: 35
Joined: Wed Jun 07, 2006 12:00 am

Post by KG »

A few questions about your methods since I'm curious about different styles of programming.

1. What is the purpose of having the main loop inside a class rather than the main() function?

2. Is there anything wrong with making pointers to the Irrlicht objects globals? I know people say to avoid using globals wherever possible, but is there anything bad that can happen with using them, even extremely sparingly and carefully?
Athlon_Jedi
Posts: 156
Joined: Wed Jul 21, 2004 4:29 am
Location: Mishawaka, In

for KG

Post by Athlon_Jedi »

answer to question 1:

having the main function inside a class as is done here does a few good things for you.

1st it makes your main function as light as possible.

2d , by using a game manager class , it gives you more control over the way the code is executed as far as what gets done and when and allows for easyer asset management which as your app grows can become a pain in the Arse with out it.

mainly because using the pointer system allows you to access anything loaded into the game manager simply by calling the fuctions assosiated with the pointer by casting the pointer name so instead of something like:

Code: Select all


ICameraSceneNode* cam = 0;
cam = smgr->createCameraSceneNodeFPS(.......);
yada yada(somestuff in here);
cam->setPosition(core::vector3df(whereeveryouwantthecamera);

say if you had a camera defined in the header for the game manager that has all your settings set in it already, and a function to call defined , the above turns into:

Code: Select all


pCam.CreateCam(position);

anywhere in your code that you need a camera, and you could even go so far as to define different types of cameras as well as thier default attrubutes, and the associated functions to create them and change 4-5 lines of code into 1 line simply by calling the pointer for the cam you want.

also useing classes in this manner makes it ALOT easyer to find misbehaving code and helps with engine overhead a bit.


question 2:

you can mix global and local pointers BUT you have to be carful, Some global pointers depending on how they are defined , would over ride local definitions making whole sections of code malfuntion and cause all kinds of headaches.

@BlindSide Thank you for commenting on this tut, I wrote it with the aim of making things a bit easyer for C++ noobs in general as well as demonstrate to beginners that IrrEdit scenes acculy are not as difficult as most may think to use with the engine :wink: and to demonstrate propercoding style (well for the most part) :lol:

also I have no idea why the int lastFPS -1;

is needed to compile it with out errors, if it works with out it on someone elses system , more than likely something i have set differently in Visual Studio, my system just being a pain that day, too much beer that day, lol no idea mate.

I am glad to know everthing is proper with it though, wasnt quite 100 % sure lol

more than likely i am going to expand on it when i get more classes added and fuctioning correctly , atm im working on a skillmamagement system with gui elements to display skill progress, how many skills you have, what level they are at , and so on and display it in a gui system. and once again using the game manager as the parent object to load the skill manager. as of yet the skills load but i have not finished the gui for it yet so there is no way to tell what they are doing lol.
n00b
Posts: 58
Joined: Tue Sep 05, 2006 3:00 pm
Location: Earth
Contact:

Post by n00b »

This method is similar to the IrrWizard framework.

Btw, i'm looking forward to your skillmamagement system.
Hope to see it soon.
waldo
Posts: 10
Joined: Wed Oct 03, 2007 9:08 pm
Location: Amsterdam

Post by waldo »

Sorry to bump this thread...

Just tried to compile the code above and it game me a new record of errors. 50 of them! And CB told me there were more and should set the max errors in the config :lol:
It was my compiler not set up in the right way...

Then, it still gave me 30 errors. In the first three lines something quite important was left out: In core.h there should be the line

Code: Select all

#include <irrlicht.h>
somewhere around the engine namespaces. It compiles now, however there are still six unused variables left, but they only give warnings, no errors...
If I stop living, does the world stop turning? Everyone will know, except me...

I love signatures, it's like space reserved for bullshi :)
Zenon
Posts: 3
Joined: Thu Oct 11, 2007 7:47 am

Post by Zenon »

hi,

while trying to copy your design for my app i ran into a problem;
this is what it looks like at the moment;

the MainGame header:

Code: Select all

#include <irrlicht.h>
#include "Core.h"
#include "EventReceiver.h"

namespace NS {
    class MainGame{
        public:
            MainGame();
            ~MainGame();
            void run();
        protected:
            Core* manager;
            EventReceiver* eventReceiver;
    };
}
the eventreceiver header:

Code: Select all

#include <irrlicht.h>
#include "Core.h"

namespace NS {
    class EventReceiver : public IEventReceiver {
        public:
            EventReceiver( Core* man );
            ~EventReceiver();
            virtual bool OnEvent( SEvent event );
        protected:
            Core* manager;
            IGUIEnvironment* guiEnvironment;

    };
}
and the core header:

Code: Select all

#include <irrlicht.h>

namespace NS {
    class Core {
        public:
            Core();
            ~Core();
            IrrlichtDevice* getDevice();
            IVideoDriver* getDriver();
            ISceneManager* getSceneManager();
            void registerEventReceiver( IEventReceiver* rcv );
            void closeDevice();
        protected:
            IrrlichtDevice* device;
            ISceneManager* smgr;
            IVideoDriver* driver;
    };
}
when compiling, i get a 'redefinition of class Core' error in the core header file;
i guess its because the MainGame header includes the core and the eventreceiver header, which in turn includes the core header again;
can anybody help me fix this while keeping pointers to the core object in both the MainGame and the EventReceiver;
monkeycracks
Posts: 1029
Joined: Thu Apr 06, 2006 12:45 am
Location: Tennesee, USA
Contact:

Post by monkeycracks »

before coreclass

#ifndef _CORE_CLASS_
#define _CORE_CLASS_

after coreclass

#endif
Post Reply