• Advertisement
Sign in to follow this  

Writing a game engine

This topic is 2255 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

@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.

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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'll be the only user, right? I'm sure you can keep yourself from making more GameEngine objects ;)


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?


Not sure about this, my guess is on this same post, but maybe posting progress would be off-topic...

Share this post


Link to post
Share on other sites
Hmm I don't think that will solve the problem.

Suppose I write the GameEngine with that bool;

GameEngine object1;
GameEngine object2;
GameEngine object3;

object1.Initialize();
object2.Initialize();
object3.Initialize();


I can only have 1 GameEngine object but with that code I can write multiple objects.
I'm not sure but I think a 'static bool m_bInitialized'' will help.

As soon this is set to true once, it will always be true in the whole application ( at least if you don't change it to false again ). I'll test in tomorrow.


Yes I'm the only user, but I asked in the question " suppose if the engine is for more users ". Edited by turbello

Share this post


Link to post
Share on other sites

[quote name='turbello' timestamp='1323200709' post='4891189']
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'll be the only user, right? I'm sure you can keep yourself from making more GameEngine objects ;)
[/quote]
Agreed; however I'd argue there is a valuable lesson in writing fault tolerant code too.

Share this post


Link to post
Share on other sites

Agreed; however I'd argue there is a valuable lesson in writing fault tolerant code too.


Agreed smile.gif

Share this post


Link to post
Share on other sites

Hmm I don't think that will solve the problem.

Suppose I write the GameEngine with that bool;

GameEngine object1;
GameEngine object2;
GameEngine object3;

object1.Initialize();
object2.Initialize();
object3.Initialize();


I can only have 1 GameEngine object but with that code I can write multiple objects.
I'm not sure but I think a 'static bool m_bInitialized'' will help.

As soon this is set to true once, it will always be true in the whole application ( at least if you don't change it to false again ). I'll test in tomorrow.


Yes I'm the only user, but I asked in the question " suppose if the engine is for more users ".


Correct, from the above perspective nothing stops you short of using some global/static locking mechanism or singleton; however at some point we must assume that the developer has to hold some level of responsibility. If you are writing this for yourself, then that responsibility is on you. If you were writing a framework for others, then there is a certain level of responsibility on the developer using your framework. We can only document how classes are to be used and how they interact and expect others to follow the blueprint and if they deviate from that, consequences must be dealt with.

Just because the singleton pattern will prevent the above from being a problem does not warrant it's use was my underlining concern. The use of singletons have a time and place and it's usually rare to non-existent. They can make our lives easier at first but lots of times, many of us have used them to later regret the use because a future requirement goes against the use of a singleton. For example, imagine you limit a class to a single use per application; however you decide to consider threading options downstream. If that class needs to be created in each local thread, the singleton pattern won't work for this and now if you've referenced that class as a singleton throughout your code, now you have a huge effort to retrofit it as a non-singleton.

Anyhow, as gsamour said, you're the only user so it's ok - you shouldn't be creating multiple copies of that class anyhow if you designed it that way. That's ultimately nothing different than say my EntitySystem class which can be created multiple times if I wish to have various entity systems running in my engine, but I only need one and the engine is responsible for creating that instance for me, I simply use the allocated object in my game code :).

Share this post


Link to post
Share on other sites
Thanks for the fast reply.

For my progress I will make a new topic so the progess itself is on-topic :wink:

Share this post


Link to post
Share on other sites

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;
};





Change that to a static.
class MyClass
{
public:
MyClass() {
assert(!mInitialized);
mInitialized = true;
}
~MyClass() { }

void initialize() {
// do initialization here
}

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

private:
static bool mInitialized;
};



bool MyClass::mInitialized = false;

Now it is not possible to make 2 of this class (threading issues aside).
Add #ifdef _DEBUG for less release-mode clutter.


L. Spiro

Share this post


Link to post
Share on other sites

You have a deadline of a few months and have only been studying for 1 year. There is a very small chance that you would be able to write a “better” game engine with the same features as theirs plus the actual game on top of it.

Additionally, the chances are absolute that your engine will not be better than theirs. That is not an insult, but a fact. Everyone makes a crappy engine the first time.
Engines are all I make and my first one, with 8 years of C++ experience and 3 or 4 of professional game-development experience (and 5 or 4 prior years of hobby game programming) at the time, was crappy.


