Object Oriented Game Design

Started by
12 comments, last by Lessa 20 years ago
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]
Advertisement
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..
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?
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
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.
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]
What you need is a property centric rather than object centric entity based engine. See some GDC slides on game object system.
3D Side-Scroller game demo Project-X2 "playable"Lashkar: A 3D Game & Simulation Project demo @ lashkar.berlios.de
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
R--------------------------------------------------------------------------There is no point in flaming if you've merely poured fuel on your own head
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.
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.

This topic is closed to new replies.

Advertisement