How to learn the concepts of making games from scratch/with a low level perspective

I have recently come across this community and the concepts of making games from scratch (I have recently learned to program in c) I have started to watch the Handmade Hero YouTube series but around episode 4 I realized that before writing games from complete scratch I would like to make a basic game in SDL 2. Learning how to use the SDL library has not been a problem due to the documentation and other resources, however I was wondering if any of you guys knew of other resources for learning about approaching making a game in a low-level language like how and when to dynamically allocate memory, and if you should make your own allocator like a Linear allocator, and why you would want to use this and where you should use one, etc. Any help is appreciated, thanks!

You can have a look at Ginger Bill's articles on memory allocations strategies https://www.gingerbill.org/article/2019/02/01/memory-allocation-strategies-001/.

The idea is that there isn't a rule, you need to find some metrics that apply to your use cases, and find a (or several) solution for those metrics, which is almost always a compromise between those metrics.

This implies, that you should have already implemented part of the game/code so that you have some real examples to work on. In the beginning, how you allocate memory will probably not matter at all and you should not worry too much about it during the "prototyping" phase. After a while try to look at patterns on how you use memory (allocation, life cycles, access pattern...) and see if there are some abstractions you could come up with to help you on some metrics you defined.

From some of the initial questions you asked it seems like you need a better low level programming philosophy/framework to work from which provides you with the ability/confidence to slowly build up a good idea for how things like memory management should be handled. If that is the case then I would recommend sticking with handmade hero for a bit longer and really pay attention to how Casey is going about building his codebase (he goes over many times how he thinks when programming and how to solve unknown problems). I think this is the most important thing to work on initially so you can be confident solving alot of the low level issues that come up when programming in something like C.

If I'm a bit off base and you already feel confident as a programmer and just want to learn game specific things at a more beginner level then ya, watching handmade hero from A-Z probably isn't the best starting point. In this case I would either use the handmadehero.org search bar and search for any specific topics you're looking for or maybe check out Jamie King's tutorial series on youtube (I put the google link below since I'm at work and can't copy any youtube links). I remember finding his stuff relatively digestible as a beginner. I would just focus more on the actual game ideas he goes through rather then trying to learn from his coding style

https://www.google.com/search?q=jamie+king+game+engine&source=hp&ei=NW_VYv3AOuKVwbkPgLik8AU&iflsig=AJiK0e8AAAAAYtV9RREfc5uGJZdOAZzFNdlYZFf4i8hS&ved=0ahUKEwi9r8SB1IL5AhXiSjABHQAcCV4Q4dUDCAo&uact=5&oq=jamie+king+game+engine&gs_lcp=Cgdnd3Mtd2l6EAMyBwghEAoQoAEyCAghEB4QFhAdOgkILhDUAhAKEEM6BAguEEM6BQgAEJECOgoILhCxAxCDARBDOgcILhDUAhBDOgQIABBDOgsILhCABBCxAxCDAToHCC4QsQMQQzoFCC4QgAQ6BQgAEIAEOggILhCABBDUAjoLCC4QsQMQgwEQkQI6BAgAEAo6BAguEAo6CAguENQCEJECOgsILhCABBDHARCvAToGCAAQHhAWOggIABAeEBYQCjoFCAAQhgM6BQghEKsCOgoIIRAeEA8QFhAdUABYxhhgpRloAHAAeAKAAdIBiAHeEpIBBjMuMTYuMZgBAKABAQ&sclient=gws-wiz

The best and most original games usually come from quick prototyping with placeholder graphics and the idea that you are just doing it for yourself, for fun. This will unleash more creativity by not censoring ideas that sound too silly at first and allow you to try it quickly. Build reusable code that can easily by made into something else with some changed settings and imagination.

All games start out as small hacks going straight for the goal just to test things, then needs higher abstractions as the duplicated patterns pile up. Don't obsess over abstractions before they are needed, but don't get stuck writing the same boilerplate code over and over again.

Common steps:

  • Outlining coherent 2D/3D coordinate systems for your sanity
  • Visual representation of the world
  • Player to navigate with while the camera follows
  • Animations, particles, light and weapons
  • Physics and basic opponents
  • Level editor
  • A goal to reach, loading the next level
  • Saving/loading game progress (use integers when possible)
  • Menu/overlay/view system (allowing top down world view to enter side-scroller level)
  • Scripted events and story

If you hit a roadblock with memory leaks and crashes when the code gets bigger and more advanced, one can also use C-style C++ to get some extra power with templates and automatic reference counting when needed. C is easier to learn from being small, but C++ can offer libraries with beginner friendly safety abstractions for quicker prototyping and less crashes.

The biggest obstacle to stability in C/C++ is optimizations that work on raw pointers where you see the start, but not the size. I use a C++ class wrapped around a raw C pointer that only remembers the allocation size during debugging. This allow doing low level pointer optimizations for release mode, with the same safety as a high level language in debug mode. External memory debuggers can detect when going outside of the allocation requested from the operating system, but this won't work when using a custom allocator and might not be triggered until after the whole application has produced incorrect results, sent corrupted pointers to GPU drivers, overwritten your files with garbage data and crashed the whole operating system beyond recovery. https://github.com/Dawoodoz/DFPSR/blob/master/Source/DFPSR/base/SafePointer.h

File serialization is one of the most common places to find bugs in released products, because it's both much more complex and called a lot less often. The consequence of a failed save is also a lot worse because it won't go away from restarting the game. Instead of copy pasting the same file access code for each file format to parse, one can create a wrapper around raw memory allocations for knowing the allocation's size at all time. Giving easy reference counted sharing of data and reusable methods for cloning, saving/loading, archive packing/unpacking, compressing and encrypting. Then you can easily regression test serialization by generating random objects, serializing them to memory buffers, parsing back to object, and comparing if they are equal, billions of times in a loop until all bugs are gone. https://github.com/Dawoodoz/DFPSR/blob/master/Source/DFPSR/api/bufferAPI.h

Reading source code from old ID software games can show how commercial games were written from scratch in C, before game-makers took over the market. The Quake 3 codebase is quite clean and minimalistic, despite being a high budget game. https://github.com/id-Software


Edited by Dawoodoz on

I'd say memory management is one of the least important things when beginning. You can go a huge way with array + count everywhere and ignore that completely for the beginning.

My goto recommendation is to start with something stupidly simple like Tetris.