Skip to main content
GameDev.net gamedev.net
🔒 Locked

OOP/Modular based Game design?

Started by Mr_Fhqwhgads Feb 5, 2006 at 10:33 PM 10 replies 9.6k views
Original Post
Mr_Fhqwhgads
Mr_Fhqwhgads
When I say OOP/Modular I mean make it so its easy to add new features without having to modify a whole lot of pre-existing code. What would be the best way to design a OOP/Modular game? So main() creates a GameCore object which does/handels everything instead of main() doing it. Then have a different class for different parts of the game: NPC, Player, Item, Map, GUI, Networking, Graphics etc. This this a good way to program a game, or is it better to do everything in main() and call the classes from that? OR is there a compleatly different/better way to desing a OOP/Modular game?
Blupix Games
steeg
steeg
Let me start off by saying that I'm not a professional game developer and have only just made a few games. In my opinion, once you have your main game objects setup, it is much easier to write a game using the OO approach and also, if you are a beginner, it will force you to organize your thoughts and think about the different parts that come together to make up a game.

I tend to think that having a game object makes the code more manageable and easier to see what is going on. This way, you could have the game object deal with the basic stuff (input handling, updating, rendering, etc) and control the actual calling of these methods from the main loop, something like:
	bool running = true;	Game* game = new Game();	game->init();	while(running) {		game->handleEvents();		game->update();		game->render();	}	game->stop();


ps: this doesn't do anything on its own (and it runs forever since bool running never changes), but it's just an example to show how you can manage your game from outside the game class.

Of course, this is not the only way to program games. Some people prefer to use the procedural approach or prefer to use some other kind of design pattern...this is just my 2 cents on what works for me.
Sandman
Sandman
Quote:
Original post by Mr_Fhqwhgads
When I say OOP/Modular I mean make it so its easy to add new features without having to modify a whole lot of pre-existing code.

What would be the best way to design a OOP/Modular game? So main() creates a GameCore object which does/handels everything instead of main() doing it. Then have a different class for different parts of the game: NPC, Player, Item, Map, GUI, Networking, Graphics etc.

This this a good way to program a game, or is it better to do everything in main() and call the classes from that? OR is there a compleatly different/better way to desing a OOP/Modular game?


This isn't quite the right forum for the technical side of game development; the forum title 'Game Design' refers to the gameplay design rather than the actual code design. I'll move this to Game Programming so maybe you can get some more advice on the subject.

How you actually break down the game into objects is really up to you, I'm not sure there is one single 'best' way - although some approaches will have clear advantages over others, depending on what you're trying to achieve with the code. What you really need to do is to spec out the requirements of your engine and what you want from the code. Then identify which components qualify as 'objects' and how they fit together.

Good OOP design is hard. Be prepared to make mistakes, and learn from them rather than be discouraged by them.
Emmanuel Deloget
Emmanuel Deloget
Quote:
Original post by Mr_Fhqwhgads
When I say OOP/Modular I mean make it so its easy to add new features without having to modify a whole lot of pre-existing code.

What would be the best way to design a OOP/Modular game? So main() creates a GameCore object which does/handels everything instead of main() doing it. Then have a different class for different parts of the game: NPC, Player, Item, Map, GUI, Networking, Graphics etc.

This this a good way to program a game, or is it better to do everything in main() and call the classes from that? OR is there a compleatly different/better way to desing a OOP/Modular game?


Like steeg, I'm not a professional game programmer, but I am a professional software architect (well... it sounds like a shameless plug; please, don't forget that my opinion is just that: an opinion) so I may be able to help.

Before saying "what should be where" - which is the first cause of OOD failure because doing so already add constraint on your design - you have to find what are your needs and what will be your needs. Too much "wanno do this" and you'll over-engineer your engine (and it will never be perfect). Not enough thinking of your engine future and you'll forget some basic needs that may break your design when you'll implement them.

Before continuing, you must understand that over-engineering is acurately defined by "beyond your comprehension", not by "too complicated". Once you feel lost in your design because of its complexity, it is over-engineered. It also means that you must stick to what you understand in term of OO design - don't try to do "what the others do" (mostly because "the others" are really scary).

