How to write a game engine in pure C: Part 2 – The Graphic initialization

If you haven’t read the other posts, go now:

 

We have a state manager now but a game without graphic representation and user interaction has nothing to do in 2019.
In this new chapter we will initialize the ‘human’ layer: graphics and input.

We could write everything from scratch but it’s a pain in the ass (trust me) so we will use SDL to do so. SDL is an abstraction library written in C that gives a common API to system calls for different architectures and OSs.
We don’t want to couple our engine to a library too much, and we will cover that in future posts, but for now we will use SDL tightly coupled, don’t worry, it wont stay like this forever.

So, first we need to get SDL2, either the static/dynamic library or install it in the computer, doesn’t really matter, their website has all the information. Just grab it and build it if you are using windows or mac or use a package manager if you are on linux, it’s easy.
Of course, if you don’t manage to make it work, you could leave a comment here and i’ll try to help 🙂

 

THE GRAPHIC INITIALIZATION

Until now we had a single module in our engine, the state manager. Our architecture will still simple, we will add modules in the src folder, each of those will be a struct that holds everything needed by the module and will have its init and free functions that will be used on the game lifecycle.

The Graphic module will be exactly as described and pretty similar to the state manager module. We will initialize the game’s window with a call to GRAPHICS_init(&graphics) and will destroy it with a call to GRAPHICS_free(&graphics).

Lets code a little:

graphics.h

#ifndef ENGINE_GRAPHICS_H
#define ENGINE_GRAPHICS_H

#include 

typedef struct {
  int width;
  int height;
  SDL_Window *window;
} Graphics;

int GRAPHICS_init(Graphics *graphics);
void GRAPHICS_free(Graphics *graphics);

#endif

Already said that we need all the information for each module in its own structure, right? this is a way to keep everything where it belongs, don’t worry, in the next chapter of the tutorial we will set some order in this mess, but for now this is the structure we will stick with.
In this case, we have a type Graphics, similar to StateManager. It has the screen dimensions and a pointer to the window, that is a SDL type.

Then we have the functions we talked about above, let’s see their implementation.

graphics.c

#include 
#include "graphics.h"

int GRAPHICS_init(Graphics *graphics) {
  graphics -> window = SDL_CreateWindow(
      "C89 Game Engine Tutorial",
      SDL_WINDOWPOS_CENTERED,
      SDL_WINDOWPOS_CENTERED,
      800,
      600,
      SDL_WINDOW_SHOWN
      );

  if (graphics -> window == NULL) {
    SDL_Log("Unable to create window: %s", SDL_GetError());
    return 1;
  }

  return 0;
}

void GRAPHICS_free(Graphics *graphics) {
  SDL_DestroyWindow(graphics -> window);
}

As you can tell, the init function is creating the SDL window, also assigns its pointer to the window variable in the given Graphics structure.
After that, it checks if the window was created and breaks the execution if there were any error.
The free function is even simpler for now, it just calls the SDL function to clean the window object, no mallocs, no frees.

THE LIBRARY INITIALIZATION

Libraries and utilities should be initialized by the engine, not by the modules, that’s why the SDL_Init() function is not in the graphics.c source file.
This is an issue we will address in the next post, for now, the SDL library will be initialized in the main.c file.
To do this we need to remove some “test” code we wrote in the last chapter and add a couple new lines in the main function, just below the STATEMANAGER_init statement we already have.

main.c

  if (SDL_Init(SDL_INIT_VIDEO) != 0) {
    SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
    STATEMANAGER_free(&statemanager);
    return 1;
  }

  Graphics graphics;
  if (GRAPHICS_init(&graphics) != 0) {
    STATEMANAGER_free(&statemanager);
    SDL_Quit();
    return 1;
  }

This code initializes the SDL engine with it’s video stuff (that’s what SDL_INIT_VIDEO means) and assures that it ran properly, breaking the execution if it didn’t and freeing the state manager before exiting the program.
State manager was initialized above, so at this point it has already allocated some memory that should be freed before leaving.

