Archived

This topic is now archived and is closed to further replies.

Object Oriented Game Design

This topic is 5007 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

First off, I'm new here, so hi to everyone. Basically, me and a small group of 3 or 4 friends are working together on a small game (a strategy RPG), and we've reached a stage where we're wondering what the best overall design for an engine might be. Up til this point we've mostly been working with procedural C-style programming, which works well for small projects (we've almost completed a breakout clone using Allegro as a base for the graphics/sound/etc), but tends to become a bit messy - lately we've noticed that changes are harder to make because they tend to cause more bugs, etc. After having been reading up a lot on OO design lately we're sort of coming round to the fact that it may be better to use this idea of OOP in our next game design. I'm aware of the benefits it could give us - encapsulation, seperation of interface from implementation, polymorphism, but none of the tutorials/guides on OO design have really given me any solid examples of it's use in games specifically. At the moment we've sort of defined seperate modules as used in our game (ie one for general game code, one for the physics used, etc.), but the structure is rather blurred. I came across an article on these forums that suggests a stack-like structure for the different 'engines' a game might have (ie one for menus, then that creates a game engine class, places it on the stack and the loop runs through that until it exits back to the menus), but specific implementations of OO in game design mostly elude me. Anyway, my (our) question is basically, how do you personally use OO in your game designs? and what sort of general structure would be best? Any examples? Also, I've seen a lot on patterns (which are interesting in their own right), but I'm not at all sure how/if these should apply to game design (eg things like singletons). Again, anyone got any ideas/examples of their use? EDIT: Oh, one thing I forgot to say is that we use C++ mostly, and we're thinking of using perl as a scripting language on top of that for non time-critical game content. [edited by - Lessa on March 25, 2004 9:06:28 AM]

Share this post


Link to post
Share on other sites
First off, let me wish you good luck with the project. I hope it goes well for you.

One thing that isnt too clear from your post is which language you are planning on coding in- I am assuming C++, but you mentioned only C in your post. It is possible to do OO in straight C, but its far from easy.

Getting OO design right from the start is extremely difficult for novices. I think you need to accept that you are going to get things wrong to start with, and simply give it your best shot. Make some decisions based on your knowledge and understanding of OO, and just go from there. Its the only way to learn.

As for patterns. I think there are two schools of thought on this. 1) Apply patterns from the beginning, or 2) Refactor your code at the end and apply patterns to areas that need them.
I think you will have to go with 2) for now, as its difficult to see where patterns should be applied from the start if you are a beginner.

Patterns are used to solve TYPES of problems- so when you find that you need an object of which there should only be one instance- then use Singleton. If you come across an problem where you have to have an object which contains instances of itself (eg. i dunno - a unit of troops which contains subunits?) use Composite etc.

I know C++, but have only done a few months OO programming with it, and havent really had much experience with patterns in C++. As a Java programmer I could be more specific, but as it is, I think you will just have to feel your way forward...
Jon

EDIT- ah, I see you just mentioned C++ as I was typing this..

Share this post


Link to post
Share on other sites
I''m of the opinion that some people spend too much time focusing on buzzwords and not enough time getting a game completed. Object oriented design is a great paradigm, but it isn''t the Holy Grail of Programmin. Thinking in terms of objects helps us to visualize a software design much more clearly (usually). C++ provides direct support for translating that visualization to code. But it''s not a requirement to make use of those mechanisms.

Consider this C example:



typedef struct
{
int id;
} base_t;

typedef struct
{
object_t *obj;
int someInt;
} objSub_t;

