Ads keep us online. Without them, we wouldn't exist. We don't have paywalls or sell mods - we never will. But every month we have large bills and running ads is our only way to cover them. Please consider unblocking us. Thank you from GameBanana <3

2D Game Engines: Part 1 - Structure

A Tutorial for GameBanana

An overview of what engines are, what they are composed of, and some structures that make them work

Judo's 2D game engine tutorial


Sections
Part 1 - Structure
Part 2 - Graphics 1 and Graphics 2
Part 3 - Physics
Part 4 - Collision detection
Part 5 - Networking
Part 6 - TBD
...


Part 1 - Structure This tutorial covers the overall structure of a game engine, some history, some definitions, and a description of structure which are common among engines that you may not know of yet. But first, a definition... A game engine is a framework, or collection of tools, which greatly simplifies rendering, audio processing, networking, collision detection, collision response, scene creation, and so on, often across multiple platforms without any need for separate code per platform. Engines do not contain any logic in themselves. That is to say they do not contain stories, characters, or even gameplay, but they ease the creation and presentation of these.


What's inside The above is a UML class diagram. Computer science students will recognize this immediatley but for the rest, just understand that these are classes defined in the code. A game engine would contain the World, Sprite, Object, Sound, and Socket objects, among others. A game would create the Character object on its own and of its own design, and then, in this case, derive NPC and Player from it. To expand on why this is needed, Sound contains routines for playing, restarting, and fading out sounds. Additionally, it would also contain the routines for decoding an audio format or two, but these things would be behind-the-scenes. This may not sound complicated but consider that every OS has its own audio mixer, audio formats come in many endianesses, bitrates, refresh rates, and so on, and it's unlikely that you know how to decode any form of statistical compression, discrete cosine transformations, or whatever other compression techniques are used. But you don't need to know. Only the engine does. Unless, of course, you're writing an engine then... sucks for you.


Utilities Engines and games alike make use of some functions you often won't find provided by a programming language's standard library or even, for example, OpenGL headers which often require certain functions. I usually call these random things utilities. The following are some examples I've used on more than one occasion, provided in C++:
#include <cmath>

int roundInt(double x) {
	x += 0.5;
	return (int) x;
}

int nextPowerOfTwo(int x) {
	double logBase2 = log(x);
	return roundInt(pow(2, ceil(logBase2)));
}

float degreeToRadian(float degree) {
	return degree * 0.0174532925;
}

float Q_rsqrt( float number ){
	long i;
	float x2, y;
	const float threehalfs = 1.5F;

	x2 = number * 0.5F;
	y  = number;
	i  = * ( long * ) &y;
	i  = 0x5f3759df - ( i >> 1 );
	y  = * ( float * ) &i;
	y  = y * ( threehalfs - ( x2 * y * y ) );

	return y;
}
That last method is actually taken from the source code of Quake III and is, somehow, an inverse square root function. And a remarkably fast one at that. How it works is a mystery. Even in the Quake III code, the comment next to the line with hex was simply "what the fuck?" Anyway, the point is, engines will often provide functions like these as well and almost always make use of them themselves. Additionally, you will often find utilities which make basic functions easier when the engine runs on more than one platform, such as this:
#include <algorithm>

std::vector<std::string> getDirectories(std::string directory) {
	#if !defined(WIN32) || !defined(WIN64)
	DIR* dp;
	struct dirent* dirp;
	std::vector<std::string> list;
	if((dp = opendir(directory.c_str())) == NULL)
		return list;
	while ((dirp = readdir(dp))) {
		if (strcmp(dirp->d_name, ".") != 0 &&
				strcmp(dirp->d_name, "..") != 0)
			list.push_back(std::string(dirp->d_name));
	}
	closedir(dp);
	sort(list.begin(), list.end());
	return list;
	#else
	// unfinished, Windows code goes here
	#endif
}
This one provides a list of files and directories given a specific directory. Source, for example, would use a similar function to load all available directories in the cstrike directory and, if a "maps" directory is within it, load the maps in that directory. The #if, #else, and #endif statements allow different code to be used depending on the platform the code is being compiled for and you can find more information on this by googling for C proprocessor statements (or C++). Java, C#, Python, and other languages quite often don't need anything like this since their libraries already contain these utitilies.