After the SDL init, the graphics are initialized, it follows the same logic than the state manager we wrote. We create a “handler” structure and pass it as reference to the init function, it’ll initialize it and an exception will be thrown if something doesn’t work.

At this point SDL should be initialized, if not, the program would have exited in the previous step, so if the graphics module doesn’t work we have to call SDL_Quit() also to clean it before exiting.

TESTING

We will add some testing code as we did before, to see if everything works.

First of all, we will delete all state definitions but the first one and give it an update function.

main.c

unsigned int updateState1(float deltatime) {
  printf("state 1 update %f\n", deltatime);
  return 0;
}

... MORE CODE ...

  State state1;
  state1.init = initState1;
  state1.update = updateState1;
  state1.destroy = destroyState1;

  Don’t forget to push it into the stack…

 STATEMANAGER_push(&statemanager, &state1);

Now, let’s create the game loop.

THE GAME LOOP

Videogames are mainly based on iteration. You have a loop that will pop events, evaluate input, update the entities and the states, draw the screen, etc.

We will implement our main game loop now in our main function, between the initializations and the free statements.

  int quit = 0;
  SDL_Event e;
  while(!quit) {
    while (SDL_PollEvent(&e)) {
      if (e.type == SDL_QUIT) quit = 1;
    }

    STATEMANAGER_update(&statemanager, 10.0f);
  }

We are using the SDL event handling system here to do our first user interaction, let’s see what happens.

First, we define a “quit” flag and a while loop that will run until we set quit truthy.
The loop then iterates over something called “SDL_PollEvent”, we will cover the event polling in future posts so no need to go deeper here, you just have to know that when a user does something it goes to a stack of performed events, this function pops them one by one.
If there’s a SDL_QUIT event we break the game loop. SDL_QUIT events are automatically created by SDL if we send a signal like clicking in the closing button of the window.

Then, we call the state manager update function. As you should remember from the last post, this function will call the update method of the top state in the stack, in this case, state1.

COMPILATION

Until now the compilation was pretty straight forward, the code of the first part was compiled with a simple gcc statemanager.c main.c, in this case we need something more.
We are using SDL now so we have to link the library and include the headers, i’m using  MAC, it’s different for every OS. In my case is something like this:

gcc -I/Library/Frameworks/SDL2.framework/Headers -F/Library/Frameworks src/graphics.c src/statemanager.c main.c -framework SDL2

in GNU/Linux systems it looks like this:

gcc $(shell sdl2-config --cflags) src/statemanager.c main.c $(shell sdl2-config --libs) -lSDL2main

Try or google it, it’s simple.

Once compiled, executing it will open a 800×600 pixels black window with a title name and we will see in the console the update function being executed once every frame.
Congratulations, you have a graphic system on your engine.

C89 Game Engine Tutorial

Nothing fancy yet, just little closer to have real fun…

In the next few posts we will expand the engine, give it a little more structure and start working on the presentation layer; sprites, images and textures will come soon.

Hope you liked it 🙂

See the whole code in github: https://github.com/PRDeving/GameEngine-C89-tutorial

 

18 thoughts on “How to write a game engine in pure C: Part 2 – The Graphic initialization”

  1. Are you a software engineer ? I mean I was reading the part 1 of game engine and the way you walked through code was quite easy and like a poem. That was cool.

    Can you please tell me how I can write code like you ? I mean I code, but I feel like something’s missing. Like I am not able to write a poem like you with code. I lack the taste to code.

    And like you I love C for some unkown reason than any language. Its close to my heart. But I am not able to flow freely. Any tips (or) advice from ur own experience.

    Like

    1. I’m not a software engineer, i’m just in love with technology. Code read learn, code read learn, code read learn, that’s the only way

      Like

Leave a comment