The right direction to go is straight back to the folder containing the engine they gave you.
Save engine programming for hobby time. Not for the graded deadline time.


L. Spiro


I'm with you, I've written a few engines in my time and every time they fall short of exactly what I want to achieve. If anything, dude should take that engine they gave you, and improve it wherever you can to make it easier to use. (If it's a c-style engine, do some wrapping, if it's a c++ style engine, find some ways to improve the functionality in a few key areas)

For turbello, I spent my uni time writing engines too, in the time frame I had to write them, they were pretty crappy, I learnt a fair deal writing them, but in hindsight I would have learnt more if I spent that time adding new features to an existing framework, then I would have been learning new features and not how to build simple engines in DirectX/OpenGL. And yes I'm working on my own engine at the moment, but that's because I want a specifically structured engine, with specific supported features; but I'm still a hypocrite regardless.

From what it looks like, you're not building anything advanced (GDI drawing basically) that's only a few weeks work, but still it is better to spend those few weeks porting the code they gave you to a better structure (because your engine and theirs will have a lot of matching code segments here and there ) then it is going through the hell of windows programming in a from scratch project. Thinking about it, for my win32 stuff I'm writing now, I wish to God I had some fucking base code to port to my project, because windows programming sucks.

And I'm probably going to be crucified for this, but in the code you posted, I prefer the third method, because it reduces the number of pointers you've got flying around, in fact I think it's brilliant.

Share this post


Link to post
Share on other sites
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?
If you write clean code, it shouldn't matter if the user decides to make 2 game engine objects... IMO you're worrying way to much about something that has zero impact on the project.
a) your code should still work if the user creates 2 game engines, so there's no reason to spend time programming this restriction into your project.
b) the user isn't going to create 2 game engines anyway, because the user is you! So you're spending time programming features that the project doesn't require...

Share this post


Link to post
Share on other sites

Yes I'm the only user, but I asked in the question " suppose if the engine is for more users ".


I laughed and I cried. Have you even worked on your actual assignment yet? You should take the majority of the advice given here and use the code that was given to you. If you believe building an engine is so easy, then modifying and existing framework, should be a breeze.

Share this post


Link to post
Share on other sites
Kyall,
I know my engine will look as good as the engine i've been given. But if I copy and change some stuff, I don't learn alot from it, I won't go deeper into the code I copied.

If I write it myself I need to know what I am doing and how it works so that way I learn what it all does.

You won't be crucified for it trust me :)



Hodgman,
yes, my code will be safe now because I'm the only user now. :)


freeworld,
I never said writing an engine was easy.. After some of you adviced me not to write it but focus on the game itself. I'm still not going to listen sorry. I'm hard headed :lol:
I didn't asked of I should write an engine or not. I was asking if I was going in the right direction.
With keeping saying I should not write it I'm losing important time.. :)



I'll use the third way and I'll make a new post with the progress. I'm now testing all events :)

Share this post


Link to post
Share on other sites

Hmm I don't think that will solve the problem.

Suppose I write the GameEngine with that bool;

GameEngine object1;
GameEngine object2;
GameEngine object3;

object1.Initialize();
object2.Initialize();
object3.Initialize();


I can only have 1 GameEngine object but with that code I can write multiple objects.
I'm not sure but I think a 'static bool m_bInitialized'' will help.