A useful structure Computer science students will recognize this as a singleton pattern, but for the rest, this is an object that will exist only once in memory and it will allow any other part of the engine to access the information it holds. In other words, you can hold your engine's configuration in this object and the multiple parts of the engine can access it and know what graphical resolution, for example, to use. Header:
class Singleton {
	
public:

	static Singleton* Instance();
	
	int resolutionX;
	int resolutionY;
	
private:

	Singleton();
	~Singleton();
	
	static Singleton* m_instance;
};
Source:
Singleton* Singleton::m_instance = NULL;

Singleton* Singleton::Instance() {
	if (!m_instance)
		m_instance = new Singleton();
	return m_instance;
}

Singleton::Singleton() {
	resolutionX = 0;
	resolutionY = 0;
}

Singleton::~Singleton() {
	
}
Finally, you would use it like so:
Singleton* s = Singleton::Instance();
int xResolution = s->resolutionX;
The syntax is a bit odd, but that's C++ for you. Java makes this easier should you choose to use it, but C++ is odd like this.


Build systems Given the size of the text involved in this, I won't be including an example but Wikipedia has a lot of information on all of these so... Engines don't always include this feature but it's become more common in recent years. Build systems like GNU Make, CMake, or any IDE's own build system allow for someone to easily create a project (in this case, game) of their own and then compile with a single click or press of the enter key. Otherwise, you would need to compile your own object files, link all relevant libraries, statically compile everything into one executable if that's your goal, or compile specific modules should they exist on that system. When games make use of OpenGL, Cg, CPU extensions, and hundreds of other possible system-dependant features, it becomes very difficult to even get a game to work on other systems when it works on your own. Build systems (especially CMake, I recommend it) make it easy to account for this.


Events This is more of a design choice for an engine more than it is a common feature, but it's a popular one. In short, an engine is set up with all the models, maps, and other resources it needs and it processes everything it wants to. Physics, graphics, audio, networking... the engine can handle these on its own. When something happens, for example a collision between a bullet and a player's head, it's worth mentioning. If something should happen in an occurance like this, we call it an event. An engine will have its events and a game will respond to them. This is what we call event-driven programming, essentially. In code, you will usually do this through function pointers. Function pointers, however, are really difficult to understand but can be easy to use if you don't try to understand the syntax (at least for C++):
void registerEventCallback(void (*function)(int, int)) {
	listOfCallbacks.add(&function);
}
I do not guarantee that's the correct syntax, though. But, more importantly, you would use the above function to add a function list that will be called upon the occurance of an event. So the engine would have some code similar to:
if (colliding(A, B) == true) {
	for (int i = 0; i < listOfCallbacks.size(); i++) {
		&function = listOfCallbacks.get(i);
		(*function)(A.x, B.x);
	}
}
The above would call each function in the list upon the collision of A and B, some random objects, and give these function the parameters A.x and B.x, which are also random. I haven't defined them anywhere. The return values of these functions and their parameters don't need to be defined the way they are above. That's up to the engine programmer(s). Although it would also be possible, and perhaps wise, to use a command pattern in place of this function pointer method. For information on that, google it or ask me*.


Final thoughts Certainly you need a good knowledge of C++ to fully understand the code above. If you can't, or you simply want to see it in another language, then... *I can be found in #fpsbanana on irc.gamesurge.net or you may send me a PM here on GameBanana. IRC is my preferred method but do as you wish. to do: singleton, build systems, polling vs. event-driven

Comments

