Structuring a Simple 2D Engine

Started by
9 comments, last by SuperG 8 years, 1 month ago

Hi all! (First post here! Hehehe)

For nearly the past year I've been working in C++ and other game engines, Unity in particular, and I feel like I have a pretty good grasp at game development basics.

Now, I've decided to tackle a writing my own game engine for learning purposes, but I have no clue how to structure my code, or how to even begin.

I'm wondering where to start and what to do.

Right now, I have my main game loop which loads the update, input, and rendering functions, but I have no clue where to go from here.

Any help would be greatly appreciated!

Advertisement

Game engines are hard to design, at some point the generic engine code stops, and the game specific code starts. The problem is, where is that point.

I am reading from your post there are no obvious open areas in your engine any more. That means to me, you're finished making your engine!

Now, it is probably useful for learning purposes, to evaluate your engine. In other words, how good does it do its job?

(I do hope you have a list of requirements what your engine is supposed to handle).

Thus, testing time has arrived. Package the engine, give it a fancy name and version number (fooengine, 0.1 alpha, build 21583).

Then make a new directory, unpack the engine, and now make a game, like pong, tetris, pacman, space invaders, whatever you want. (Smaller is better, it's the first test, don't try anything big until you're confident small things "are trivial".)

Here you're supposed to write only game-specific code. Assuming you will finish at some point, leave it for a week, and then look again at the code you actually wrote, and the changes you made in the engine code (which you are not supposed to change?!). Could you re-use parts for another game? Did the engine code cause restrictions where you had to work around, or even hack the engine code to make it work?

At this point, you can decide to fix or expand the engine, making a new version, and a new test cycle begins.

If things look good, it's probably useful to do at least 2 or 3 games, to verify your findings.

And here you see the disadvantage of focusing at an engine. The games are not the goal any more, the engine is the goal. The games you make become sort of by-products of testing the engine. With each test cycle of the engine you have to write a lot of games, or update already written games.

If this is what you want to do, it's fine, just be aware of it.

One thing about game engines, as mentioned above, is how some code ends up being the game, while other code is in the game engine. But at some point, the better game engines have code that would be better in specific games, but can be used in some games, so becomes a feature. These are things like path-finding, AI, and any number of similar ilk of features.

Once you are past the basics, the things that pretty much every game will have, you would then move on to making features like I describe above. Sometimes, this comes on because you know of a certain feature, or because you try making a game with it, and then after coding that game, extract that code, and make it work in a general sense with your engine. Either way can work, though if you do it the second way, making a game, then I recommend you remember the eventual goal of the engine, and therefore should remember to write things in somewhat general ways when possible. It will make things take a bit longer, but will be quicker at the point of integrating the thing into your actual engine.

So, you have two paths you can generally follow, though you can go back and forth no problems. You start making some simple games, and then you start extracting game code from them so you can then put the features into your game. Or you can make a feature list of things you know games have that would work in your engine. This list would include things like navigation, AI, particle systems, lighting systems, maybe custom shaders, you know, all those things that make games great. Then you can simply make some test cases in order to make sure your engine features are working in a good general way, and that you can use/not use the features as you wish for any given game, and ensure that nothing interferes with other systems in the engine, regardless of which all features are actually in use at the moment. Everything should work in concert with each everything else, in any usage combination, under any given circumstances. That last part is generally the hardest part of making generic game engines, much more than any single given feature.



In my opinion. Start by abstracting your core loops as functions/functors/pointers you can arbitrarily set as any function/method you want. If your update requires passing elapsed time, create a loop around calling the function which in addition to calling the function will acquire elapsed time. Beyond that obvious stuff, I'd recommend building the fundamental initializations into the engine. For example, my game engine works with OpenGL, I initialize GLFW, I also configure a window to render upon, and start up some threads then move the rendering context to one of those threads, I do this so I can poll input on my main thread without requiring the thread to do multiple things. I also keep the projection/view matrices as part of my engine. I have function callbacks for types of input as well as user instigated window resizing.

In a more abstract design-centric approach, I'd recommend determining what functionality your engine requires, and what the ultimate purpose of the engine is with regards to development of a game. eg. I need my engine to save me from setting up architecture, initializing opengl, and provide interfaces for loading and managing assets.

Once you have your requirements start making some simple object oriented designs, and the rest will likely take on a life of its own.

I hope that was as succinct and helpful as I'd like to think it was. Good luck, especially if you decide to implement object pooling and memory management features (that stuff kicked my ass hard).

edit:


Thus, testing time has arrived. Package the engine, give it a fancy name and version number (fooengine, 0.1 alpha, build 21583).

Then make a new directory, unpack the engine, and now make a game, like pong, tetris, pacman, space invaders, whatever you want. (Smaller is better, it's the first test, don't try anything big until you're confident small things "are trivial".)

This is very true. If you end up having a time even remotely close to the one I had, you'll end up finding countless bugs in the process of making a game. I made a bullet hell space invaders game. I ended up finding bugs everywhere: shader compiling, sprite data file formatting flaws, asset loading mistakes, memory allocation, object construction, matrix calculations, etc.. Making a simple game allowed me to worry about debugging the engine instead of, primarily, the game itself. I already had a bullet hell space invaders though, so it was a small game to me.

Game engines are hard to design, at some point the generic engine code stops, and the game specific code starts. The problem is, where is that point.
I am reading from your post there are no obvious open areas in your engine any more. That means to me, you're finished making your engine!

Now, it is probably useful for learning purposes, to evaluate your engine. In other words, how good does it do its job?
(I do hope you have a list of requirements what your engine is supposed to handle).


Thus, testing time has arrived. Package the engine, give it a fancy name and version number (fooengine, 0.1 alpha, build 21583).

Then make a new directory, unpack the engine, and now make a game, like pong, tetris, pacman, space invaders, whatever you want. (Smaller is better, it's the first test, don't try anything big until you're confident small things "are trivial".)
Here you're supposed to write only game-specific code. Assuming you will finish at some point, leave it for a week, and then look again at the code you actually wrote, and the changes you made in the engine code (which you are not supposed to change?!). Could you re-use parts for another game? Did the engine code cause restrictions where you had to work around, or even hack the engine code to make it work?

At this point, you can decide to fix or expand the engine, making a new version, and a new test cycle begins.
If things look good, it's probably useful to do at least 2 or 3 games, to verify your findings.



And here you see the disadvantage of focusing at an engine. The games are not the goal any more, the engine is the goal. The games you make become sort of by-products of testing the engine. With each test cycle of the engine you have to write a lot of games, or update already written games.

If this is what you want to do, it's fine, just be aware of it.



For myself, being someone working on an engine myself, this is arguably the best post I have ever read!

Agree with above. I worked on and with many game engines and one thing I found is that building a tech for a sake of building the tech isn't good option. You must have something to use your engine with. Otherwise you even don't know that maybe you're going in wrong direction, maybe you spend time on features that, from "enginish" point of view are useful, but in practice - there's barely usecase for them. 2D or 3D engine - it doesn't matter as much as you need to know what you want to achieve with it. Look at Unreal or IdTech. In the beginning they were not even called 'engines'. They were standalone games from which engines have been 'extracted'. When Carmack worked on the new engine, there was Romero taking care of using it.

Now here's answer to your question. You're saying "I have no clue where to go from here". Make something ( I probably mean 'a game' here ) with your engine. You may get surprised how many things you're not going to use and how many other things will be missing to meet the requirements. A potential game build on top of your engine will show you where to go from there. You got certain basics working and it's enough to start working on the actual game. Also look at it from an artist and designer viewpoint. Today the workload has been shifted towards content creators rather than programmers. The easier to make art and design related things, the easier to use your engine. Couple of years ago I worked on the engine and game. I worked very close with an artist who brought lots of requests about handling of particular things. In the beginning, what I didn't plan to place within the scope of the engine, I made it as part of the game layer. Later, whatever seemed to make sense, I merged with the core engine. My work though was not the engine only but also tools, scripts, assets pipeline etc. All those requirements came up while working on one single game. Since it was just "two of us" team I had load of work including coding the actual game. At the end of the road, the engine was shaped not by the code that I've done before the game, but by the game itself. So shortly - the game will show you where to go next smile.png

As an extension to the above thought, might I ask a related question?

If you've seen the YouTube videos about gaming concepts and game development on the Extra Credits channel, and/or have been considering game development for some time, you've probably come across the phrase "minimum viable product". This is meant to recommend to start very small and simplistic at first, then slowly add in functionality and enhancements as the final project requires. But does this also apply to making game engines?

In other words, how exactly does one go about creating a game engine from minimalist engineering, and go through iterations of the engine and its features, unless at some point we can expect what we add in may perhaps break previous functionality?

As an extension to the above thought, might I ask a related question?

If you've seen the YouTube videos about gaming concepts and game development on the Extra Credits channel, and/or have been considering game development for some time, you've probably come across the phrase "minimum viable product". This is meant to recommend to start very small and simplistic at first, then slowly add in functionality and enhancements as the final project requires. But does this also apply to making game engines?

In other words, how exactly does one go about creating a game engine from minimalist engineering, and go through iterations of the engine and its features, unless at some point we can expect what we add in may perhaps break previous functionality?

No. The engine is the minimum viable product to make the game (should you choose not to use an existing engine). Write a game and you will necessarily get a minimalist engine. An engine is a tool, and you can't realistically develop a tool without a customer, or at the very least a use case.

go about creating a game engine from minimalist engineering, and go through iterations of the engine and its features
So what is a minimal engine here?

I don't see any feature X that you MUST have to call some piece of software an engine. On the other hand, you do need one feature, or you are not helping in development. Theoretically, the smallest possible feature in a single game is thus a game engine.

I don't know how this scales in "viable", without a clear definition of engine, you cannot measure such properties.

You see incremental development a lot, and it does have some nice properties like not getting all problems at the same time. I believe it's the primary means to evolve to whatever you end up with. Software is just too complex to visualize the end-product, and design and implement it from scratch in one time without errors.

On the other hand, if you have a piece of software, you look at it, you throw it away, and you rebuild it from scratch, the new solution tends to be way better than what you originally had. I believe you need some balance between both, build incrementally when it all fits, otherwise redesign (some parts) from scratch.

Don't lose sight of that first word: simple. It sounds to me you've got the workings of a simple 2D engine already. Input, logic, render, repeat until done.

This topic is closed to new replies.

Advertisement