Sign in to follow this  
Omelas0469

Program structure issue (pacman)

Recommended Posts

Hi, I've been coding a pacman game in C++ using the openGL GLUT library. Right now I've got three main files 1. Pacman.cpp 2. Ghost.cpp 3. Manager.cpp Pacman.cpp defines the class pacman which I used to instatiate pacman. Ghost.cpp is a base class I used to create ghost objects. Manager.cpp is not a class but is the driver code (contains the 'main' function). Right now, Manager.cpp has global variables declared as follows:
Pacman * pacman;
Ghost * blinky;
and my main() looks like this:
int main(int argc, char **argv) {
	glutInit(&argc, argv);            // initialize GLUT
	glutInitDisplayMode(GLUT_RGBA);   // set RGBA display mode
	glutInitWindowPosition(325, 0);
	glutInitWindowSize(600, 600);
	glutCreateWindow("Pacman");
	init();
	srand((unsigned)time(0)); //for random number generation
	pacman = new Pacman();
	blinky = new Ghost();
	glutDisplayFunc(displayScene); // set the rendering function
	glutTimerFunc(0,Timer,0);
	glutSpecialFunc(arrow_keys);
	glutIdleFunc(update);
	glutMainLoop(); // process events and wait until exit
	return 0;
}
My issue is that I don't want to use global variables but I don't see how else I can organize the files since my glutDisplayFunc callback procedure (displayScene) needs to access the global variables pacman and blinky to call their draw functions... i.e.
void displayScene()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glPushMatrix();
	Map::drawMap();
	pacman->draw();
	blinky->draw();
	glPopMatrix();
	glFlush();
}
Any ideas as to how I might be able to organize these files (or how I could use a new class) so that I can avoid using the global variables? Note that the reason I'm using global variables in "Manager" in the first place is because I need to be able to access pacman and blinky (and soon the other 3 ghosts) all in one place so I can compare their variables (positions, states, etc.). Thanks, Omelas UPDATE: I tried creating a class Game as follows: Game.h:
#ifndef GAME_H
#define GAME_H

#include "Character.h"
#include "Pacman.h"
#include "Ghost.h"

class Game
{
public:
	Game();
	void displayScene();

private:
	Pacman * pacman;
	Ghost * blinky;
	/*Ghost pinky;
	Ghost inky;
	Ghost clyde;*/
};

#endif
Game.cpp:
#include "Game.h"

using namespace std;

void Game::displayScene()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glPushMatrix();
	Map::drawMap();
	pacman->draw();
	blinky->draw();
	glPopMatrix();
	glFlush();
}

Game::Game()
	: pacman(new Pacman()), blinky(new Ghost())
{
}
then I removed displayScene from Manager.cpp since its now in Game and I modified main as follows:
int main(int argc, char **argv) {
	glutInit(&argc, argv);            // initialize GLUT
	glutInitDisplayMode(GLUT_RGBA);   // set RGBA display mode
	glutInitWindowPosition(325, 0);
	glutInitWindowSize(600, 600);
	glutCreateWindow("Pacman");
	init();
	srand((unsigned)time(0)); //for random number generation
	Game game;
	glutDisplayFunc(game.displayScene()); // set the rendering function
	glutTimerFunc(0,Timer,0);
	glutSpecialFunc(arrow_keys);
	glutIdleFunc(update);
	glutMainLoop(); // process events and wait until exit
	return 0;
}
but I get an error saying: error C2664: 'glutDisplayFunc' : cannot convert parameter 1 from 'void' to 'void (__cdecl *)(void)' 1> Expressions of type void cannot be converted to other types Any idea how to get around this? Am I on the right track? [Edited by - Omelas0469 on December 17, 2008 9:50:16 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Omelas0469

UPDATE: I tried creating a class Game as follows:
Game.h:

#ifndef GAME_H
#define GAME_H

#include "Character.h"
#include "Pacman.h"
#include "Ghost.h"

class Game
{
public:
Game();
void displayScene();

private:
Pacman * pacman;
Ghost * blinky;
/*Ghost pinky;
Ghost inky;
Ghost clyde;*/
};

#endif


Game.cpp:

#include "Game.h"

using namespace std;

void Game::displayScene()
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
Map::drawMap();
pacman->draw();
blinky->draw();
glPopMatrix();
glFlush();
}

Game::Game()
: pacman(new Pacman()), blinky(new Ghost())
{
}


then I removed displayScene from Manager.cpp since its now in Game and I modified main as follows:

int main(int argc, char **argv) {
glutInit(&argc, argv); // initialize GLUT
glutInitDisplayMode(GLUT_RGBA); // set RGBA display mode
glutInitWindowPosition(325, 0);
glutInitWindowSize(600, 600);
glutCreateWindow("Pacman");
init();
srand((unsigned)time(0)); //for random number generation
Game game;
glutDisplayFunc(game.displayScene()); // set the rendering function
glutTimerFunc(0,Timer,0);
glutSpecialFunc(arrow_keys);
glutIdleFunc(update);
glutMainLoop(); // process events and wait until exit
return 0;
}


but I get an error saying:
error C2664: 'glutDisplayFunc' : cannot convert parameter 1 from 'void' to 'void (__cdecl *)(void)'
1> Expressions of type void cannot be converted to other types

Any idea how to get around this?
Am I on the right track?


It's good that you gathered all of your game variables into one game class. However there is no way in C++ to create a pointer to a member fucntion that can be called as a C-style function pointer. Its mainly the fault of GLUT for not providing a more Object Oriented interface. There is nothing you can do about it. However, you current abstraction is good enough. You will have to have only one global instance of the Game class and then use wrapper global functions that will call your game class functions.

I would also advise that you put your update, and input handling functions inside your game class.

Notice that your abstraction still works if you make your game class abstract and have virtual functions. Then you can create different game classes and just initialize the global game instance to different specific game classes without having to change any other code.

Share this post


Link to post
Share on other sites
Quote:
glutDisplayFunc(game.displayScene()); // set the rendering function

Remove the parenthesis. Currently, you're calling game.displayScene() and you're then passing it's return value to glutDisplayFunc(). What you want to do is passing a pointer to game.displayScene instead. However, glutDisplayFunc does not take a pointer to a member function, only to free functions, or static member functions.

So, you'll need a free render function. What you can do is to make a global Game instance and a DisplayGame function, that knows about the Game instance so it can call it's displayScene function.


On a side-note: I see you're dynamically allocating memory for your pacman and ghost instances with 'new', but your Game class does not have a destructor that 'deletes' this memory afterwards, so you're going to leak memory there. Either delete them in the destructor, or use smart pointers so it will be taken care of automatically.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this