As soon this is set to true once, it will always be true in the whole application ( at least if you don't change it to false again ). I'll test in tomorrow.


Yes I'm the only user, but I asked in the question " suppose if the engine is for more users ".


There won't be more users. These game engines (and dozens more like them) exist and are free for non-commercial and/or students projects:

http://unity3d.com/
http://www.udk.com/
http://www.crydev.net/

Therefore nobody will ever care about or use the engine you made in one month for a class project. Worrying about "other users" making a second game engine object in your code is tantamount to studying what techniques Jessica Alba enjoys in the bedroom. The likelyhood of you dating her and someone using your class project game engine are about the same - 0.00000%.

Please ... just make the game. Do not code anything unless it is aboslutely needed to complete the game.

Share this post


Link to post
Share on other sites

Change that to a static.
class MyClass
{
public:
MyClass() {
assert(!mInitialized);
mInitialized = true;
}
~MyClass() { }

void initialize() {
// do initialization here
}

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

private:
static bool mInitialized;
};



bool MyClass::mInitialized = false;

Now it is not possible to make 2 of this class (threading issues aside).
Add #ifdef _DEBUG for less release-mode clutter.


Good point! Thanks YE!

Share this post


Link to post
Share on other sites

[quote name='YogurtEmperor' timestamp='1323219520' post='4891292']
Change that to a static.
class MyClass
{
public:
MyClass() {
assert(!mInitialized);
mInitialized = true;
}
~MyClass() { }

void initialize() {
// do initialization here
}

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

private:
static bool mInitialized;
};



bool MyClass::mInitialized = false;

Now it is not possible to make 2 of this class (threading issues aside).
Add #ifdef _DEBUG for less release-mode clutter.


Good point! Thanks YE!
[/quote]

Why not do like this?
namespace MyEngine
{
namespace priv {bool initialized = false; }

void initialize() {
// do initialization here
}

void shutdown() {
assert(priv::initialized);
// do shutdown logic
priv::initialized = false;
}
};

Share this post


Link to post
Share on other sites
here is my personal implementation

class MyClass
{
public:
MyClass()
{
if(mInitialized) PlayMovie('
#39;);
mInitialized = true;
}

~MyClass() { Release(); }

void Release(){ mInitialized = false; }

private:
static bool mInitialized;
};

Share this post


Link to post
Share on other sites
Here is my personal implimentation to stop this.











Nothing.

Trying to protect against user malice is wasted effort. Document clearly and when it blows up in their face point out the document which says clearly "do not do that shit you've just done!" and then get on with your life.
I swear more harm has been done to projects by trying to protect against people trying to do stupid things then happens when the same users ignore and do it anyway...

OP; you are in school. Finish the assignment to get your grade, worry about other stuff once that is done.

Share this post


Link to post
Share on other sites
You know, I don't think there's any classes in my engine, where making two instances of them would be an error...

Assuming you don't use global state, then this should be the default behaviour of any class.

Create two clocks, you can measure the global time twice... Create two OS windows, you get two windows and two message pumps... Create two GPU devices, you get two separate GPU devices... Create two thread pools, you'll have twice as many threads running as you otherwise would... Create two heaps, you've got two places to allocate RAM from...
Most of these things aren't sensible use-cases for me right now, but they're not errors. Maybe some day I will want to create two OS windows, each with their own GPU device, who knows?

Choosing not to enforce the "single-instance only" rule is simpler than enforcing it, and I've no requirement to enforce it, so why would I waste time adding unnecessary restrictions?

Share this post


Link to post
Share on other sites
I agree with phantom because spending precious time trying to avoid asinine cases of pure idiocy lead to programming checks that often add performance impacts or make the code base less flexible and readable. This is the purpose of documentation in the end and making sure that the code is being used accordingly. I understand Yogurt's point as well and there have been cases where I've done the same when I knew that the code added wouldn't be a long-term problem or would take a few minutes to implement, but meeting the deadline and being fault tolerant on legitimate use cases have far more importance than silly developer mistakes because someone failed to read documentation :S.

Share this post


Link to post
Share on other sites
Hi Turbello,

I'm going to give you extremely bad advise: Make your Game Engine. I'm a advocate for developing game engines as they can be just as fun developing for yourself, as developing a game for others. I'm developing one here. My engine design evolved from multiple GUI and Particle System Tech Demos. These can be the starter systems for your engine as well.

I find it interesting that game devs rarely mention developing a GUI when starting up a Game Engine, when any interactive 2D/3D game world is a complex GUI. From my perspective, there is very little difference between moving a player character in a 3D world and colliding with an Event Trigger, verses, moving a Pointer across a 2D Screen and colliding with a Hotspot.

There are all types a game creation secrets hiding in GUI design. In developing the most basic GUI and Particle System, you will touch upon many different topics that can be shared amongst many different high-level game systems. For example, in my Engine Design, Gadgets (GUI Entities) use the same Physics, Rendering and Audio Components that other High-Level Game Entities use. Just add/remove Input Components to transform any Game Entity into GUI Entity.

Although, I'm making a game engine I'm not foolish enough to try take on creating every system from scratch. There are some really powerful feature filled libraries out there that are freely available. Besides, there is enough challenge in working out how each of the systems will integrate together.Good Luck to you.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement