Writing a game engine

Started by
116 comments, last by freeworld 12 years, 4 months ago
I asked my teacher if I could write my own code for the game and he said yes with a big smile. He gave some encouragement that it will very good for my portfolio but he also said it will be hard and I need to start now. Well I'm starting now..
I got a really good teacher, and he is funny too. ( he always tells a big and cool story of a subject :D )

And hey,! You just said, " You go from 'zero' to 'hero' ... I am doing that and then you say I'm setting up for failure.. :unsure:

My teacher really believes I can do this, so do I. I don't need any discourage now..
And I am not starting from zero. I know how to load/draw images, text, lines, etc. I know how events work. I got enough basics.

Look at those ways in the previous link please and tell me which one is the best.
Advertisement
Don't be discouraged! biggrin.gif
Just keep in mind that you're making this 'engine' only for this current project's needs, and not because it's the great next engine that people will use for years to come, and that way you'll always be working towards your project's goals.

If you've got to cut corners or do things not-quite perfect, it's ok, as longs as you're helping the project along.
That is the point of my engine that I want to write now. ( sort-of-engine I mean )
I'm not writing an engine now for millions of people because there are a lot better engines that I can't beat with my experience.

But like I said, I don't want to learn the 'wrong' way of programming. There are tons of wrong ways and I want to learn zero of them. And so I am asking for the good ways here. I wrote some code http://pastebin.com/VUMEjVpC

I like the 4th way, because I gives me some freedom. But is that a good way of programming? No idea.
Are there better ways then the ways I have in mind?
I still got a Painter and Recource class but I use heritance here.
[font="Courier New"]class GameEngine: public Painter, public ResourceLoader[/font][/quote]This is a common pattern, where you inherit a class simply to gain it's functionality. Using inheritance like this is often simpler to implement than using composition.
However, it does bend a few OO rules -- usually inheritance is for [font="Lucida Console"]is a[/font], and composition is for [font="Lucida Console"]has a[/font]. It's tempting (and sometimes valid) to use inheritance for this, but generally using member variables is more correct in regards to large-scale engineering concerns.
[font="Courier New"]GameEngine engine = GameEngine::GetInstance();[/font]
[font="Courier New"]engine.StartUp( 640, 480, _T("Game Engine"), 60 );[/font]
[font="Courier New"]engine.Shutdown();[/font][/quote]You can simplify this by using constructors and destructors, and instead of using globals/singletons, you can give these variables the same scope as main has:class GameEngine
{
public:
GameEngine( int w, int h, char* t, int r )
: painter(w,h,t,r)
, resourceLoader() { StartUp(); }
~GameEngine() { Shutdown(); }//N.B. calls painter.~Painter() and loader.~Loader()
Painter painter;
Loader loader;
};
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
GameEngine engine( 640, 480, _T("Game Engine"), 60 );
Image* pImage = new Image( engine.loader, "image.bmp" );
while( engine.ProcessMessages() )
engine.painter.DrawImage( pImage, xPos, yPos );
delete pImage;
return 0;
//N.B. engine.~GameEngine() is called here
}
You can also pull the painter/loader out of the game engine object like this:class Painter
{
public: Painter( GameEngine& e ) : engine(e) {}
private: GameEngine& engine;
};
class Loader
{
public: Loader( GameEngine& e ) : engine(e) {}
private: GameEngine& engine;
};

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
GameEngine engine( 640, 480, _T("Game Engine"), 60 );
Painter painter( engine );
Loader loader( engine );
Image* pImage = new Image( loader, "image.bmp" );
while( engine.ProcessMessages() )
painter.DrawImage( pImage, xPos, yPos );
delete pImage;
return 0;
//N.B. resourceLoader.~ResourceLoader() is called here
//N.B. painter.~Painter() is called here
//N.B. engine.~GameEngine() is called here
}

I want to have the feeling with this game that -> I <- made it all on my own.
[/quote]

Just because you used a nailgun to build that house doesn't mean it was any less of an accomplishment than using a hammer; it just means you built a better house in less time.
@Hodgman:

