Engine Conceptualization

KiroNeem
Unregistered
 
Post: #1
Because of certain reasons I will be building a game engine for my future games. I have read things here and there about game engine design, and I thought my best place to start would be building a conceptualization first. After looking what I had written I realized that each feature I have done before, just not in one cohesive project. So to say the least, I know this will be a big task, although I am confident that I can do it. Yet I wanted to pass off what I have to the idevgames community to see if there may be anything I am missing, or if there may be some flaw in my logic. >.< Just as a note my conceptualization is ment to be breif and to the point, later I will expand on it in full detail.

Game Engine Conceptualization

Key Features: cross platform, network capable, modular, reusable
Core Features:
3d sound (OpenAL),
2d/3d graphics (OpenGL),
windowing/full screen (AGL, WGL, OS specific but abstracted from the user)
3D model/animation support (LWO, LWS, maybe more),
appropriate file loading (PNG, OGG, ect),
networked client/server (Posix Sockets),
managed play environments including BSP or Oct Tree,
automatic visibility culling,
physics/particle support,
menu system creation,
event management (Win32, Carbon or Cocoa),
keyboard mouse joystick input and configuration,
misc toolkit classes


Platforms: Mac OSX, Windows XP, maybe Unix...
Compilers: GCC
Languages: C/C++

Implementation: The proposed game engine plans to be a reusable and will be the backbone of many of my new games. The design should be simple to use, creating a level of abstraction between the game code and what is really going on by the system. Also most of the code will be written with classes, allowing you to create custom sub classes to extend the engine if necessary. Because of the engine plans to be modular, not all aspects of the engine has to be used at once. This will allow a few things, the over head to be tailored to what you are doing, and allowing you to write non-game applications if wanted. If implemented as such I would expect this will allow old game code to see little revision, and new game code to be written easier.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
Write a game, not an engine. Then write a second game, reusing some code from the first. Now you have an engine -- the code that's the same between those two games. Rinse, repeat, and watch your engine grow.

Only hobbyists program engines. Even the big name engine companies don't program an engine -- they program a game or two, with an experienced eye out for places that need to be generic.
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #3
Nice one OSC Smile

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #4
Agreed. You don't truly know everything you need until you actually build the game. You will probably end up re-writing parts of your engine regardless, since your needs always change game to game. Most commercial games don't stick to one engine, and even all the Quake III engine spinoffs have modified the engine.

Now to the shameless self promotion. Rasp For models and animations, I'm working on something like that myself, and I'm making an open source framework (as well as an accompanying helper application) for just that. You can see my first demo (which I just released yesterday) here. Right now it only imports obj models, but you should be able to edit the source of the utility to import lwo. I tried to make it as flexible as possible, and you could also both edit the data in the model directly, or the source code of the framework if that doesn't give you what you need, if you want to have it do something special. Oh, and you can also add collision surfaces from the utility and use them from the framework, and it uses ODE (in fact, it contains ODE internally) so you can use those collision surfaces with ODE collision surfaces. I hope to finish by summer.
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #5
I'd just like to point out that writing an "extensible & modular" game engine in C++ is an oxymoron. C++'s class system is very inflexible, and an established hierarchy is almost impossible to extend beyond the original conception.

If you want flexibility, you must use a dynamic language.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #6
I think you're going a bit far with that statement. It's perfectly possible to have a modular system with subclasses and virtual pointers. You may have to jump through a few hoops at times, but I wouldn't say that it's impossible (or even "virtually impossible") to have it be "extensible and modular."
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #7
akb825 Wrote:I think you're going a bit far with that statement. It's perfectly possible to have a modular system with subclasses and virtual pointers. You may have to jump through a few hoops at times, but I wouldn't say that it's impossible (or even "virtually impossible") to have it be "extensible and modular."

I'd be glad if you'd explain what the heck virtual pointers are supposed to be. And modular is not the same as extensible. Modularity can be achieved through the use of clear interfaces, to a certain extent.

Your "jumping through a few hoops" for extensibility basically means that you end up using functions and function pointers which use void pointers as their arguments and return values, which entirely defeats the purpose of compile-time type checking, and you will be left in a big mess trying to debug things due to the lack of runtime dynamism, your interfaces will be far from self evident, and sane memory management will be near impossible.