obj_t *newObject(int id) { // yadda, yadda }


void deleteObject(obj_t *pObj) { yadda, yadda }

void objectSetID(obj_t *pObj, int id) { pObj->id = id; }

objSub_t *newObjSub(int someInt, int id)
{
objSub_t *pObjSub = (objSub_t *)malloc(sizeof(objSub_t));
pobjSub->obj = newObject(id);
pobjSub->someInt = someInt;
return objSub_t;
}

void deleteObjSub(objSub_t *pObjSub)
{
deleteObject(pObjSub->obj);
free(pObjSub);
}


Here we have a primitive form of inheritance and encapsulation, both of which are concepts found in the OO paradigm. The data structures could be hidden behind a handle system (much like the handles used in Win32 programming), or exposed in header files (provided the user is disciplined enough not to manipulate member fields that shouldn''t be manipulated - okay for a single coder project, but asking for trouble when a team is involved).

Of course, because C++ is designed to support the OO paradigm directly, we can protect ourselves from manipulating things that shouldn''t be manipulated with the private keyword. Or make safe casts from one type to another by making use of features like dynamic_cast. Or access non-virtual superclass methods directly through a subclass without having to cast the dubclass or get a reference to the superclass first.

The point of my little tirade here is that the OO paradigm is a way of thinking that can be applied to (nearly) any programming language. So when sitting down to start an initial design, it might be a good idea to forget about languages and think about objects. Think about the language and language features when it comes time for the implementation. This, I think, is where a lot of people get hung up.

Breaking your application down into components is a great way to start. Once you know your major components you can flesh out the functionality. You may find that some components can be broken down further, or will need new objects you haven''t thought of before. Once you have reached a certain level in the design where it looks like things should do what you want them to (i.e., you know the realtionships of each object in the graph, what functionality an object needs to expose in it''s interface to other objects, and how the flow of the app will go from start to finish) - then you are ready to start mapping this OO design to your language of choice. This is the point where you can make decisions about implementation details and language specific features (should my Entity container be a class? a template? a custom list implementation? a std::list? a std::vector?).

I really, really, really suggest that you don''t stress it. Design what feels natural. Read some books and articles to gleen some insight into the concepts, but don''t spend weeks on theory, trying to get the ''perfect OO design''. It doesn''t exist. Just start with what feels natural and implement it.

And one more thing - don''t design an engine!!! Design the game. Forget the term game engine completely. ''OOP'' and ''game engine'' are two buzzwords that I wish people would unlearn when they are starting out. Game programming means making games. Get a game completed. Then another. Then another. Then another. As time goes by you''ll recoginze how some of those design patterns pop up in your code structure. You''ll see how your first design was naive and your second was only slightly better. One day, you''ll decide to take all that you have learned and put it together, imporved of course, as a highly reusable code base. Hey, isn''t that a game engine?

Share this post


Link to post
Share on other sites
I agree with these things about "Engines" and "OOP", but I think you should generally use polymorphism:

Simple answer: It''s just does what you want.

Games are a very object-oriented application. In fact, the whole OO systems we normally talk about, are very well suited to typical games, due to the fact that a typical video game only has a limited amount of base types of things, then they tend to be divided into subclasses with different behaviours. This is what polymorphism does.

There is a fairly good tutorial on this from a game-programming perspective here

http://www.gamleby.net/gearhead/index.php?action=articles&view=1

Mark

Share this post


Link to post
Share on other sites
quote:
Original post by markr
I agree with these things about "Engines" and "OOP", but I think you should generally use polymorphism:



Hmm. I didn''t say polymorphism shouldn''t be used. The point I was trying to get across is that you establish object relationships at the design level. This does not exclude polymorphism at all. If you decide that a BigBlueBlob ''IsA'' SpaceCritter, then when you move on to implementation you use the language features available to model that relationship.

But I do disagree with the idea that you should ''generally use polymorphism''. There are instances where it''s the right thing and instances where it isn''t. In some cases containment is a better solution than subclassing.

Share this post


Link to post
Share on other sites
What we're trying to do is to design our system for a specific game (we're not aiming to create a generic game engine for reuse over multiple projects, although if we do end up creating stuff that we might reuse it could help in future. That's not the main aim though). We've got a fairly clear idea of what we want the game to be, and what we need to do, and we're starting on working out how to implement it. Basically you're saying it'd be a good idea to sit down and effectively divide what we need into seperate sub-systems and work on the higher concepts before descending into code properly?

When I wrote the first post I think I was focusing more on the fact that our current project is a bit of a mess because we used C, but I suspect that if we'd designed it properly from the start we might've avoided a lot of the problems we have where subsystems are meshed with each other. Hrm.

I guess we need to sit down together and figure out what we need and how it interacts before thinking about specific implementations of it.

Having said that, it's still useful to see how other people have used ideas in their designs. There are certain things (data loading systems/general framework for the game loop) that are common within games, and it's useful to see how other people have generally structured their systems. How does the industry generally go about designing games (or software in general?), from the position of implementing them? (Is that even a reasonable question to ask?). I mean there are no hard-and-fast rules, but it's nice to have pointers in the right direction (incidentally, I find the project postmortems posted on gamasutra very interesting, especially from the pov of how the teams work together - I think one of the most important things when working in a team is communication, between all members. Basically I'm tryig to see what techniques work well and which don't when developing games).

I'm learning a lot from this already (especially in terms of what's important when desiging games/applications, thanks ).

