Getting started with C programming - Example game -
Here is a very simple shooter game made in C using minimal libraries. This is quite a big of a jump from the last example, but everything is commented, just go to the main function at the bottom and read along, one part at a time.
This page is for Windows. I don't know how to do this on Linux at this time, but you can check the Linux SDL version.
Adding sound and images
Most image and audio files are very complicated so it is highly recommended to use libraries to load them. Audio playback can also be quite involved because audio APIs in operating systems have always been a big mess. Luckily there's simple "single-file header" libraries to help.
- For images: stb_image (this is a collection of different single-file libraries, all you need is the stb_image.h file).
- For audio: miniaudio (all you need is miniaudio.h).
Just download the source code (from the green button that says "code") and extract those into the same place as your project.
That's it. Unlike normal libraries, single-file libraries do not require any additional setup. The only thing you typically need to do is #define something before #including (otherwise you only get the type declarations without the code), here's how to properly include them:
#define MINIAUDIO_IMPLEMENTATION #include "miniaudio-master/miniaudio.h" #define STB_IMAGE_IMPLEMENTATION #include "stb-master/stb_image.h"
Note: loading .bmp image files and .wav audio files by yourself is pretty easy, and I recommend trying it some time as a learning exercise. Those file formats have a very large file size though and the goal of this example game is to do something more practical, so I chose to use libraries instead.
The code
I won't put the code on this webpage since there's about 900 lines of it, instead you can download the code and assets (not including the libraries mentioned above).
Use WASD or arrow keys to move, Space to shoot, Enter to restart, Esc to quit. The enemies will start spawning faster depending on how high your score is.
The project uses some free sounds and music from mixkit.
Note about software rendering and performance
This project renders it's graphics by simply writing pixels into memory (this is called "software rendering"). This works fine in a small window and in programs that don't need to animate graphics much (like FilenameWrangler), but it's still VERY slow compared to how fast a GPU can draw graphics. It's not ideal to do this for full-screen graphical programs like games. You can speed up the rendering by adding -O3
into the compiler command, this tells the compiler to try as hard as it can to optimize your program (it significantly slows down the compile-time though).
I don't exactly know what to recommend for proper graphics, everything has it's own problems.
- Raylib is a graphics framework that seems to be rising in popularity lately due to it's simplicity and easy drawing features. It has some limitations, for example you can't open multiple windows, and it uses a lot of common function/variable names that you might have wanted to use yourself (this is only a problem in C because you can't wrap a library into any kind of "namespace"). It seems to be specifically designed for videogames rather than generic applications, and kind of forces you into it's own way of doing things rather letting you mold it into your ways.
- SDL is a very old (it's still being updated) and widely used library with lots of different features, and includes some graphics rendering functions.
- The most powerful thing you can do is learn to use a graphics API directly. Interacting with GPUs and writing shaders can be very exciting, but it's also more complicated than the other options because there's a lot of uninteresting busywork (like registering a bunch of objects and attributes) involved when using any of these APIs.
- Direct3D is a graphics API made by Microsoft for Windows, there's many versions of it. You might have to use other Microsoft's tools like Visual Studio if you want to use Direct3D, I haven't used it so I'm not sure.
- OpenGL is probably the most popular graphics API, it works on Windows and Linux and maybe some other places too, but is pretty outdated and has some technical limitations, and is "deprecated" in favor of Vulkan.
- Vulkan is a newer "successor" to OpenGL, it's a lot more capable, but also SIGNIFICANTLY harder to use. Vulkan is mostly used by people who develop engines and libraries since they have more time and reason to delve into it. Indie game developers tend to still use OpenGL because it's much more approachable and easy to use, but some do use Vulkan.
- I believe Metal is what Mac uses. I don't have any knowledge about Mac things, but I've heard it's similar to Vulkan.
Drawing text
There's 3 approaches to drawing text:
- Use a bitmap font, which is just an image with letters on it, and then draw small parts of that image one letter at a time. This is the easiest method and very commonly used in videogames, it's also easy to make custom fonts this way. The biggest downside is that you can't resize this font easily without issues, for example it's fine to scale it to 200% or 300%, but becomes ugly if you try to scale it to 80% or 150%.
- Load a font file like .ttf and render the vector shapes into pixels, this is extremely difficult without a library like stb_truetype.
- Create a signed distance field font image and use shaders on the GPU to render it. An SDF font looks like a blurry bitmap font, there's a clever trick to render these blurry characters as sharp text at any size. You could think of this as an advanced combination of the 2 above techniques, it is also often used by videogames. There's a few variations of SDF font rendering, more advanced ones use multiple colors.