Object Oriented Game Programming

Started by
12 comments, last by A_Primetime_Fool 19 years, 8 months ago
So working on my game engine, I've been finding myself using a whole lot of object oriented concepts. I've got plenty of inherited classes, some interfaces, and just a lot of other things to take advantage of C++. Then the other day I was browsing threw LaMothe's book Tricks of the Win Game Programming Gurus, and he said to limit your useage of it, to not go "class crazy." Personally, I love how organized my code is. I realize that sacrafices a little speed here and there, but I'm not working on Half Life 2 here, so it not that big of a deal is it? And to tell you the truth, I can't imagine the guys at Valve would be writing in straight C anyway. I respect LaMothe's opinions greatly, but this comment of his seems counter-intuitive to me. But since I don't have much expeirence my intuitions much be misguided. So for all of you who have been game programming for years now, what do you think about using a lot of object oriented techniques in your code?
__________________________We're all Dumb And Jaded
Advertisement
i haven't been OO game programming for years.
but i feel that you shouldn't use every OO technique there is.
whether it's for speed or for plain readability.

some people on this boards (and there's very few) tend to use techniques just because they can and the techniques has no real impact on their game.

singletons, polymorphism, 3 level inheritance, virtual functions every which way... is alot of that necessary? even in a 3D game (Q1 level game)?

oh well, just my opinion.

Beginner in Game Development?  Read here. And read here.

 

Just do whatever you can to hide complexity and make your code maintainable.
OO can help with this :)
I've found that interface based design usually is more flexible and easier to understand and refactor than implementation inheritance or deep inheritance hierarchies.

I e, I wouldn't have "Thing" from which "MovableThing" and "StaticThing" derive, from which "MovableLivingThing" and "MovableVehicleThing" derive, ... "Actor" ... "Player". Because, suddenly I'd realize that "Horse" is a "MovableLivingThing" but can be ridden, just like "Car" that's (indirectly) a "MovableVehicleThing".

Instead, there would be "Thing", and then you query for specific optional interfaces, such as "Ridable" and "Movable".

Anyway -- this is still object oriented design, just applied differently. "OO" is a very broad and loose concept, and applied appropriately, it helps organize most code bases. I think LaMothe is saying "apply it appropriately".
enum Bool { True, False, FileNotFound };
Lamothe is a good guy for sure and I own alot of his books. However, lately I've come to believe he isn't as great as alot of people think (myself included, once upon a time.) After all, if he were such a great programmer he'd probably be programming new and exciting things rather than re-hashing the same old books over and over.

Anyhow, I don't think his oppinion deserves as much wieght as people want to give it sometimes. OOP has its place, it sounds as though you're using it right to me. There is such a thing as "class crazy" though, where everything and every variation becomes its own class, thats what you want to avoid.

The classic example is weapon classes, you don't need a seperate class for every single weapon, it usually suffices to have an umbrella class which has properties describing how each sub-unit is different. IE- a dagger does 5 damage while a broad sword does 50. Damage is a property of a weapon and doesn't need a whole new class just for that.

OOP is a tool, just like anything else, but as the old adage goes: When all you've got is a hammer, everything starts to look like a nail. Realize that there are alot of tools and techniques at your disposal.

throw table_exception("(? ???)? ? ???");

Quote:Original post by hplus0603
I've found that interface based design usually is more flexible and easier to understand and refactor than implementation inheritance or deep inheritance hierarchies.

I e, I wouldn't have "Thing" from which "MovableThing" and "StaticThing" derive, from which "MovableLivingThing" and "MovableVehicleThing" derive, ... "Actor" ... "Player". Because, suddenly I'd realize that "Horse" is a "MovableLivingThing" but can be ridden, just like "Car" that's (indirectly) a "MovableVehicleThing".

Instead, there would be "Thing", and then you query for specific optional interfaces, such as "Ridable" and "Movable".

