Friday, 21 November 2025

[SFML & C++] 9 - Simple UI: Basic Progress Bars // Tutorial

This is part of a series of small projects and tutorials using C++ and SFML

Library version: SFML 3.0.0
C++ Standard: ISO C++20

In this project, we'll make a simple app that includes the basics of a progress bar class. Here's what the finished product will look like:
[SFML & C++] 9 - Simple UI: Basic Progress Bars  // Tutorial


Step 1 - Creating the Progress Bar Class

To start, what's our scenario for this tutorial? I eventually decided on the concept of a "magic bar", pressing space will use all of the magic bar in an 'attack'. Pressing R will refill the magic bar instantly. Pressing S will refill the magic bar over X seconds. When the magic bar is full, the space button can be used again.

This is quite a few mechanics in one, however it features pretty much all of the ground we've covered so far; displaying text, updating text, keyboard input, and timing. Hopefully this project will show you how easy it is to chain mechanics together to create more complex ones.

We'll start off by creating the header file:
There's a few variables here that we won't use just yet. I cheated a bit as well and made the member variables protected so inherited classes can access them without getters/setters. I usually wouldn't do this but it's for conciseness in the tutorial.

Also, this class has virtual functions but it's not abstract. This is an intentional choice because you can have a singular progress bar. In a "proper" project, a class like this would probably inherit from an abstract class like a "Shape". A shape is itself an abstract concept, you can't have a 'shape' by itself, it must have a type. 

As we're going to make this an inheritable class, we should always mark the destructor virtual as well so the correct destructor can be called by the compiler. Not that it matters much in this project but it's a good habit to have.

For the cpp file:


I've set up some defaults here so when we create an instance of it in main, we have something to see. There's nothing in here we haven't seen in earlier tutorials as well.

In main:
We create a font to pass to the constructor of the progress bar, create an instance of it and draw it. It looks something like this:

[SFML & C++] 9 - Simple UI: Basic Progress Bars  // Tutorial

Step 2 - Adding Deplete and Full Refill

So now we have something to work with, lets go ahead and process some events. For this I'm going to create a new class that inherits the progress bar and this will be a specific bar for magic.

The header file:

In here, all we have to do is override the processEvents function which is nice.

The cpp file:


And in main, just replace the instance of our progress bar with a magic bar and call our new process events function.

Now when you run the program you should be able to deplete the magic bar when pressing space and refill it with R. We can also tell this is our new magic bar class because the constructor sets the default colour to red and the base class is green.

We also have some basic checking like, we can't empty the bar further if it's already empty.



Step 3 - Adding Refill Over Time

You might be wondering why we created two rectangles at the start considering a RectangleShape has both a fill and outline. Well, a RectangleShape has no concept of "filling slowly over time" so that's what our mFillRect is for. Basically, the width of mFillRect is determined by mCurrentFillAmount. So for example, if the width of the rectangle is 100 units and the current fill amount is also 100 units, then it appears as "full". If the current fill amount is 50 units, the width is set to 50, giving the appearance of being half empty.

Just like in the first DVD logo tutorial, I'd like this to look smooth, so we'll need to use DeltaTime and an update function that's called each frame.


The deltaTime is used to create an increase amount that's added to the current fill amount each frame based on how long it takes to hit the max fill amount. We then calculate a fill ratio based on the current fill amount as our loading bar is an arbitrary number of units. Perhaps you can get upgrades that make the loading bar bigger? Perhaps it takes a different amount of time to load a level?

We also need to add an event for when the S key is released so it will refill:

And then last, we call the update function in main and pass delta time to it:

And that's it!

[SFML & C++] 9 - Simple UI: Basic Progress Bars  // Tutorial

Note, this is a gif optimised for web so the animation isn't as smooth as when run locally.

Things you should change:
  • The default position of the progress bar is hardcoded in the constructor.
  • A lot of things are hardcoded in the constructor....
  • The base class should probably handle emptying/refilling/timers and have functions that inherited classes can just pass values to that manipulate the effects.
Things you could change:
  • Perhaps space key only uses a certain amount of magic instead of the whole thing?
  • Perhaps there could be a health class? Or a battery left mechanic for a flashlight?
  • Maybe you want a loading bar between levels?
  • Maybe you want a cooldown mechanic between using magic attacks?

No comments:

Post a Comment