EDIT: Just a thought: it's been mentioned that it's better to make a game than an engine, but surely there's something to be said for seperating the so-called 'engine' from the content (ie the low-level routines from scripted sequences and such)? Is that a good idea? When does the abstraction become too abstract, in essence?

[edited by - Lessa on March 26, 2004 5:30:24 AM]

Share this post


Link to post
Share on other sites
You may know some of what I''m about to say but I think I should spell it out anyway.

As some people have generally eluded to, you need to learn some OO stuff before you tackle your larger project.

You mentioned that your breakout game was getting messy. I suppose you can imagine that an RPG is a *lot* bigger than a breakout game so you can imagine the mess you can get yourself into if you just go gung-ho.

So why not try to learn a bit of OO by rewriting your Breakout game from the ground up? It''s not an enormous project and if you decide to change your design ideas because you''ve made a mistake (or just got a better idea) then the reworking won''t be so bad. Since you already understand the game all your learning efforts are concentrating on OO/game design.

Learning to write a proper RPG can be complex. You have game characters (NPCs) and they need some AI, you need to map a world out, you need your character to interact with it, you need to develop a plot and learn how to weave events together to create a coherant flow without everything deciding to happen in the wrong order (or all at once). This sounds like the old "biting off more than you can chew" cliche, if you don''t mind me saying so.

I know you might sigh and roll your eyes at the Breakout rewrite. It''s not 3D and it feels so "yesterday" now that you have it but you need to learn OO and feel more comfortable with it before doing your RPG. Trust me. Even "professionals" can make a *total* meal of it.

Program design can be an art. Some people are better at it than others but everyone starts off making mistakes. Make your first ones smaller and learn more quickly. You won''t be disappointed.

Also, someone else talked about design. Once you start your project, try to design it on paper (or virtual paper if you like). Don''t design it by starting to code. Design the high-level view and then design the subparts. Draw your bubbles or clouds or whatever, write your data and methods in them and draw lines between them etc. Think about how the puzzle fits. Break it down a little but don''t go crazy. Make sure it all sounds like it makes sense and that it sounds like it''ll work. Then start coding. It should practically code itself.

Don''t refer back to your original procedural implementation either. You''ll have nothing to refer back to for your RPG.

This is why we have design documents in the real world. And they can be huge.

R

--------------------------------------------------------------------------
There is no point in flaming if you''ve merely poured fuel on your own head

Share this post


Link to post
Share on other sites
quote:
Original post by Lessa
EDIT: Just a thought: it''s been mentioned that it''s better to make a game than an engine, but surely there''s something to be said for seperating the so-called ''engine'' from the content (ie the low-level routines from scripted sequences and such)? Is that a good idea? When does the abstraction become too abstract, in essence?


When you start thinking about separating the engine you lose sight of what the term ''game engine'' really means - reusable support code. If you look around these forums a bit you''ll find numerous game engine design topics. Look closely at some of the proposed designs. It seems to me that people who set out to design a game engine to support their game treat the engine as one system with several subsystems. What this leads to is a design where the subsystems are tightly coupled, dependant upon one another.

That''s why I say to forget the term ''game engine''. Focus on ''game subsystems''. Input, audio, graphics, network, resource management... all of these will be separated from the game itself, and the game will make use of all of them. But I think the most important thing is to keep them independent of each other. It should be possible to rip out one of the subsystems and replace it with an entirely different implementation. As long as you have a clear interface defined, it becomes easy. In essence, this is a game engine, but how you mentally approach the design will truly influence the outcome.

Share this post


Link to post
Share on other sites
I am going to have to agree with the points made here. I got fixated with the term "Game Engine" and it lead to my development downfall.

Now I have would could be called a "game engine" but I think of it as more a reusable code base, each independent of the other. If I want to rip out the graphics and replace it I can without interfering with any other code includeing the game.

I got to this stage after many rewrites of "game engine" and then writing lots of small games (in some cases I would be reported to the Trading Standards for use of that term) and this gave me an idea of what code is reused time and time again.