Sign up to access this!
  • shash7 avatar
    shash7 Joined 11y ago
    Offline
    3,335 points Ranked 2477th
    17 medals 1 legendary 1 rare
    • 10 years a member Medal icon
    • 6 years a member Medal icon
    • Halloween Mapping Contest Submitter Medal icon
    • 4th Place - Secret Society Mapping Contest Medal icon
    • Winter Worlds Mapping Contest Entrant Medal icon
    • Reached 1,000 Points Medal icon
    access_time 7y
    > **Posted by Judo** .... Even I hated javascript due to its lack of classes, shitty scoping and weird design patterns. But everything changed once I read douglas crockford's javascript, the good parts.

    Anyways, I once had this fantastic idea to make a simple level designer in javascript using webgl ...
    Got no fuel, running on pure a avatar
    Mantra
    Got no fuel, running on pure a
    URL to post:
  • Decemberklar avatar
    Decemberklar username pic Joined 13y ago
    Offline
    9,657 points Ranked 606th
    26 medals 1 legendary 6 rare
    • 10 years a member Medal icon
    • 25 posts awarded Exemplary Feedback Medal icon
    • 6 years a member Medal icon
    • Submitted 100 Threads Medal icon
    • GameBanana’s Christmas Giveaway 2017 Day Eighteen Winner! Medal icon
    • Submitted 20 Maps Medal icon
    access_time 7y
    > **Posted by Judo** > > **Posted by Sebhael** > > > it probably wouldn't hurt to just throw a few comments in the code > > I would if I had enough width on this page. :( > > > **Posted by Sebhael** > > > I just feel like the most that'll happen here is people copy and pasting and not really learning anything (save a handful) - even though you do explain the process underneath. At least if there's some clues in the source, it'll be there until the person deletes the lines. > > Nah, this is all incomplete, except for the Singleton class but that's just a google away anyway. Plus, the people that are so new to programming that they'd want to copy and paste wouldn't be using C++. Limitations of the medium are always understandable. I'm a server-side developer, so the methods of desktop programming do slightly elude me. Though, everything I say is something I feel reflects upon myself when I original set out to learn PHP/AJAX/Javascript. I'm a student trying to get "THAT" piece of paper, I haven't learned **SHIT** from my university. Are they bad at teaching? No. It's just that I set to do something, and took it upon myself to study things prior to being "taught" them. Everything I know about web development is self taught - to the point - how did I learn these sort of things? Well, by highly descriptive tutorials and proper commenting and explanations. I can tell you right now, if I came to this tutorial to learn something - I'd have probably ignored everything outside of the CODE blocks. I didn't just read people's commentaries, I just looked at the code itself - and understood what the presenter was trying to accomplish at the given time. That's why I brought up the commenting thing, is that I personally would have copy and pasted your code and just plopped it into my text editor and headed forth as a means to start a project. So since you're not able to comment the code due to medium limitations, maybe style the description of the code itself instead of plain text? Remember, as step 1 of a complex project - lots of colors and pictures help a lot. None of this is against you yourself personally, it's a fantastic tutorial - and I will personally be looking at this when I tackle desktop programming. I know what you're trying to accomplish though because of my background (aside from the singletons, that's not a common (although it is talked about) thing in PHP programming). At least link people to a basic tutorial on C programming to understand basic programming statements? Tis all, still 10/10 on the tutorial - the knowledge presented is invaluable and I'm personally looking forward to the next iterations. I need to brush up on non-server programming, so this'll get me started at minimum.
    URL to post:
  • Judo avatar
    Judo Joined 13y ago
    Offline
    314,415 points Ranked 8th
    18 medals 4 rare
    • Reached 75,000 Points Medal icon
    • Reached 200,000 Points Medal icon
    • 6 years a member Medal icon
    • Returned 1000 times Medal icon
    • Reached 1,000 Points Medal icon
    • Reached 2,500 Points Medal icon
    Judo Technical Expert
    access_time 7y
    > **Posted by Sebhael** > it probably wouldn't hurt to just throw a few comments in the code I would if I had enough width on this page. :( > **Posted by Sebhael** > I just feel like the most that'll happen here is people copy and pasting and not really learning anything (save a handful) - even though you do explain the process underneath. At least if there's some clues in the source, it'll be there until the person deletes the lines. Nah, this is all incomplete, except for the Singleton class but that's just a google away anyway. Plus, the people that are so new to programming that they'd want to copy and paste wouldn't be using C++. > **Posted by shash7** > But this stuff is really low level. And plus, pointer make me vomit :P
    Is it? It's just OOP. I know the function pointer stuff is complicated but whether I show that or the command pattern, it's complicated no matter what. > **Posted by shash7** > If you want to teach 2d game programming, teach in javascript with the html5 canvas tag. It is braindead simple and there are many simple game engines available.
    Eh... no. JavaScript is one thing I will not use if I can help it. And as far as the web goes, Java applets are still plausible and everything here applies to JavaScript too. I don't really want to teach a language with these tutorials. > **Posted by shash7** > Also, love2d for the lua programming language is pretty easy.
    Love2D is, indeed, good. But I'm more interested in teaching how to make Love2D rather than use it. > **Posted by shash7** > Also, I would teach people how to make a simple render loop and then explain drawing simple shapes from there. Part 2, which I've already posted, covers that. Without graphical primitives, though... I guess I could go back and add that sometime. But I did at least cover GL_QUADS in it so far and the same logic applies to primitives.
    • Interesting x 1
    ?????? avatar
    Mantra
    ??????
    URL to post:
  • shash7 avatar
    shash7 Joined 11y ago
    Offline
    3,335 points Ranked 2477th
    17 medals 1 legendary 1 rare
    • 10 years a member Medal icon
    • 6 years a member Medal icon
    • Halloween Mapping Contest Submitter Medal icon
    • 4th Place - Secret Society Mapping Contest Medal icon
    • Winter Worlds Mapping Contest Entrant Medal icon
    • Reached 1,000 Points Medal icon
    access_time 7y
    Awesome guide mate.
    But this stuff is really low level. And plus, pointer make me vomit :P

    If you want to teach 2d game programming, teach in javascript with the html5 canvas tag. It is braindead simple and there are many simple game engines available.
    Also, love2d for the lua programming language is pretty easy.

    Also, I would teach people how to make a simple render loop and then explain drawing simple shapes from there.
    • Disagree x 2
    Got no fuel, running on pure a avatar
    Mantra
    Got no fuel, running on pure a
    URL to post:
  • Decemberklar avatar
    Decemberklar username pic Joined 13y ago
    Offline
    9,657 points Ranked 606th
    26 medals 1 legendary 6 rare
    • 10 years a member Medal icon
    • 25 posts awarded Exemplary Feedback Medal icon
    • 6 years a member Medal icon
    • Submitted 100 Threads Medal icon
    • GameBanana’s Christmas Giveaway 2017 Day Eighteen Winner! Medal icon
    • Submitted 20 Maps Medal icon
    access_time 7y
    Although it's assumed that the person reading has any programming experience, it probably wouldn't hurt to just throw a few comments in the code just to give a bit more of an idea of what is happening at that moment. I just feel like the most that'll happen here is people copy and pasting and not really learning anything (save a handful) - even though you do explain the process underneath. At least if there's some clues in the source, it'll be there until the person deletes the lines.
    URL to post:

Embed

menu
Share banner
Image URL
HTML embed code
BB embed code
Markdown embed code

Credits

Key Authors
Judo
Author

Submitter

Judo avatar
Judo Joined 13y ago
Offline
314,415 points Ranked 8th
18 medals 4 rare
  • Reached 75,000 Points Medal icon
  • Reached 200,000 Points Medal icon
  • 6 years a member Medal icon
  • Returned 1000 times Medal icon
  • Reached 1,000 Points Medal icon
  • Reached 2,500 Points Medal icon
Judo
Creator
Sign up to access this!
Sign up to access this!
Sign up to access this!

Game

Sign up to access this!

Category

Details

Difficulty Level
Advanced

Attributes

Share

  • Share on Reddit
  • Share on Twitter
  • Share on Facebook
  • favorite 1
  • remove_red_eye 34.1k
  • mode_comment 5
  • access_time 7y
  • access_time 4y

More from Submitter

menu

More Scripting Tutorials