The second main thing to do before anything else is to get some information about design patterns and OO design principles (Coad's rule, OCP, LSP, ISP, and so on. You'll find some interesting informations on Object Mentor). It is also good to get a UML modeler and to learn the basics of UML - it will really help you (note that UML can be replaced by OMT or by some other object oriented methodology; UML is prefered).

The reason for learning OO design principles and patterns is that they really enhance your way of thinking.

Now, you have everything ready and you mind full of idea. Launch your UML modeler and create your project.

First, it is obvious that you are going to handle a game. Thus, it seems taht a Game class is required. This game will probably have different states (loading screens, option screens, game lost/won, and so on) so you'll have a GameState class.

Try to define your game states correctly (this is where "game design" as seen by Sandman is important because it will defines the features needed by your game), this will give you your game classes.

Note, you have seen, we only had a look to the game itself (not the technology behind it). This is because the game is a model that is not dependant upon its representation and the user actions (thus, the core game is not dependant on the graphic/input engine). This simple sentence also say that we have 3 different entities to deal with: the game model, its representation and the user actions (I let you find why I say this in this particular order [smile]).

Once you defined your game model, it is easier to spot your needs in term of user input (and how to deal with them) and game representation. This will give your some hints about the objects that are needed in the interface of each main entities (game, representation, input).

Needless to say, you'll have a pretty decent amount of work to do before you put your first line of code in your project.

Oh. Did I mention that coding once you finished (and polished) everything is the only choise you have ? Because coding before the design is finished will give you some headaches if you make a design mistake :)

Of course, as I stated before, this is only my (humble?) opinion [smile]

HTH,
cypherx
cypherx
I'm also not a professional game developer. I do have some coding experience, including a few small games...but take my opinion with a grain of salt.

That said, I don't think Object Oriented design is that great for a small hobby game. In the past, I spent way too much time on a game engine building up intricate object relationships and then untangling them when I realized I had missed an important feature. I think OOP is much better suited for development teams with explicit/semi-rigid requirements than individual hobby coders.

For small games you usually don't need all that structure. Think about what you need your game to do, decompose that into functions and data structures. You'll have some organization/modularity without the rigidity of inheritance hierarchies.

To recode steeg's example:
GameState game; //a simple POD datastructure with any gamestate varsinit(game);while(game.running) {   handleEvents(game);   update(game);   render(game);}stop();

This is almost the same thing, but you're not tying your functions to any specific stateful data. This makes your code less scalable but more flexible, and in my opinion, quicker to develop.

-Alex
DaTroof
DaTroof
Quote:
Original post by cypherx
I'm also not a professional game developer. I do have some coding experience, including a few small games...but take my opinion with a grain of salt.

That said, I don't think Object Oriented design is that great for a small hobby game. In the past, I spent way too much time on a game engine building up intricate object relationships and then untangling them when I realized I had missed an important feature. I think OOP is much better suited for development teams with explicit/semi-rigid requirements than individual hobby coders.

For small games you usually don't need all that structure. Think about what you need your game to do, decompose that into functions and data structures. You'll have some organization/modularity without the rigidity of inheritance hierarchies.

To recode steeg's example:
*** Source Snippet Removed ***
This is almost the same thing, but you're not tying your functions to any specific stateful data. This makes your code less scalable but more flexible, and in my opinion, quicker to develop.

-Alex



Your example isn't significantly different from steeg's other than separating the functions from the data structure. I don't see how that makes it more flexible or quicker to develop. It's just as easy to encapsulate the functions and data in the same class. I did appreciate, however, that your example encapsulated the running bool in GameState.
Post Extant Graphical MUD
cypherx
cypherx
DaTroof,

Like I said in my first post, my recoded example is almost identical to the original. Since the code doesn't actually do anything, it's hard to make something distinct out of it.

For a more relevant example, think about how much scaffolding/infrastructure something as simple as rendering requires in an OO approach to game engines. In many designs I've seen screen objects implement an IRenderable interface and possess a Draw() method. There is then a Renderer class responsible for calling all these draw methods. Another option (if you're targetting multiple backends) is to have Renderables carry high level data describing their graphical properties and then different Renderers (OpenGLRenderer, DXRenderer, SoftwareRenderer, etc...) translate these into appropriate API calls. I'm sure there are other OO approaches to rendering I'm not thinking of. There's nothing wrong in either approach, but it's easy to get caught up in "high level" design issues and spend time perfecting how classes interact instead of writing useful code.