I store my reusable code in dll''s with well designed interfaces (paper everywhere). Each dll is independent of each other.

My game then hardcodes nothing, everything is external from how the menus look to the game content (via a simple scripting language) so I can tinker until my hearts complete.

As well as getting in a rut about "game engine" another of my fallings was trying to be a big development house when I was only 1 man. My output may not look as good as the pro''s but I am now at least getting things completed.

Share this post


Link to post
Share on other sites
quote:
Original post by RowanPD
You may know some of what I'm about to say but I think I should spell it out anyway.


No, that's good. The reason why I'm asking about these things is because I want to learn, and you've been very helpful so far (thanks).

Re-writing the breakout game from the ground up I suspect might be a good idea, I'll have a think about that one. The reasoning behind our current design for the RPG is for a relatively small project - I don't want it to turn into a huge epic (1000 playable characters lolol!!!11), in fact our storyline's fairly simple (and very linear, for a reason - I don't want to have 300 subplot sidequests going on at once), e.g. we're not using NPCs for more than just talking to - I've had a long think about various projects that I've seen on the net that've just been basically FAR too much for 1 or 2 people to handle. At the moment we have about 3 or 4 programmers (it's an informal arrangement, we aren't a software house or anything, just a group of friends who happen to like making games), who are fairly proficient at what we do (again, I'm under no illusions, we've got a LOT to learn, which is one of the reasons I'm asking so many questions), a graphic artist and a modeller.

As an honest question, is that too big a chunk to start with?

quote:

That's why I say to forget the term 'game engine'. Focus on 'game subsystems'. Input, audio, graphics, network, resource management... all of these will be separated from the game itself, and the game will make use of all of them. But I think the most important thing is to keep them independent of each other. It should be possible to rip out one of the subsystems and replace it with an entirely different implementation. As long as you have a clear interface defined, it becomes easy. In essence, this is a game engine, but how you mentally approach the design will truly influence the outcome.


If we were to redesign our breakout game from the ground up, with the idea of these game subsystems, would it be a feasible idea to create the systems (input, sound, graphics, etc), then reuse them along with this RPG I mentioned? Or would it be better to recode them for the breakout clone and then recode them again along with the lessons learned from the first recode? Again, I'm not aiming to create an 'engine' but to be more specific to our game(s).

Again, thanks a lot for the input, I really appreciate it.

[edited by - Lessa on March 26, 2004 11:18:22 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by Lessa
... would it be a feasible idea to create the systems (input, sound, graphics, etc), then reuse them along with this RPG I mentioned? Or would it be better to recode them for the breakout clone and then recode them again along with the lessons learned from the first recode? ...



It depends - if you recode them, and they seem like they''re good and usable, then see if they meet the requirements for your RPG, if they do, use them, if not, rewrite. As a trivial example, suppose you wrote your sound system to output 2D audio, and then in your RPG you had a requirement that said 3D audio, it''s obvious that your sound system needs upgrading or rewriting.

Inevitably you''ll probably end up doing upgrades/rewrites because of requirements changes, or because of changes in your thinking (which will happen quite a bit when you''re new to a language or paradigm). You can either fight the urge to rewrite (because it can take lots of time and you might end up doing it a lot) or you can just put in upgrades to systems as necessary, promising yourself "I''ll rewrite this nicely if there is time".
If you spend all your time writing and rewriting components no progress is made (this has been the downfall of many programmers and teams, myself included, in the past).

-Mezz

Share this post


Link to post
Share on other sites
Guest Anonymous Poster


About 2 years ago I decided to program a small turn-based strategy game as a hobby. Starting with no game programming experience I jumped in head first and now, several false starts later, I finally made first-playable. During that time I went to great pains to teach myself OOP largely for the reasons that have been discussed, as my code was always a mess, but I was determined to ''do it right''. Based on what little I learned in that time, some of the comments in this thread contain excellent insights:

1. OOP is not a programming language. While languages like Java and C++ attempt to ''enforce'' good OOP, that doesn''t prevent people from creating hideous designs. OOP is a way of thinking about the design of your code that can be applied, for the most part, to any language.

2. A highly reuseable game engine, or reuse in general for that matter, is not the holy grail, finishing the game is the holy grail. Opportunities for reuse will, however, be more likely to emerge naturally from a good OOP design.

3. Start with what you know. This is critical. I started out knowing very little about game programming and my first attempt was a horrible mess. I tossed it out, bought a book on OOP and started over. From scratch. I had learned enough about programming on the first attempt to understand the basics of OOP, but they say that if all you have is a hammer then everything looks like a nail, and that was the mistake I made with inheritance. I tried to do EVERYTHING with inheritance and my second attempt also quickly turned into a big mess. I tossed it out, bought a book on design patterns and started over. From scratch. I had learned enough about OOP on the second attempt to understand the basics of design patterns and finally, after months of programming the same game over and over, I hit on a code design that I liked and finished the game. Don''t be afraid to jump in and make mistakes, and when it gets ''messy'' don''t be afraid to toss it out and use what you learned to do it better the next time.

4. Design on paper. This is extremely critical. It might sound boring, but if you take the time to sit down and figure out how things work together on paper first, then the code will practically write itself. Not to mention it also serves as a document that clearly describes your thought process behind the code. This is something that isn''t easy to do with comments in the code, and something that will be worth it''s weight in diamonds if you ever have to rework code that you haven''t touched for several months. For my little hobby game I built up a stack of design papers the size of a phone book, a fitting testament to the fact that even small games can quickly become extremely complex.

5. Design by decomposition. This is a highly useful concept and has served me very well. Almost any program (or any THING for that matter) can be defined as a few major components: interface, display, network, etc. And any component can be broken down into sub-components. Components can be developed independently of each other and, using a well defined interface, can be easily ''plugged-in'' to the overall framework of the application. It follows that they can also be ''swapped-out'' at any time as improvements are made, leading to very flexible code and an agile development process, but it''s critical that components have as few dependencies as possible, which leads to:

6. Decouple, decouple, decouple. This is probably the single most valuable lesson I learned from my experience. It is the clear intent behind almost all of the design patterns, and it is at the very foundation of OOP because it is the essential concept behind encapsulation, or ''programming to an interface''. I think the single biggest conceptual breakthrough for me was when I realized that OBJECTS DO NOT WORK TOGETHER. Sound strange? Think about it, if two objects are working together it implies that they know about each other and right away you have a dependency. Change one object and there''s a good chance you will break the other one. After working with design patterns for awhile I eventually realized that the ultimate goal in OOP program design is to create objects that know absolutely nothing about any of the other objects in the program.

The trick is to stop thinking about objects that ''use'' other objects by calling their interface directly. Instead, think about objects that are completely isolated, sitting alone in a dark room. An object knows how to broadcast events by shouting into the dark, and it knows how to listen for events that come out of the dark, from who knows where, but that''s all it knows. When an object hears an event it has everything it needs right there in the room to do it''s thing (including data, helper objects, and sub components), it doesn''t need to know anyting about where the event came from, or from who, it only knows what it''s job is when it hears that event. Sometimes doing it''s thing involves shouting it''s own events out into the dark, but again, the object doesn''t need to know anyting about who, if anybody, is out there listening, it just knows that it''s job is to shout that event out. I have found that this conceptual trick forces me to think through designs that have a very high degree of encapsulation and leads naturally to very flexible, and yes, reuseable code. This concept is the intent behind the ''observer'' and ''mediator'' design patterns.

A slightly less flexible arrangement, but one that arises naturally from designing by decomposition, is to think of programs as offices full of cubicles. Each object toils in it''s little cubicle and doesn''t speak directly to the other objects. Instead, it passes it''s work up to the floor manager who, in turn, decides to either pass the work up to the next level in the heirarchy, or to delegate the work to one of the other cubicles on that floor. This concept is the intent behind the ''composite'' and ''chain of responsibility'' design patterns.

And finally:

7. Seperate content from code. This is a no-brainer and is already widely practiced in the game industry, as evidenced by the mod scene. Game engines are increasingly becoming fancy front-ends to what are essentially content databases.

That''s about it. Hope this helps.

Jerry




Share this post


Link to post
Share on other sites
Good post, a little observer/listener-centric, but good none the less.

For more info on design patterns google for "Thinking in Patterns" by Bruce Eckel. The code is in java but the syntax a really close to c++.

Read other peoples code. You learn alot. There is alot of really horrible code out there (thinking of the freecraft source here). Alot of people have absolutely no clue.

Share this post


Link to post
Share on other sites