Modularity also means that you can exchange parts of the program without affecting the others, which is again hard to do without resorting to the former techniques. Of course, you can implement any sort of functionality in C, in assembler even, but it will not even come close to being easily extensible, let alone being maintainable.

Even commercial game engines are very rigid, and are largely modified with the help of their scripting languages.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #8
You don't necessarily have to use void pointers and function pointers. You could do the same thing with a subclass and virtual functions. Basically, you subclass the base class with a virtual function, then you can override that function in the subclass. It's almost like using function pointers with void pointers, but there's some type checking involved with the fact that you need to have a subclass of the class of the class it's declared to take or return. If you don't at least have a vague idea what you're supposed to have in the function (aka: what to use as a base class should be), there's no real point in writing the function in the first place. Also, you can do runtime type checking if you wanted to inside the overriden fucntions using typeid or dynamic_cast. Through subclassing, you can add any new functionality you need anyways.

I personally like to keep dynamic types, such as id in Cocoa, at an arms length. Though it's sometimes nice to just be able to send a message to an object, I often get useless warnings saying that there's multiple functions with the same name (when I know what the type will be) and won't check for errors at all, since any function call period is valid. I personally prefer the C++ method of where you can have generics through templates or subclass for similar functionality. That way, the compiler can actually do something useful for error checking when you're working with more than one type.
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #9
akb825 Wrote:You don't necessarily have to use void pointers and function pointers. You could do the same thing with a subclass and virtual functions. Basically, you subclass the base class with a virtual function, then you can override that function in the subclass. It's almost like using function pointers with void pointers, but there's some type checking involved with the fact that you need to have a subclass of the class of the class it's declared to take or return.

