Hello Guest, please login or register.
Did you miss your activation email?
Login with username, password and session length.

Pages: [1]   Go Down

Author Topic: Building a Game Engine Help  (Read 4233 times)

0 Members and 1 Guest are viewing this topic.

DaSpirit

The Quiet
Building a Game Engine Help
« on: May 05, 2012, 07:57:55 pm »
  • The Mad Programmer.
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 87
Hey guys, so I started writing a game engine architecture by myself. I guess I'm an intermediate at C++. Before anyone says anything about game engines being bad, I want to say that I shall be reusing it and building onto it in my later projects. For now, I only want to make the core with some 2D graphics foundations built in.

I need help because I don't really know how exactly the best way to build it would be. My current idea resolves around circular dependencies, which I want to avoid. Generally, I have a header, game.h
Code: [Select]
#include <vector>
#include <string>
#include "texture.h"
using std::string;
using std::vector;

class State;
class Game
{
private:
vector<Texture2D> Textures;
State* Level;
public:
/* Some startup and exit functions ... */
TextureAdd(string filename);
}

And then my level.h:
Code: [Select]
class Game;
class MainMenu : public State
{
private:
Game* game;
public:
/* Some functions here ... */
void Load()
{
game->TextureAdd("Graphics/player.png");
}
}

I generally wanted to have my textures stored in the core so that some textures could be preloaded during some levels and used in the next. One problem is the circular dependency that is being created. Another is that I have to be careful to know which textures are preloaded when. I'm just having trouble coming up with concepts.

Another thing I don't understand is memory management. How do I handle that? Should I try to allocate everything as soon as possible? Also, in case that the player has an error, how do I handle that? Should I make some functions boolean that return false so that my main function can end peacefully or should I just use a function like exit()?

Anyone like to share how they build their engines?
Logged
I support:
Re: Building a Game Engine Help
« Reply #1 on: May 05, 2012, 08:55:02 pm »
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 3725
I'm only an intermediate myself, but this is the advice I can give:

1) Circular dependencies happen when you try to include header A in header B and header B in header A. I was taught not to try to include any of your own made headers in other header files. It is preferred to use forward class declarations, unless it is not possible. With forward declarations it is also required to have pointers to classes as variable types. When you don't use pointers you need to include the header file of the class you are importing. Try to include the *.h files in the *.cpp files. 

2) Preload issue, you could try to create smart pointers that keep track of the number of times a reference is stored. Next you can use a Texture manager/Texture factory to load and manage textures.

3) Memory Management. I can't really help you there. I have troubles with this as well. But I found that you need to discover a good balance for yourself. It is good to allocate some memory before hand, but too much that you will never use is not good either. Just know that loading resources from the HDD takes a long time, so you don't want to do this during gameplay at the time you need it.

4) When your game results in a state of error. A state that it should not be in, it is not good to use a boolean return or calling a function like exit(). What you should do is throw an exception. Which you will catch or let it propogate up the execution stack. Exceptions are the way to go here.

I hope it helps.
Logged
Re: Building a Game Engine Help
« Reply #2 on: May 05, 2012, 09:02:15 pm »
  • *
  • Reputation: +3/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6629
Quote
I need help because I don't really know how exactly the best way to build it would be. My current idea resolves around circular dependencies, which I want to avoid. Generally, I have a header, game.h
Circular dependencies are unavoidable at times, there is nothing inherently wrong with them as long as you make sure you tear them down correctly.

Quote
I generally wanted to have my textures stored in the core so that some textures could be preloaded during some levels and used in the next. One problem is the circular dependency that is being created. Another is that I have to be careful to know which textures are preloaded when. I'm just having trouble coming up with concepts.
I would personally have a texture manager, and have that passed between the entities that need it, rather than a root "Game" object that everything goes through for everything (I imagine you would do the same for audio and such?).

As for knowing what textures are preloaded, why not use texture "handles". When a texture is requested that's not loaded you just return a "default" texture, and spawn off a thread to load the new texture and replace the default one when its ready.

tbf through that's kind of unnecessary, what situations are you going to come into when you need to load textures at runtime (I assume most would be loaded when the map is loaded?)? If all else fails, loading textures at runtime is unlikely to take more than a few milliseconds, unnoticeable to the player.

Quote
Another thing I don't understand is memory management. How do I handle that? Should I try to allocate everything as soon as possible?
Number one rule of game developer, always avoid allocating at runtime when possible, memory allocation is one of the slowest things you'll find in any game. Especially on consoles. Try and load everything before hand, or better yet, stick em in the stack.