Anyway -- this is still object oriented design, just applied differently. "OO" is a very broad and loose concept, and applied appropriately, it helps organize most code bases. I think LaMothe is saying "apply it appropriately".


The phenomenon you are describing here seems a huge lot like interfaces. Instead of having:

ThingMovableThingRidableThing[oops] Car

you have:

Thing,IMovable,IRidableCar : IMovable, IRidable

I prefer to use the last one which is very comfortable and easy to implement, so, I second hplus.

/edit:
Forgot to add that a certain base class is usefull for ingame objects, so the default behaviour doesn't have to be rewritten everytime
Quote:Lamothe is a good guy for sure and I own alot of his books. However, lately I've come to believe he isn't as great as alot of people think (myself included, once upon a time.) After all, if he were such a great programmer he'd probably be programming new and exciting things rather than re-hashing the same old books over and over.


I have to disagree with you there. I'm sure people give Lamothe more credit than necessary but he's still a helpful person, and a lot of his books are helpful especially to beginners.

I do disagree with his use of straight C though. Alpha_ProgDes
if you feel you've organized your code efficiently, and haven't done a lot of advanced OOP features to waste, then that's good for you.

Lamothe may code in straight C, but it's pretty easy to convert the concepts he gives you and how to implement them, so you can use them in your own C++ code.

Quote:Anyhow, I don't think his oppinion deserves as much wieght as people want to give it sometimes. OOP has its place, it sounds as though you're using it right to me. There is such a thing as "class crazy" though, where everything and every variation becomes its own class, thats what you want to avoid.


Another thing you have to take into consideration Alpha_ProgDes. A lot of things out there don't need to be classes or use all the versatility that C++ offers. Certain thigns can be static arrays, or plain old structures. Keep that in mind, develop your own style that works for you and is cool and you'll be all good.
Quote:Original post by hplus0603
I've found that interface based design usually is more flexible and easier to understand and refactor than implementation inheritance or deep inheritance hierarchies.

I e, I wouldn't have "Thing" from which "MovableThing" and "StaticThing" derive, from which "MovableLivingThing" and "MovableVehicleThing" derive, ... "Actor" ... "Player". Because, suddenly I'd realize that "Horse" is a "MovableLivingThing" but can be ridden, just like "Car" that's (indirectly) a "MovableVehicleThing".

Instead, there would be "Thing", and then you query for specific optional interfaces, such as "Ridable" and "Movable".


can you please explain this more... right now in my game im doing what you describe... i have Thing from which MovableThing and StaticThing derive, etc.....

"Instead, there would be "Thing", and then you query for specific optional interfaces, such as "Ridable" and "Movable"."

what do you mean by this? exmaples and stuff would help. thanks a lot!

also, you write:

"I've found that interface based design usually is more flexible and easier to understand and refactor than implementation inheritance or deep inheritance hierarchies."

could you explain what the interface based design and implementation inheritense / deep inheritense is? thanks a lot!

FTA, my 2D futuristic action MMORPG
There are two kinds of inheritance, basically: inheritance of interface (the kind you get in Java when you use keyword 'implements', or in C++ when you inherit a completely pure-virtual class), and inheritance of implementation (the kind you get in Java when you use keyword 'extends', or in C++ when you inherit in general).

"Interface-based design" basically means that you are making more use of the former. You might also inherit implementation here, and use multiple inheritance of implementation (in C++), but you are then thinking of the inherited classes more as "mix-ins". Personally, I prefer to handle these by object composition and delegation. "delegation" and "polymorphism" are basically the key (and orthogonal) concepts here; "inheritance" and "composition" are both ways of obtaining "delegation" and "polymorphism". (By doing object composition, you can acheive more flexibility in your polymorphism without shattering your brain or using weird things like virtual inheritance; but at the cost, generally, of having to do delegation manually.)

