SDL Tutorial Part 1: Opening A Window
Tags: gamedev, programming, c
Published: 2024-02-17 16:45:22


![SDL Logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5w36k6xjb6uu93o5i4nk.png)
I was recently learning SDL2, and I found the lack of tutorials in plain C frustrating. I've decided to be the change I wanted to see in the world, and write my own. This will be a multi-part series, and will serve as a quick reference for how to do common things in SDL2. I've listed the main functions at the top of the tutorial kind of like the Raylib Cheatsheet, if you just need a quick reference.

Before we dive in, I want to point out an immensely helpful resource that will be useful as you become more experienced.  [The SDL2 Wiki](https://wiki.libsdl.org/wiki/index) contains an index which has a link to every SDL function wiki page. This will teach you everything you need to know about calling the function and handling its output properly. If a big list of functions is too disjointed, there is also a [wikipage](https://wiki.libsdl.org/SDL2/APIByCategory) that links to the same resources, but organized into API categories as well. This can be useful as common operations usually require multiple functions that are related.

## Open a Window Cheat Sheet
1. [SDL_Init](https://wiki.libsdl.org/SDL2/SDL_Init)
2. [SDL_CreateRenderer](https://wiki.libsdl.org/SDL2/SDL_CreateRenderer)
2. [SDL_CreateWindow](https://wiki.libsdl.org/SDL2/SDL_CreateWindow)
3. [SDL_SetRenderDrawColor](https://wiki.libsdl.org/SDL2/SDL_SetRenderDrawColor)
4. [SDL_RenderClear](https://wiki.libsdl.org/SDL2/SDL_RenderClear)
5. [SDL_RenderPresent](https://wiki.libsdl.org/SDL2/SDL_RenderPresent)
6. [SDL_DestroyWindow](https://wiki.libsdl.org/SDL2/SDL_DestroyWindow)
7. [SDL_DestroyRenderer](https://wiki.libsdl.org/SDL2/SDL_DestroyRenderer)
8. [SDL_Quit](https://wiki.libsdl.org/SDL2/SDL_Quit)

## Tutorial
The simplest and fastest way to get a window open in SDL2 is to write the following code.

```C
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>

#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 720

int main() {
    SDL_Window *window = SDL_CreateWindow("Example: 0", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_SetRenderDrawColor(renderer, 255,255,255,250);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);
    SDL_Delay(2000);
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    SDL_Quit();
    return EXIT_SUCCESS;
}
```

![Example white SDL Window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2bs17g8gzkyyjtotk7m4.png)
But this is not recommended. It's possible that many of the functions that we just called can fail, so we want to include a few more checks to make sure that everything is working correctly. Let's do that now

```C
int main(){
  if (SDL_Init(SDL_INIT_VIDEO) < 0){
    printf("Couldn't initialize SDL: %s\n", SDL_GetError());
    return EXIT_FAILURE;
  }

  SDL_Window *window = SDL_CreateWindow("Example: 0", SDL_WINDOWPOS_UNDEFINED,
					SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
  if (!window){
    printf("Failed to open %d x %d window: %s\n", SCREEN_WIDTH, SCREEN_HEIGHT, SDL_GetError());
    return EXIT_FAILURE;
  }

  SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
  SDL_SetRenderDrawColor(renderer, 255, 255, 255, 250);
  SDL_RenderClear(renderer);
  SDL_RenderPresent(renderer);
  SDL_Delay(2000);
  SDL_DestroyWindow(window);
  SDL_DestroyRenderer(renderer);
  SDL_Quit();
  return EXIT_SUCCESS;
}
```

The first thing we do is call [SDL_Init](https://wiki.libsdl.org/SDL2/SDL_Init) and pass the flag `SDL_INIT_VIDEO`, which initializes the video subsystem. SDL has many initialization flags that you can bitwise OR (`|`) together to initialize multiple subsystems at once. For example like this
```
    // Initialize SDL with video and audio subsystems
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
        printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
        return 1;
    } else {
        printf("SDL video and audio initialized successfully.\n");
```

But we will stick to the video subsystem for now. Next we will call `SDL_CreateWindow`. It takes in a title, x and y for the window position, width and height for the window size, and some flags. If we go to the wikipage for [SDL_CreateWindow](https://wiki.libsdl.org/SDL2/SDL_CreateWindow) we will see the function prototype, a description of its parameters (including flags that can be passed), and the expected return values on failure. This is how I knew what that I wanted to pass `SDL_WINDOWPOS_UNDEFINED` for the x and y, and let the operating system handle window placement.

Moving on, we create our renderer with [SDL_CreateRenderer](https://wiki.libsdl.org/SDL2/SDL_CreateRenderer). We give it the window we created, so we can render to it, and pass its index parameter `-1` to initialize the first rendering driver that can support our requested parameter flag of `0`. You will always pass `-1` as the **index parameter** unless you have a good reason not to. For the **render flag** we pass `0` which defaults to `SDL_RENDERER_ACCELERATED` (using hardware acceleration for the graphics) if it is supported on your system. If you want to be more explicit you can pass `SDL_RENDERER_ACCELERATED` instead. Just like with the SDL window, we write an if statement to check if the renderer was created so that we don't accidentally use it if it hasn't been initialized.

Next we call [SDL_SetRenderDrawColor()](https://wiki.libsdl.org/SDL2/SDL_SetRenderDrawColor) and pass it our renderer, as well as 4 integers with values from 0-255. The 4 integers correspond to `Red`, `Green`, `Blue`, and `Alpha` values of a color. The alpha controls the transparency of the color, while setting the R, G, and B values to various levels allow you to create any color you want between `0,0,0,255` (Black) and `255,255,255,255` (White). [SDL_RenderClear()](https://wiki.libsdl.org/SDL2/SDL_SetRenderClear) takes our renderer and clears it with the white color we set using `SDL_SetRenderDrawColor`. [SDL_RenderPresent()](https://wiki.libsdl.org/SDL2/SDL_RenderPresent) displays our graphics to the screen (just a white window for now) and then we call [SDL_Delay(2000)](https://wiki.libsdl.org/SDL2/SDL_Delay) which specifies a number of milliseconds to wait before moving onto the next piece of code. Normally the rendering code will be in a while loop that will constantly update until the user quits the game, but for simplicities' sake, we will stick with a delay for now.

[SDL_DestroyWindow](https://wiki.libsdl.org/SDL2/SDL_DestroyWindow) safely removes our window once we are done with it. If for whatever reason the window was not initialized, it is still safe to call this on the `window` variable. The same goes for [SDL_DestroyRenderer](https://wiki.libsdl.org/SDL2/SDL_DestroyRenderer). It does the same thing as `SDL_DestroyWindow` and cleans up our renderer. Finally we call [SDL_Quit](https://wiki.libsdl.org/SDL2/SDL_Quit) which cleans up the systems we initialized before we close our program.

And that is it, we've created our first window in SDL. In the next tutorial we will look at how to draw text on the screen.

One last thing to note. I will not be abstracting many things to functions or multiple files in these first few tutorials. I believe it's important when you are learning a new library, to keep it as simple as possible. As the code gets longer this will become a bigger pain point, and that is good. You will have a much clearer picture about what we should abstract, and why we should abstract it, as you become more familiar with SDL. Feel free to come up with your own abstractions as you see fit

## FAQ
### Why do we clear the screen with a color?
We clear the screen with a color so that the previous frames pixels don't interfere with the next frames pixels. For example, if we have a square on the screen that we are moving with the `WASD` keys, if we don't clear the screen, then square will smear across the screen as the old pixels from it's old position are not "wiped" away.

### Why SDL and not Raylib?
[Raylib](https://www.raylib.com/) is an awesome C library for creating games, and Raysan specifically made it for teaching. He did [a comparison](https://gist.github.com/raysan5/17392498d40e2cb281f5d09c0a4bf798) at one point between the two frameworks, though it is a little dated at this point. It is easier to learn and make new FFI bindings for Raylib than it is for SDL and Raylib comes with more convenience features out of the box. You are not making a mistake if you choose Raylib. But SDL has been around over twice as long as Raylib. Many of the open source projects I'm interested in contributing to (Doom Source Ports, [OpenMW](https://gitlab.com/OpenMW/openmw), and others were started before Raylib existed and use SDl2. Since these projects use SDL so will I. SDL2 is also a little lower level than Raylib, and requires you to work at a lower level with it's subsystems. This means instead of placing drawing code between a `BeginDrawing` and `EndDrawing` block like in Raylib, you have to set up the renderer, create textures, copy them to the GPU, before finally presenting it to the screen. I find this process to be enlightening.  


## Call To Action 📣
Hi 👋 my name is Diego Crespo and I like to talk about technology, niche programming languages, and AI. I have a [Twitter](https://twitter.com/deusinmach) and a [Mastodon](https://mastodon.social/deck/@DiegoCrespo), if you’d like to follow me on other social media platforms. If you liked the article, consider checking out my [Substack](https://www.deusinmachina.net/). And if you haven’t why not check out another article of mine listed below! Thank you for reading and giving me a little of your valuable time. A.M.D.G