Let me just start off by saying that I have a few hundred thousand lines of C++ code under my belt. So I think I know how OO works (or doesn't) in C++.

To be able to write a good base class, you need to know exactly what you will need. You have to define the capabilities of your classes at compile time. This means that you either end up with a very rigid structure, or a large number of empty, and therefore useless, virtual functions that are overloaded or not in the subclasses. Inflexibility or crud, that's the choice. Or, if you don't know very well what you are doing, you will get both.

Quote:If you don't at least have a vague idea what you're supposed to have in the function (aka: what to use as a base class should be), there's no real point in writing the function in the first place. Also, you can do runtime type checking if you wanted to inside the overriden fucntions using typeid or dynamic_cast. Through subclassing, you can add any new functionality you need anyways.

You don't understand. You cannot describe everything with a rigid class hierarchy. dynamic_cast is a very poor substitute to, for example, Objective C's respondsToSelector: method. It is just much more elegant and much more powerful. The "is a" relationship used for subclassing is more often than not stretched beyond the limits of reason in C++, only because it is the only way to use the dynamic runtime features.

Quote:I personally like to keep dynamic types, such as id in Cocoa, at an arms length. Though it's sometimes nice to just be able to send a message to an object, I often get useless warnings saying that there's multiple functions with the same name (when I know what the type will be) and won't check for errors at all, since any function call period is valid. I personally prefer the C++ method of where you can have generics through templates or subclass for similar functionality. That way, the compiler can actually do something useful for error checking when you're working with more than one type.

You seem to have a fundamental misunderstanding of how Objective C works. You don't call functions. You send messages. At the end of the day, the messages will translate to the equivalent of function calls, but there is a whole dynamic runtime in between. Which is good.

The "useless warnings" you get can be eliminated by casting, or alternatively, by better method naming. And not any message is valid.

You say you prefer generics through templates. That sentence doesn't even make sense outside of C++. Have you tried any language other than C/C++? Templates are basically just type-safe macros, and debugging them is certainly no easier nor more fun than debugging macros. Just look at the Cocoa containers in comparison to the STL ones, they are worlds apart. The Cocoa ones are just infinitely more elegant and useful.

C++ is as good for doing OOP as a tricycle with only two wheels is for making a trip around the world.

I strongly suggest you try to broaden your horizon and look into some of the more elegant programming languages, such as the good old Haskell, Lisp, Smalltalk, or some of the more modern ones like Python, Ruby, and Io. You need to shed your concepts of C++ OOP in order to really understand the object oriented paradigm as it was meant to be. And by looking into functional and prototype based languages, you can learn a whole lot more. The concepts these languages embody can be carried to back to C/C++, even.

Don't claim to know how to fly a plane when all you have done was riding a bicycle.
Quote this message in a reply
KiroNeem
Unregistered
 
Post: #10
OneSadCookie Wrote:Write a game, not an engine. Then write a second game, reusing some code from the first. Now you have an engine -- the code that's the same between those two games. Rinse, repeat, and watch your engine grow.

Only hobbyists program engines. Even the big name engine companies don't program an engine -- they program a game or two, with an experienced eye out for places that need to be generic.

I see where your coming from, and agree that the experience and code you gain from just programming a game is invaluable. For the most part the features i'm thinking about for this engine are things I have build before, just not all working and written in a standard way. I may have been a little over zealous calling it an engine, because I see what you are saying to be very similar to what I'm doing.

Now I may not be as experienced as some people in the independent development field, although I can still see a major advantage to building an engine or at least a framework that you can reuse. Game to game the engine/framework is always going to change, because no two games are the same. Yet If planned out correctly I am confident that you can make it extendable and even modular to an extent.

Looking back at it now, maybe a complete modular design would just be shooting myself in the foot. Although I think that some practices can still be implemented that will make eventual change easier for you along the way. To achieve this modularity you need some base that everything can connect to, and things will get ridged the father down the tree you go. Although if you keep things far enough away from each other then you should be fine with creating new code and not using other code. To create a truly modular environment you would most likely end up writing custom connector code, although I now agree that would be more then is really needed.

Putting all the cool features aside, one of the most valuable aspects of creating a standard engine/framework is to have an abstraction layer between my game code any any system specific code. Much like GLUT and many of it's spin offs.

I see it as a means to an end, and not another quake 3 engine.
Quote this message in a reply
KiroNeem
Unregistered
 
Post: #11
DoG Wrote:To be able to write a good base class, you need to know exactly what you will need. You have to define the capabilities of your classes at compile time. This means that you either end up with a very rigid structure, or a large number of empty, and therefore useless, virtual functions that are overloaded or not in the subclasses. Inflexibility or crud, that's the choice. Or, if you don't know very well what you are doing, you will get both.

akb82 Wrote:If you don't at least have a vague idea what you're supposed to have in the function (aka: what to use as a base class should be), there's no real point in writing the function in the first place. Also, you can do runtime type checking if you wanted to inside the overridden functions using typeid or dynamic_cast. Through subclassing, you can add any new functionality you need anyways.

I would have to agree with akb825 here. If you don't know why a function/method should be used then don't write it. The main part of designing your program before you build it is to work out these questions so that you don't find yourself lost in your own code. Simply if you don't know why you are writing the code, then don't.

To me is seems like you are talking about a level of modularity beyond the capabilities of C/C++ and even Objective-C. I'm not saying that those are the only languages out there, although I don't see why the industry standard is such a bad thing. C/C++ is not perfect, no language is, although for the most part you can get things done quickly and still with little memory. Also for what is not supplied by the language can easily be build because of how generic C/C++. Just look at the MVC structure which is completely language independent. http://ootips.org/mvc-pattern.html There has to be some happy medium in between flexability and structure.

I think that even this comes down to a means to an end, and I think that the gaming industry has proven that these things can be done withing C/C++.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #12
DoG Wrote:*snip*
Though I still disagree with some points, I won't press any further since I do have a lot less experience and haven't learned any of the other languages you mentioned. (I've only really learned Java, C, C++, and ObjectiveC) I would have to say that I would do the way described as "crap" for C++. As I learn more, I may see things your way as far as OO paradigms are concerned, but until that time I will continue to do what I have found works for me. As I come across other techniques and possibly run into problems with larger projects, I will adjust and learn as needed. Perhapse over the summer I will try out some of the languages you have mentioned.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #13
Every word DoG says is true. If you haven't had the pleasure of programming in Python, Ruby, or similar, go out and learn one now!

C++'s poor excuse for OO just leads to horrible designs, overuse of inheritance, and egregious hackery (c.f. Qt's MOC).
Quote this message in a reply
Post Reply