Personally what I do is write my own allocation routines (and then override new/delete to assert, to make sure people don't accidently use them). These allocation routines typically allocate in huge blocks of about 64mb each, and then portion them out and return them. Far faster than malloc'ing them at runtime.

Quote
Also, in case that the player has an error, how do I handle that? Should I make some functions boolean that return false so that my main function can end peacefully or should I just use a function like exit()?
If the game can continue from the error, ignore it. Better to allow the player to keep playing than drop out (obviously don't do this in debug mode tho).

If you want to find a nice way of showing fatal error messages to the user, checkout the use of SetUnhandledExceptionFilter on windows and setjmp/longjmp on any other platform.
Logged
Re: Building a Game Engine Help
« Reply #3 on: May 05, 2012, 09:06:44 pm »
  • *
  • Reputation: +3/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6629
Quote
1) Circular dependencies happen when you try to include header A in header B and header B in header A. I was taught not to try to include any of your own made headers in other header files. It is preferred to use forward class declarations, unless it is not possible. With forward declarations it is also required to have pointers to classes as variable types. When you don't use pointers you need to include the header file of the class you are importing. Try to include the *.h files in the *.cpp files. 
I figured he was talking about circular references between classes, not in the more abstract "header files" deal.

But if you are talking about that, solid advice above, forward declarations are the way to go.

Quote
2) Preload issue, you could try to create smart pointers that keep track of the number of times a reference is stored. Next you can use a Texture manager/Texture factory to load and manage textures.
Never get over reliant on smart pointers, they tend to instil bad programming practices, and they are several factors slower than accessing normal pointers.

Quote
It is good to allocate some memory before hand, but too much that you will never use is not good either.
Totally disagree there. I think its far better to allocate a lot of memory that you may not use, than slow the game down horribly for the user when you don't have enough.

Few users have such a low amount of RAM these days that it makes any difference to them. Not to mention with games you tend to be in more or less exclusive control of the computers resources.

Quote
Which you will catch or let it propogate up the execution stack. Exceptions are the way to go here.
Huuum, totally disagree with this, error codes for functions are IMO a far better way to go. Exceptions in C++ have HUGE overhead (mainly because they infer several context switches by the OS), they shouldn't be used for general error handling, only in exceptional circumstances (exception,exceptional,etc).
Logged

Antidote

>.>
Re: Building a Game Engine Help
« Reply #4 on: May 05, 2012, 09:13:34 pm »
  • In all seriousness who's serious?
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 1485
When I program i generally stay away from smart pointers. They're useful but people tend to get carried away then wonder why there is a huge bottleneck in speed. 10to1 it's the smart pointers or dynamic allocation.
Logged
  • Axiomatic Data Laboratories

thestig

Re: Building a Game Engine Help
« Reply #5 on: May 05, 2012, 09:17:08 pm »
I hate how smart pointers are somehow the automatic solution to memory management. IMO, they're only useful for certain cases just like garbage collection is only useful for certain cases(to the developer). I'd rather have more speed, though.

Dynamic allocation ftw, though.
Logged

DaSpirit

The Quiet
Re: Building a Game Engine Help
« Reply #6 on: May 05, 2012, 09:26:25 pm »
  • The Mad Programmer.
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 87
Hm, wow thanks guys. I keep reading these over and over trying to understand.

Quote
Number one rule of game developer, always avoid allocating at runtime when possible, memory allocation is one of the slowest things you'll find in any game. Especially on consoles. Try and load everything before hand, or better yet, stick em in the stack.

Personally what I do is write my own allocation routines (and then override new/delete to assert, to make sure people don't accidently use them). These allocation routines typically allocate in huge blocks of about 64mb each, and then portion them out and return them. Far faster than malloc'ing them at runtime.
This I'm kinda confused about. What do you mean by "stick em in the stack"? And would you mind giving me an example of your own allocation routines?

Quote
Error codes for functions are IMO a far better way to go.
Does an error code mean something like my idea of having a boolean return that makes its way go back to the main function? I generally use that to find errors, then in the debug version of my project, I have the console activated and I use std::cout and cin.get() so I can assess what happened. The reason why I have it go back to the main function is so that I can safely delete the Game object that I create and immediately return, ending the program.
Logged
I support:
Re: Building a Game Engine Help
« Reply #7 on: May 05, 2012, 09:29:23 pm »
  • *
  • Reputation: +3/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6629
As in;

Quote
MyGameEngine engine;
engine.Run();

rather than;

Quote
MyGameEngine* engine = new MyGameEngine();
engine->Run();

Top is allocated on the stack and is basically instant, bottom one is allocated on the heap and is slow as hell.

If you want an example, look in memory.h, callocator.h and cheapallocator.h from one of my projects here;

http://binaryphoenix.com/svn/public/Crossplatform%20Game%20Engine/Engine/

Quote
Does an error code mean something like my idea of having a boolean return that makes its way go back to the main function? I generally use that to find errors, then in the debug version of my project, I have the console activated and I use std::cout and cin.get() so I can assess what happened.
Pretty much yes.
Logged

DaSpirit

The Quiet
Re: Building a Game Engine Help
« Reply #8 on: May 05, 2012, 10:00:30 pm »
  • The Mad Programmer.
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 87
Quote
If you want an example, look in memory.h, callocator.h and cheapallocator.h from one of my projects here
Wow, this is very hard to follow. Just wondering, how necessary is this?
Logged
I support:
Re: Building a Game Engine Help
« Reply #9 on: May 05, 2012, 10:04:30 pm »
  • *
  • Reputation: +3/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6629
Quote
If you want an example, look in memory.h, callocator.h and cheapallocator.h from one of my projects here
Wow, this is very hard to follow. Just wondering, how necessary is this?
Definitely not necessary, you can get away with new/delete fine lol, I'm just going for crazy speed.

You did ask for an example of my functions :). lol
Logged
Re: Building a Game Engine Help
« Reply #10 on: May 05, 2012, 10:09:58 pm »
  • Wooper Don't Give a !@#$%
  • *
  • Reputation: +16/-0
  • Offline Offline
  • Gender: Male
  • Posts: 1457
