Posts
Search
Contact
Cookies
About
RSS

raylib a novices guide for creating a simple game

Added 30 Jun 2019, 11:45 a.m. edited 18 Jun 2023, 7:18 p.m.

First off its important to have a clear goal in mind...


But before we get carried away, you need some prerequisites, first of all you need raylib installed and you should verify you can compile the examples and that they work.

You need to have at least some exposure to programming in C, you should understand basic topics like functions, variable scope, and be able to create a simple console app (for example) to take two numbers from the user, add them together and print the result. Additionally some idea of what a pointer is would be very useful, well.... okay essential.

At this point it would be a good move to run each of the examples and look at their code, look at the raylib cheat sheet as you do this (in fact although there are a large number of examples don't skip looking at them all !). Don't be afraid to look at the source code for raylib either, its well written and well commented too. Hopefully after you've done all this, it should give you a good idea of the various capabilities of raylib.

Okay, by this point hopefully I haven't lost too many of you! Some of the concepts I'll introduce will need some thought, especially if you've never encountered them before, but shouldn't be too onerous to get a solid grasp of.

When I first got my hands on raylib two thing that got my interest were the game templates and especially the core_window_letterbox example. Inspired by the templates I set to creating a simple game, there are a number of advantages to scaling your game screen, but the main one is that regardless of the window size and even in full screen mode, you are always rendering to the same sized "screen" so you don't have to worry about scaling everything you do, an even worse thing to do would be to fix your window size (The examples do this, in order make them as brief and simple to understand as possible - thankfully the examples aren't enmeshed in some horrid example framework - which you often see with other libraries!).

The core of our game (the main function) will act as I kind of switchboard for the various "screens" this will allow you to segregate all your code into discreet units, for example we'll have a splash screen, a main menu and a game screen, this also means that later if we want a settings screen we can just drop a new source file and get coding, integrating it with the core of the application will be trivial and quick.

Unfortunately this does mean a little bit of complication (oh the horror!) as I've used callback to make things easier in the long run. If you have no idea what a callback is don't worry, take a look at the Wikipedia entry on callbacks its actually quite clear and has a number of examples in C to boot!

With each "screen" having a common set functions, it doesn't matter to the main switchboard which screen is active, it just calls the update or render function as needed, the main function doesn't deal with any specifics of the different screens other than deciding which screen should be active next when the current screen decides it wants to exit.

The screens.h include gives you an idea how this is organized, each screen has the following functions

    updateFunc update;
    renderFunc render;
    freeFunc destroy;
    doneFunc done;
    resetFunc reset;

Note that I've wrapped up each of the function prototypes as types (updateFunc, renderFunc and so forth) . While update and render are fairly obvious, there is a distinction between destroy and reset, reset will just reset the state of a screen, whereas destroy will (hopefully!) release any resources the screen is holding, the done function is called to find out if the screen wants to quit. Those of you paying attention will notice there is no set up call here, that's because each screen has its own setup function that returns this callback structure, these appear at the top of our main unit as prototypes (rather than including the screens headers which would pull in all sorts of stuff we neither want nor need)

You should also note that each screen itself is isolated from any other screen, later on the game screen will interact with other units as it has separate code for things like aliens, shots (missiles) and even player code. Keeping stuff static is often good practice as it allows you more easily follow whats going on, just as spaghetti code is a really bad idea, spaghetti globals are quite unhelpful, globals are not in themselves terrible, used in limited circumstances they can be helpful as long as you can keep track of every place that they are being modified....

There is just one unit that isn't directly involved with screen handling but is used by the menu screen, the button.c unit is a utility inspired by the textures_sprite_button.c example, I've made a struct and set of functions to make adding simple buttons easy.

There is one caveat to scaling the screen, you need to compensate the mouse position to allow for the scale and letterbox margin, you can see this being done in the menu screens update function.

While we haven't got an actual game yet, I've put some some code in the game unit to move a bunch of different coloured stars down the screen, hopefully you should have sufficient C skills, to work out what's going on inside the game unit.

It is worth mentioning however how the array of stars is stored. I could have had a simple array of star structs, but for some reason I can't quite remember I just allocated a block of memory, as the pointer to this memory is a star struct pointer, you can simply treat it as an array of star structs, often people new to C miss that this is a fundamental part of the C specification... I think Wikipedia explains it better than the actual spec...

One last feature, in order to test StorageSaveValue for settings, the game saves the fullscreen state for the next time the game is run, although the persistent store only stores integers, its ideal for things like key bindings etc.

Okay so no actual game coding per se, but a good solid foundation for the game.... you can see the source code for this post here, there's plenty of other stuff in there so have a good look through it an make sure you understand what's going on.

The next part continues here