Why even bother? That infrastructure is useful for managing complexity, organizing a large codebase. But if your codebase isn't large (in the case of a small hobby game) the exta structure is (in my opinion) more distraction than useful. Just write the code you need, put it in a function, call that function. Whatever data the function requires, you group in a struct and pass it in. No data/implementation hiding, no Liskov Substitution Principle...just do things in the plainest most obvious way possible.

I repeat that I this will fall apart once your game grows. Maybe it's a reaction to my own propensity to over-design, but I think it's more important to get *something* done instead of worrying about the scalability of a not-yet-finished engine.

-Alex
Omid Ghavami
Omid Ghavami
I usually have (when applicable) a game session class (The functionality of that class is of course also devided into several classes),
which handles a complete session of the game (loading resources, setting up initial state, game loop, rendering e.tc) and returns the outcome.
Then combine that with some higher level game class, menu class and so on expand the complexity.

[MyGameApplication] -----------------------------> [Menu]                     Creates a main menu object                     initiates it, loads it, and                     starts it.[Menu] --------------------------> [Game]        Holds a game object,                    either initial state new        one, or loaded state.


[Game]
Manages the state of the game progression. Number of remaining lives, total score, ship upgrades e.tc.
Also manages in-game menu (ie buy ship upgrades, check map for available missions, select next mission e.tc)

[Game] -------------------------------------> [GameSession]        Sets up a game session object         according to selected level        specifications. Passes relevant        game info to the session. Starts it


[GameSession]
Where the actual game play takes place. This part can and should be devided into many classes and functions handling different parts.
Using the same principal as for the higher level classes, ie give necessary info, receive results, apply results.
Example
std::for_each(objects.begin(),               objects.end(),               boost::bind(&objects::Update,                          _1,                          boost::ref(timeDelta),                          boost::ref(objUpdateResults)));std::for_each(objUpdateResults.begin(),              objUpdateResults.end(),              boost::bind(&GameSession::ApplyResult,                          this,                          _1));

[GameSession] ---------------------------------------> [Game]               When session is over, the results                of the session are returned to the                game (acquired points, lost lives e.tc)Game gets updated, and repeat.


I'm quite tired so might be a bit messy, but I hope it helps

EDIT: fixing some layout problems

Regards,
/odyss-jii
Best regards, Omid
DaTroof
DaTroof
Quote:
Original post by cypherx
For a more relevant example, think about how much scaffolding/infrastructure something as simple as rendering requires in an OO approach to game engines. In many designs I've seen screen objects implement an IRenderable interface and possess a Draw() method. There is then a Renderer class responsible for calling all these draw methods. Another option (if you're targetting multiple backends) is to have Renderables carry high level data describing their graphical properties and then different Renderers (OpenGLRenderer, DXRenderer, SoftwareRenderer, etc...) translate these into appropriate API calls. I'm sure there are other OO approaches to rendering I'm not thinking of. There's nothing wrong in either approach, but it's easy to get caught up in "high level" design issues and spend time perfecting how classes interact instead of writing useful code.


Okay, I can see your point about over-design. I just thought you were throwing the baby out with the bathwater. Why avoid encapsulation if the problem you describe is related to inheritance? An object-oriented approach doesn't mandate the use of a complicated inheritance hierarchy. Proper encapsulation remains useful on its own because it can provide a design that's just as flexible, but easier to maintain.
Post Extant Graphical MUD
steeg
steeg
I think the important thing about using the OO approach even in small projects, is the ability to easily expand upon it, especially adding new features to accomodate new requirements (to do some paraphrasing of the patterns book mentioned by "Anonymous Poster" [grin]). Of course, the same thing could be accomplished with a well designed modular approach. OOP is not the almighty problem solver which works everytime.
Zahlman
Zahlman
We are not bumping threads that are 5 years old to promote blog articles, thank you.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.