OOP Game Structure [solved]

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
klikmaster
Posts: 40
Joined: Mon Sep 11, 2006 1:06 pm

OOP Game Structure [solved]

Post by klikmaster »

Hey guys,

I need a little help on how to go about structuring a new project. I am familiar with how to go about doing things object-oriented, however I don't have much experience with working with libraries/engines.

In a new project I am likely to create classes for my main character and level objects, and I am tempted to define ISceneNodes here so that each object can have it's mesh/texture all set up. But to do this my game objects would have to access parts of the system like the Irrlicht SceneManager which would be in a class much higher up in the hierarchy, and it just seems a bit messy and tightly coupled.

I ask this because when I start including other libraries like a physics engine, audio engine etc. it would be nice to keep everything as loosely coupled as possible so objects only rely on objects lower in the hierarchy and I can avoid problems like having dependancies all over the place.

I'd appreciate if someone can tell me if I'm thinking the right way and assist me with a solution, or feel free to tell me I'm thinking the wrong way! Thanks in advance x
Last edited by klikmaster on Sun Jun 22, 2008 12:14 am, edited 1 time in total.
~IRRLICHT ROX MY SOX~
XXChester
Posts: 95
Joined: Thu Oct 04, 2007 5:41 pm
Location: Ontario, Canada

Post by XXChester »

Hello,
The way I do it, and I am not sure if it is "correct" is I pass a reference to my Irrlicht Device to the classes that require it (basically all of them). This is in C# but it is easily ported to C++.

Here is an example of a class I would write;

Code: Select all

internal class Menu {
	IrrlichtDevice _device = null;
	internal bool InitializeMenu(IrrlichtDevice device) {
		try {
			this._device = device;
			return true;
		} catch { return false;}
	}
}
Right before I enter my main rendering loop I would have something like this;

Code: Select all

Menu _menu = new Menu();
if (!_menu.InitializeMenu(_device))//failed to initialize class so shut down
	_device.CloseDevice();
while (_device.Run()) {
//...
I hope this helps, good luck with your endeavours.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

There are two ways possible basically:

1. declare those Irrlicht classes (device, scene manager, gui environment and so on) global. Like that any part of your code can access them. This works well with simple, short projects.

2. make your class to hold pointer to Irrlicht classes it needs, preferably as private member and pass it in to your class in its constructor. This is prefered for more complicated projects with code split in to lots of files, classes and so on.

Example:

Code: Select all

class MyClass
{
   scene::ISceneManager* Smgr;

public:

   MyClass(scene::ISceneManager* smgr)
   {
      Smgr = smgr;
      if(Smgr) Smgr->grab();
   }
   
   ~MyClass()
   {
      if(Smgr) Smgr->drop();
   }
};
grab() will tell engine that you are using scene manager and prevent it to discarding it while you do so. drop() will tell engine you do not use it anymore so it is safe to remove it if needed.
JerryM
Posts: 5
Joined: Thu Jun 19, 2008 9:51 pm

Post by JerryM »

Though it may not be the best way, I intend on writing my own abstract SceneManager and SceneNode classes, that for now will simply wrap around Irrlicht. That will allow me to write my actual game using a generic interface, and if I need to switch to another 3D engine, I only need to write a new set of wrappers, without having to touch any of my game logic.

The idea is that if I need to switch to a different engine, I should only have to write the new wrappers and change a single line of existing code.
Jgoldnight
Posts: 31
Joined: Thu Jun 07, 2007 6:23 pm
Location: New York
Contact:

Post by Jgoldnight »

I would take Arras' advice one step further and implement a generic class that keeps track of those pointers.

Code: Select all

using namespace irr;
using namespace video;
using namespace core;
using namespace gui;
using namespace scene;
using namespace io;

/*
Base class for all game entities. Game Entities 
all use Irrlicht.h and the irr namespace derivations. 
Therefore, we include them in one place to keep tidy.
*/
class GameEntity
{
public:
	GameEntity (IrrlichtDevice *device)
	{ 
		this->device = device; 
		this->driver = device->getVideoDriver();
		this->env = device->getGUIEnvironment();
		this->smgr = device->getSceneManager();
	}

	~GameEntity()
	{}

protected:
	IrrlichtDevice *device;
	IGUIEnvironment *env;
	IVideoDriver *driver;
	ISceneManager *smgr;
};
This is a cleaner way of managing the pointers without having to redeclare them for every new class in your game.

You can use this file as such:

Code: Select all

#include "GameEntity.h"
class MyClass : public GameEntity
{
public:
   MyClass(IrrlichtDevice *device) : GameEntity(device)
   {}
};
This will pass the passed in pointer to the irrlicht device, to the GameEntity class' constructor that will set up the pointers to the SceneManager, GUIEnvironment, etc.

Hope it helps!
Computer scientist by day...
http://www.mrjoelkemp.com
klikmaster
Posts: 40
Joined: Mon Sep 11, 2006 1:06 pm

Post by klikmaster »

Ok, so it seems like the best way to do it is to have everything Inherit from a GameEntity class which has all of the parts I need access to.

Thanks for the help guys. Much appreciated.
~IRRLICHT ROX MY SOX~
Post Reply