Thanks for the code.
Just a question of that GameEngine. Suppose the engine is ment for others ( it isn't don't worry ) but just suppose. Will it be stable then? Because the user can make many GameEnine objects, what is not the plan. ( but the user don't know that ). Is there a way to avoid multiple objects of the GameEngine?

Image* pImage = new Image( engine.loader, "image.bmp" );
I will always put 'engine.loader' in that method. So I better use a callback in the Image class that will ask the loader of the GameEngine.

I think I'll use the first way of code. So I won't need a lot of loader/painter/inputstate pointers/objects.
A bit of terminology - what you are describing might be better called a library. Everyone probably has their own definition for things - but a library is at heart a collection of related functions that make certain things easier (or possible).

A game engine could perhaps be considered a very large library or collection of libraries, but the term "engine" implies (to me at least) quite a large amount of functionality and a level of abstraction that's hard to get right.

The 'engine' I got from school I don't like because:
- it don't have any performance at all / terrible names for datatypes ( maybe because we need to understand it )
example in header:
Code I use: Object* m_pObject;
Code the 'engine' have: Object* m_MyObjectPtr;
- The WinMain we never wrote because this was already implemented in the engine. Almost no one of my class knows how WinMain works.

These are the 2 things I don't like. I know the priority is to make the game. But I want to do more.. I am already 3weeks ahead with the lessons.


-How do you know "it don't have any performance at all" ? Are you getting high frame times / low framerates?
-I can see how the variable naming can be a turn-off...
-Why do you dislike the fact that the engine already implements WinMain? Does that prevent you from doing something?

I think it boils down to this: you WANT to write an engine, and you dislike the existing engine because it's not yours... So you will write your own and can't be convinced otherwise (nothing wrong with that). No one can tell you what to do, but the suggestions you've seen are based on previous experiences.

It won't be a wasted effort, because you will learn a lot. However, just be careful and follow a schedule to make sure you meet the requirement for the course instead of finding yourself implementing engine features forever. It's fun to work on "engine code", but at some point you will have to make a game with it. It sounds obvious but it's easy to forget.

Good luck, I'm looking forward to seeing your game. If you want to, post your progress on this forum. It's always interesting to see how things begin and how they end up. I mean this in a good way (you're probably going to make changes to your original design/framework/etc). And this info can be very valuable to others.


EDIT: I also suggest adding time for "engine bug fixing" to your schedule. Some bugs will be noticeable with simple tests, but other bugs will only show up until you start writing the real game. I've seen bug databases for some software products end up with hundreds of bugs.
Well performance is a big word :rolleyes:

I write this for getters/setters:

inline void SetTitle( const string& sTitle );
inline tstring& GetTitle() const { return m_sTitle; }


This are the methods in the engine:

void SetTitle( string sTitle );
tstring GetTitle() { return m_sTitle; }


I know this is not much, but I just want to work properly.
But I'm not allowed to copy that and change those methods, I'll be kicked of school then and my chance on work is gone.
And his code is not bug-free.

I can call the initialization many times, so it will everytime make a class with the same name and same instance and hwnd ( what can't work ). His code is not stable at all.
Those things I can avoid.

At least if I know how to make the user able to make the GameEngine object only once without a singleton. Is this even possible?


Ok and thanks, I will progress on this forum but where? Should I post it here ir is there a special topic for WIP's?

At least if I know how to make the user able to make the GameEngine object only once without a singleton. Is this even possible?

You can definitely do this without the use of a singleton. See the following snippet:

class MyClass
{
public:
MyClass() : mInitialized(false) { }
~MyClass() { }

void initialize() {
assert(!mInitialized);
// do initialization here
mInitialized = true;
}

void shutdown() {
assert(mInitialized);
// do shutdown logic
mInitialized = false;
}

private:
bool mInitialized;
};


The above leverages the assert function that will throw a runtime exception if the expression evaluates to false. This way, if I call initialize() more than once without calling a shutdown() in between then it will throw an exception. Additionally, if I call shutdown before calling initialize or call shutdown more than once, it will throw the same runtime exception, thus making it very obvious to the developer that some code is executing out of order and should be fixed.

Depending upon the situation, some bugs can easily be logged and the application will continue to function without stability issues; however when core code such as initialization/shutdown features are used out of order or fail to properly do their job, faults should be very clear which is what assert is meant to do in this case.

This topic is closed to new replies.

Advertisement