To me it makes sense to build a solid timing system before delve into graphics, since graphics are dependent on timing. You know, just a wrapper against OS tick calls mostly.

Then I'd suggest setting up an easily configurable game loop that makes use of your new wrapper.
Logged
ROLL TIDE WHAT? **** YOU!!! Geaux Tiga

~The Gaurdians of ZFGC~
Kirby, metallica48423, Max, Vash, walnut100
  • Gamers & Developers Unlimited

DaSpirit

The Quiet
Re: Building a Game Engine Help
« Reply #11 on: May 05, 2012, 10:22:01 pm »
  • The Mad Programmer.
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 87
Quote
Definitely not necessary, you can get away with new/delete fine lol, I'm just going for crazy speed.

You did ask for an example of my functions :). lol
Well my brain exploded looking at all of this O_O I'm still looking at it and it's very interesting. I have a lot to learn. How long have you been working on it? And where did you learn all of this from? Do you read books on this all?

I knew the best place to ask about programing was the ZFGC, cause Infini lives here! lol
Quote
To me it makes sense to build a solid timing system before delve into graphics, since graphics are dependent on timing. You know, just a wrapper against OS tick calls mostly.
I already have a limit of 60 FPS and for Win32 I use GetTickCount(). I had to call Sleep() anyway, so I could lower my CPU usage.
Logged
I support:
Re: Building a Game Engine Help
« Reply #12 on: May 05, 2012, 10:28:26 pm »
  • *
  • Reputation: +3/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6629
Quote
Well my brain exploded looking at all of this O_O I'm still looking at it and it's very interesting. I have a lot to learn. How long have you been working on it? And where did you learn all of this from? Do you read books on this all?
Nope, never found many programming books worth reading :S. Most are terrible attempts at ripping money out of people trying to learn.

As for the engine, start writing it about a month ago, put in an hour or so every other day.

Quote
I already have a limit of 60 FPS and for Win32 I use GetTickCount(). I had to call Sleep() anyway, so I could lower my CPU usage.
ps. GetTickCount() is very inaccurate, resolution is usually as around 10ms, sometimes more, sometimes less. Check the MSDN article for information. QueryPerformanceCounter is probably a better idea.

Also sleep gives up your entire timeslice, and its only guarantee is that it will sleep for at "least" the amount of ms you give it, usually its more. Normally it should be fine, but its worth keeping an eye on if your performance gets bad.
Logged

DaSpirit

