Can you correct this design

Started by
25 comments, last by Zahlman 15 years, 8 months ago
I tried making a oop design for my game but i think there is really something wrong with it. I'm using OpenGL, C++ and GLUT to make my game. My game is a copy of the game lightcycle (just search for details its long if i explain,sorry). Well my design goes like this. i have four class (w/ three as the main and one is just inherits the first one): Window Class: -well this class is for initializing the window system of the game although its use is just to for basic accessor methods and init methhods,this is used as a base class to inherit a more specific windowing system. glutWindow Class -this class inherits from Window.basically it just initializes the glut window and has the inherited method of setting the size of the window Cycle Class -well this class takes care of initializing and drawing of the cycle in the game Game Class -this is where i put the games logic,drawing screen,and input reading.the problem is that glut require callback registration,but all my callback 'to be' are in my game class but that gave error when i put in my class(ie if i put glutKeyboardFunc(this->keyHandler); to my Game::keyHandler definition) so the turn around that i thought of is to make a function holder,here how it goes: if i need to connect my Game::keyHandler to glut i make a function(namely kewyHandlerFunc) that has only "g->keyHandler;" in it (g is the object of Game) and register in main glutKeyboardFunc(keyHandlerFunc); so far it works but i feel something is wrong...also when i run glutMainLoop() i cant delete the Game Object,so i did is that i assign a function to atexit() where it deletes the Game object...and initializing the game can be seen on the main function...what i really want to only see on main is this:

#include "Game.h"

int main( int argc, char **argv )
{

   Game g= new Game( &argc, argv , "Beam Cycle" );

   if ( g->init() )
   {
      g->run();
   }
   else
   {
      std::cout << "initializiation failed!" << std::endl;
   }

   delete g;

   return 0;
};



Please help me with this design...if you need the code just say it and ill post it...really need to make this work PS its required that i use GLUT..so cant change it
Advertisement
Game g= new Game( &argc, argv , "Beam Cycle" );


You forgot g would be a pointer.
And your forgot about good naming conventions.

Anyway, could you show the way you implemented your architecture right now? As a graphical representation.

And explain your "Cycle" class a bit more.
Quote:Original post by Skeezix
the problem is that glut require callback registration,but all my callback 'to be' are in my game class but that gave error when i put in my class(ie if i put glutKeyboardFunc(this->keyHandler);
In C++ there is an almost painful distinction between a pointer to a free function and a pointer to a member function. GLUT requires a pointer to a free function but Game::keyHandler is a member function which is why it doesn't work.
Note however that a static member function behaves like a free function, so if you can make Game::keyHandler a static function then it will be possible to register it with GLUT. The caveat is that static member functions cannot access non-static members of a class.

You have to realise that GLUT is a C library and it won't play nicely with C++ classes, only C-style functions (and static member functions), so you are going to have to put up with a sub-ideal design to use it.

Quote:what i really want to only see on main is this:

*** Source Snippet Removed ***
Some points to make here:

1) Don't use pointers needlessly.
2) Don't separate construction and initialisation.
3) Do use exceptions.

So with that in mind something like this makes more sense:

int main(){    try {        // Instantiate the game, load the configuration from a file rather        // than from the application arguments.        Game g(Settings("config.txt"), "Beam Cycle");        // Run the game        g.run();    }    catch (...) {        std::cout << "Something Failed!" << std::endl;        return -1;    }    // return 0 is implicit}
If I were making this design, I would have some system of getting input defined in the Window Class. Then the glutWindow Class should handle the glut way of getting input internally, and provide that data to other classes through a strictly defined interface in the base Window Class. This way there would be no dependency between GLUT and the Game Class.
Quote:You forgot g would be a pointer.


sorry my mistake

Quote:And your forgot about good naming conventions.


its just for example,anyway i noted it :)


Quote:Anyway, could you show the way you implemented your architecture right now?


well,Window Class is a general class of window system(but for now it can only initialize and set its own size),glutWindow inherits form Window and changes how it(glutWindow) initializes itself(it uses glutInit,glutInitDisplayMode, glutInitWindowSize,glutInitWindowPosition,glutCreateWindow w/ properly supplied parameters) then it its SetSize function it uses glutReshapeWindow(again with proper parameters)

Quote:And explain your "Cycle" class a bit more.


the Cycle Class is a class contains the current x and y position of a cycle,its velocity,direction facing,if its destroyed,width of its trail and its trail(w/c are x&y points in a vector)

it also has a draw function which is basically just opengl,glut commands to draw circles translated and scaled to look like a bike :),also in that draw function i draw the trail using lines with certain widths...so if you call bike->draw() the bike(with proper facing due to direction member var) and trail are drawn

for the Game class it contains a glutWindow object,two cycle var,pause var(bool),framedelay var

this class contains other glut functions(glutKeyboardFunc,glutSpecialFunc, glutReshapeFunc,glutDisplayFunc, glutIdleFunc) that i pass external function but in that function it only contain member function call from the Game class..because if i make my member function static i wont be able call objects that aren't static

Quote:If I were making this design, I would have some system of getting input defined in the Window Class. Then the glutWindow Class should handle the glut way of getting input internally, and provide that data to other classes through a strictly defined interface in the base Window Class. This way there would be no dependency between GLUT and the Game Class.


i thought of that but glut only requires a function to be passed to glutKeyboardFunc, and i think that the game class should contain the input reading cause games has its own input translations and i maintain the window and thus glutWindow class as a window only....can you elaborate on this more...
So if your game class contains glutWindow object (not a pointer to your base window class), then it voids the need for your window class in the first place.

If you will ever create another window class implementation, such as using plain win32 for initializing the OpenGL window or something, you'll find that your game class is dependent on the way how GLUT calls its callbacks and your new window class will have to emulate that convention. If this is fine by you, then go for it.

On the other hand, you can architect your system a bit differently. You can define an interface for getting access to input data in your base window class, implement it in your glutWindow class and then access the input through that interface. Or if you want to have event like callbacks in your game class, then make an event system, which would accomplish that.

If you're going to go with the GLUT method, you can have a static game pointer in the game class, which would point to this of the game class object (assuming that only one instance of game exists). Then you could access the members through that pointer. I'm certain that you will be able to access the public members through that pointer, but I'm not sure if you'll be able to access the protected and private members. If you're not able to access those members, this probably can be solved using friendship. Haven't ever tried that though.

[Edited by - Giedrius on August 12, 2008 6:08:43 AM]
can you post some pseudo codes,i get the point about the base window class and having input interface for it but want im confused is that if in case i already have an input interface in my base window but glut needs to use either glutKeyboardFunc or glutSpecialFunc(or else if i missed something),so how do i do that if what i need is a function that needs to be passed to these functions,actually that was one of my first plan...to pass a member function of glutwindow to the input functions of glut(keyboard and special) but as i have said it cant be done because it needs static functions...

Quote:Or if you want to have event like callbacks in your game class, then make an event system, which would accomplish that.


i haven't dwell on this topic much so i think i need further explaining on this..
You might want to look into the other options for window setup and input handling. I'd recommend GLFW, SDL or SFML. SFML is newer and C++ while the other are more mature and C based. All of them are (IMHO) better choices than GLUT.

Your game class seems pretty heavy. It has a lot of responsibility. You might want to consider breaking it out into several smaller classes with well defined roles. If you want a single interface to them, you could use the facade pattern to create a class to wrap them all, but that's up to you.

Cheers,

Bob

[size="3"]Halfway down the trail to Hell...
As I don't know how exactly you are architecting your system, I'll keep the samples simple, so you can adapt and extend them to your needs.

class CWindow{public:	virtual bool IsKeyDown(int key) = 0;	//...};class glutWindow : public CWindow{private:	static void glutKeyHandler(<glut params go here>);	static bool m_bKeys[256]; //true if the key is down, false otherwisepublic:	bool IsKeyDown(int key)	{		return m_bKeys[key];	}};void glutWindow::glutKeyHandler(<glut params>){	if (<key> was pressed) m_bKeys[key] = true;	else if (<key> was released) m_bKeys[key] = false;}bool glutWindow::m_bKeys[256];


or

class glutWindow : public CWindow{private:	static void glutKeyHandler(<glut params>);	static glutWindow * pThis;	bool m_bKeys[256];public:	glutWindow()	{		pThis = this;	}	bool IsKeyDown(int key)	{		return m_bKeys[key];	}};void glutWindow::glutKeyHandler(<glut params>){	if (<key> was pressed) pThis->m_bKeys[key] = true;	else if (<key> was released) pThis->m_bKeys[key] = false;}glutWindow * glutWindow::pThis;bool glutWindow::m_bKeys[256];


As for the events, you can have an IEvent abstract interface class which should be inherited by classes who need to get some kind of event (such as a keypress). Then the class should register itself with the class that dispatches the event, so when the event occurs, the dispatcher class knows which object to send the event to.
so basically you just register glutKeyHandler(<glut params go here>); to glutKeyboardFunc then the game class queries the keys using IsKeyDown,then i handle the effects of pressing that key in the Game class...where do i register glutKeyHandler(<glut params go here>); to glutKeyboardFunc,i mean where do i put this statement glutKeyboardFunc(glutKeyHandler); in the Game class or in the window class??

another problem now is the drawing function...same as input reader but with more problem...if i make this function static i wont be able to call the Cycle objects' (included as member var of Game class) draw function in it,w/c lost its purpose because as of now that's the only thing i draw in the screen,i think this goes the same with the update func(w/c contains the logic of the game),if i make it static i wont be able to call any function of cycle class(or any class that is not static)

This topic is closed to new replies.

Advertisement