"Deep inheritance" is not a technical term, it just means that your tree of inherited classes is rather tall. I.e. you have A which inherits from B which inherits from C which ... etc. so that there are several layers. (LOL, I remember when I was first learning to program in BASIC, and my teacher asked me if I wanted to see a "long program", and I thought that was a technical term for some reason! It wasn't even that long, a couple thousand lines maybe, but back then when you could still find Commodore 64s in use, it seemed pretty substantial.)
There's a tendency for people to get wrapped up in the object oriented design paradigm as if it were a religious practice. I think the best advice anyone can give you is that you shouldn't stress over it. There's a thing called analysis paralysis, and I see too many people fall into it. It's very easy to do when you sit down to architect the perfect design using the latest and greatest OO concepts.

Using OO design concepts can go a long way in improving the maintainability and extensibility of your code base. The Unreal Engine is an excellent example. But they designed it that way from the beginning because they wanted an engine that they could port to several platforms, use again and again for several years, yet still be able to easily upgrade. The architecture they came up with would likely have been less flexible had they taken a different approach.

I'm sure that the design goals of most people around here do not fall in line with Epic's goals for the Unreal Engine. In most cases people are just wanting to make a game and learn something in the process. In that case, I say do what feels right. Get it done. Good software design, whether you use OO concepts or not, comes from experience with software design. Using OO techinques can still lead to a pile of spaghetti very easily (look up the terms tight coupling and loose coupling). Spending all of your time designing an engine, then throwing it out and doing it again because you over engineered yourself into a corner, is less time pumping out a game.

If you remember that Object Oriented design does not mean using classes (you can easily apply OO techinques to C, you just don't get built in support to make the implementation easier), and if you keep in mind that the best design is the one that allows you to meet the goals of your project (whether that be the Unreal Engine or a Tetris clone), then there's nothing to be concerned about. Eventually, you start to see the benefits of certain design concepts and, more importantly, learn to recognize where to apply them.

Quote:
So working on my game engine, I've been finding myself using a whole lot of object oriented concepts. I've got plenty of inherited classes, some interfaces, and just a lot of other things to take advantage of C++.


Two things stand out about these two sentences that I think are the wrong attitude.

The first is the fact that you are making a game engine. Too many people sit down to make a game and think the first thing they need to focus on is a 'game engine'. I say, you need to focus on the game. There are many legitimate reasons to make a 'game engine' (to license to others, to support multiple future titles, for the learning experience). But for most people on these boards who are still learning, I think the best thing to do is to forget even the concept of 'engines' and just make the game. Make as many games as you can. This will lay the foundation you need, not just on the implementation details (like graphics algos), but more importantly for design. Building a game engine that you aren't likely to use again, or even complete, is a waste of time. Coming at it with insignts gleaned from slapping together four or five games will improve not only the chances of completing it, but also of having something that can be easily reused and extended.

The second thing is this bit:

Quote:
I've got plenty of inherited classes, some interfaces, and just a lot of other things to take advantage of C++.


Never implement features just to take advantage of the language. Instead, use the language features to the advantage of your project. Inheritance and interfaces are quite useful - in specific cases. For example, there are some cases when composition is a better solution to a problem than inheritance. You need to choose the language features that meet your design needs, not shoehorn your design to make room for the features. It's very easy to bloat your code with things you don't need. Every design decision should be given careful consideration. This is the sort of thing which comes with experience, of course. All of the threory in the world is useless until you've actually applied it and seen the results firsthand.

Quote:
what do you think about using a lot of object oriented techniques in your code?


It's not about using 'a lot of object oriented techinques'. It's about applying design solutions to design problems. Some people go to such extremes to follow 'good OO design' (I have yet to figure out exactly what they're on about) that they do the silliest things. I could rant on and on about the silly things people do to achieve OO nirvana. Let me tell you - it doesn't exist. Layout the requirements for your project, spend some time to determine how you are going to meet those requirements, implement, profile, debug, refactor, move on to the next project. Let others squabble about the finer details of public vs. private member variables.

This topic is closed to new replies.

Advertisement