The Quiet
Re: Building a Game Engine Help
« Reply #13 on: May 05, 2012, 10:50:49 pm »
  • The Mad Programmer.
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 87
Thanks. I don't really use Sleep() for precise intervals. I noticed it's unreliability long ago. I only use it for 10 milliseconds and then artificially limit the FPS from there (simply don't draw if it's past 60 FPS, though I'm not entirely sure what would happen on monitors with higher than 60 refresh rates).

Your whole code is making me want to try do the same (make everything from scratch). I always thought I was speed obsessed until I saw you, you're extreme. I want to start making a game already though... :D
Logged
I support:
Re: Building a Game Engine Help
« Reply #14 on: May 05, 2012, 11:01:55 pm »
  • *
  • Reputation: +3/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6629
Your whole code is making me want to try do the same (make everything from scratch). I always thought I was speed obsessed until I saw you, you're extreme. I want to start making a game already though... :D
Bad idea XD.

I'm just anal about my code, I hate using libraries that are out of my control (hence no stl).

It's a bad move really, reinventing the wheel is pretty dumb lol.
Logged
Re: Building a Game Engine Help
« Reply #15 on: May 06, 2012, 08:55:30 pm »
  • Wooper Don't Give a !@#$%
  • *
  • Reputation: +16/-0
  • Offline Offline
  • Gender: Male
  • Posts: 1457
Keep in mind too that you only want to lock rendering and game state type activities to 60 FPS. Ideally you want to take input as fast as the computer will allow. And yeah use QPC for Windows over GetTickCount like Infini said, most of the problems you'll read about it aren't as relevant today as they were six years ago
Logged
ROLL TIDE WHAT? **** YOU!!! Geaux Tiga

~The Gaurdians of ZFGC~
Kirby, metallica48423, Max, Vash, walnut100
  • Gamers & Developers Unlimited

DaSpirit

The Quiet
Re: Building a Game Engine Help
« Reply #16 on: May 06, 2012, 11:09:18 pm »
  • The Mad Programmer.
  • *
  • Reputation: +1/-0
  • Offline Offline
  • Gender: Male
  • Posts: 87
Walnut: Yeah, I'm aware, I've made a game in pure Win32 and GDI years ago. I'm not entirely new at making games or applications, just frame-working an engine.

Oh yeah, Infini, I have been studying your code. For one, your PlatformMain() entry point is somewhat unnecessary. You can use main() for creating Win32 App, it even says so on the Microsoft Docs. If you want to get rid of the console window, you can just use:
Code: [Select]
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
//Why not keep the console while debugging?

Also, I noticed you use
Code: [Select]
#pragma once as your control guard. Not sure if you know, but I've read that it's best to use
Code: [Select]
#ifndef FILE_H
#define FILE_H
//... insert code here
#endif
across your whole application.

Anyways, that's what I know from experience. I'm going to try to make my own way of making things work like you, but I'm going to use the STL.

Unfortunately, I want to add threads using the STL but it didn't come out for Visual Studio 10 and 11 Beta does not work on Vista. Would anyone recommend me switching compilers or should I simply wait until I get a new computer (in at least 2 months! w00t!).
Logged
I support:
Re: Building a Game Engine Help
« Reply #17 on: May 07, 2012, 10:57:49 am »
  • *
  • Reputation: +3/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6629
Quote
Oh yeah, Infini, I have been studying your code. For one, your PlatformMain() entry point is somewhat unnecessary. You can use main() for creating Win32 App, it even says so on the Microsoft Docs. If you want to get rid of the console window, you can just use:
I think you missunderstand the point of PlatformMain(). The main point of my engine is to make it entirely cross-platform, each platform code stub implements the main method differently (setting up different bits of the environment specific to the platform) and implements error recovery, it then calls the PlatformMain which contains the "generic" platform-agnostic code for the actual game.

It has nothing at all to do with the subsystem being compiled to. The compiler has no knowledge of PlatformMain it dosen't do anything based on it, it's just a nicer system to hide away the platform specific code.

I also intend to have NO platform specific code outside of the platforms folder, allowing porting to be possible just by copy/pasting a platform folder and updating it to support the new platform. No #ifdef WIN32 etc are allow anywhere outside the platform folder, thus the PlatformMain is neccessary.

Quote
Also, I noticed you use
#pragma once
as your control guard. Not sure if you know, but I've read that it's best to use
Actually no it isn't.

This holds true for years and years ago, but nowadays all of the standard C++ compilers fully support #pragma once, and make optimizations based on it. All the compilers I'm targeting (Intel, GCC, MS) support it so its fine :3.

The header guard system is a left over from when only MS supported the definition.
« Last Edit: May 07, 2012, 11:01:10 am by Infini »
Logged

Antidote

>.>
Re: Building a Game Engine Help
« Reply #18 on: May 07, 2012, 02:28:06 pm »
  • In all seriousness who's serious?
  • *
  • Reputation: +0/-0
  • Offline Offline
  • Gender: Male
  • Posts: 1485
Why is there even a debate on that? They both do the same thing, the #ifndef ... #endif one is just a TINY bit more portable if a little more to write. Honestly <.<

Personally I Prefer the #ifndef ... #endif header guard myself as it's a good way to tell the programmer they are indeed in a header file.

e.g:
Code: [Select]
#ifndef __EXAMPLE_HPP__
#define __EXAMPLE_HPP__

...

#endif
Logged
  • Axiomatic Data Laboratories
Pages: [1]   Go Up

 


Contact Us | Legal | Advertise Here
2013 © ZFGC, All Rights Reserved



Page created in 0.109 seconds with 72 queries.

anything