Glusoft

Make a health bar with SDL

In this tutorial, we will make a health bar with SDL and SDL2_image.

A simple health bar

Introduction of making a health bar with SDL

You will need to have SDL2_image installed and working properly, if not you can follow this tutorial: Display an image with SDL_image

For the include you simply need SDL2, SDL2_image and iostream :

#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
#include <iostream>

After that you can initialise the SDL2 context with the PNG format, inside a main function:

SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
IMG_Init(IMG_INIT_PNG);
SDL_Window* window = SDL_CreateWindow( "Health bar", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_SHOWN );
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

Loading the texture

The next step is to load the image for making the health bar and create a texture from a surface.


You can download the empty health bar image :
Health Bar

You can also download ressources for the health bar on other tutorials, here are some health bar from Brackeys


Here is the code to load to create the texture and load the image, the SDL_Surface reside in the CPU memory (ram) but to render the texture we need to have a SDL_Texture which reside in the GPU memory (vram) :

SDL_Surface* healthbar_sur = IMG_Load("img/healthbar.png");
SDL_Texture* healthbar_tex = SDL_CreateTextureFromSurface(renderer, healthbar_sur);

SDL_Rect rect{100, 100, 200, 22};
    
int x = 0; // x position of the mouse

We also want to store the x position of the mouse because we want to add some interaction to the health bar.
We will use the mouse position to fill the health bar accordingly.

The event loop

The event loop allow the player to quit the app and record the x position of the mouse. The mouse position is bound between 196 and 392, if we exceed the positions we reset the variable to the nearest value. The event SDL_MOUSEMOTION occurs when the player move his mouse cursor.

while (true) {
    SDL_Event e;
    if (SDL_WaitEvent(&e)) {
        if (e.type == SDL_QUIT) {
            break;
        }
        if(e.type == SDL_MOUSEMOTION) {
            x = e.motion.x;
                
            if(x < 196)
                x = 196;
                
            if(x > 392)
                x = 392;
        }
    }

The rendering

We need to render everything the texture and the red rectangle which size depend on the x mouse position. The function SDL_SetRenderDrawColor set the default color used in the renderer. SDL_RenderClear clear the renderer with the default color. SDL_RenderFillRect creates a rectangle with the default color.

	SDL_Rect rect2{102, 102, (x-196), 18};
        
	SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
	SDL_RenderClear(renderer);
	
	SDL_RenderCopy(renderer, healthbar_tex, NULL, &rect);
	
	SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
	SDL_RenderFillRect(renderer, &rect2);
	
	SDL_RenderPresent(renderer);
}

Cleanup

Time to do some cleanup when the main loop is exited, we delete the texture of the health bar, the renderer and the window. Then we quit SDL2_image and SDL.

SDL_DestroyTexture(healthbar_tex);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();

Full source code to make a health bar with SDL

#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
#include <iostream>

int main( int argc, char* args[] )
{
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
    IMG_Init(IMG_INIT_PNG);
    
    SDL_Window* window = SDL_CreateWindow( "Health bar", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_SHOWN );
        
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    SDL_Surface* healthbar_sur = IMG_Load("img/healthbar.png");
    SDL_Texture* healthbar_tex = SDL_CreateTextureFromSurface(renderer, healthbar_sur);

    SDL_Rect rect{100, 100, 200, 22};
    
    int x = 0; // x position of the mouse
    
    while (true) {
        SDL_Event e;
        if (SDL_WaitEvent(&e)) {
            if (e.type == SDL_QUIT) {
                break;
            }
            if(e.type == SDL_MOUSEMOTION) {
                x = e.motion.x;
                
                if(x < 196)
                    x = 196;
                
                if(x > 392)
                    x = 392;
            }
        }
        SDL_Rect rect2{102, 102, (x-196), 18};
        
        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
        SDL_RenderClear(renderer);
        
        SDL_RenderCopy(renderer, healthbar_tex, NULL, &rect);
        
        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        SDL_RenderFillRect(renderer, &rect2);
        
        SDL_RenderPresent(renderer);
    }

    SDL_DestroyTexture(healthbar_tex);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    IMG_Quit();
    SDL_Quit();

    return 0;
}