Internship at OpenGenus

Get this book -> Bug on Array: For Interviews and Competitive Programming

Reading time: twoscore minutes | Coding time: 20 minutes

Yes! You tin do graphics using C++ and also create blitheness. Today in this article I volition innovate you all to a C++ graphic library called SDL2. I detect this library as a super fun for the demonstration of my algorithms. I promise that information technology might me useful to you some solar day, who knows! Very well so, lets go started.

We will start past implementing a basic class design which initialize various parameters of SDL with a clear black window. From there, nosotros will implement cartoon dissimilar shapes and then we volition create a uncomplicated animation of those shapes! This will be the scope of this tutorial.

Feeling excited already? Lets get moving...

Installation

Assuming yous are using ubuntu 16 or xviii, y'all can but install by using apt

            sudo apt install libsdl2-dev libsdl2-two.0-0 -y;                      

For other operating system, you can use the google to search for the installation. If you are having difficulty installing then mention it in the comments. I will do my best to help you out.

Anyways, lets move on..

Showtime, we volition start by creating an empty directory. For that you can use the gui or terminal, your choice. Lets phone call that directory "sdl_intro".

Below is the CMakeLists.txt file which will ascertain the build instruction for this project. Be SUPER SUPER SURE, that you proper noun it every bit "CMakeLists.txt" only (without the quotes) and nothing else.

            cmake_minimum_required (VERSION 3.0) set up(CMAKE_BUILD_TYPE Debug)  # Below line is for using C++fourteen standard set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")  # Our project name projection (framework)  add_executable(framework main.cpp)  # For finding our SDL2 parcel! INCLUDE(FindPkgConfig)  # Searching SDL2 package. PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)  # Including our external library's directory for header files! INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS})  # Linking SDL2 library with our project. target_link_libraries(framework ${SDL2_LIBRARIES})                      

Below is the main file for this project which has to be in the same directory equally the CMakeLists.txt file.

            #include <SDL.h>  form Framework{ public:     // Contructor which initialize the parameters.     Framework(int height_, int width_): height(height_), width(width_){         SDL_Init(SDL_INIT_VIDEO);       // Initializing SDL as Video         SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer);         SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);      // setting depict color         SDL_RenderClear(renderer);      // Articulate the newly created window         SDL_RenderPresent(renderer);    // Reflects the changes washed in the                                         //  window.     }      // Destructor     ~Framework(){         SDL_DestroyRenderer(renderer);         SDL_DestroyWindow(window);         SDL_Quit();     }  individual:     int height;     // Peak of the window     int width;      // Width of the window     SDL_Renderer *renderer = Goose egg;      // Pointer for the renderer     SDL_Window *window = Nix;      // Pointer for the window };  int principal(int argc, char * argv[]){      // Creating the object past passing Height and Width value.     Framework fw(200, 400);      SDL_Event consequence;    // Upshot variable      // Beneath while loop checks if the window has terminated using close in the     //  corner.     while(!(consequence.type == SDL_QUIT)){         SDL_Delay(10);  // setting some Delay         SDL_PollEvent(&issue);  // Catching the poll event.     } }                      

At present, brand sure you are in the "sdl_intro" directory. Create a new folder or directory chosen "build". I will demonstrate using last commands below.

            mkdir build/ cd build/ cmake ../ make                      

The higher up commands will create a directory called build and then build the projection. Yous last might look like this

            your@computer:~/sdl_intro/build$ cmake ../ -- The C compiler identification is GNU vii.four.0 -- The CXX compiler identification is GNU 7.4.0 -- Check for working C compiler: /usr/bin/cc -- Bank check for working C compiler: /usr/bin/cc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - washed -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - washed -- Detecting CXX compile features -- Detecting CXX compile features - done -- Plant PkgConfig: /usr/bin/pkg-config (establish version "0.29.one")  -- Checking for 1 of the modules 'sdl2' -- Configuring done -- Generating washed -- Build files have been written to: /home/shivang/sdl_intro/build your@calculator:~/sdl_intro/build$ brand Scanning dependencies of target framework [ 50%] Building CXX object CMakeFiles/framework.dir/main.cpp.o [100%] Linking CXX executable framework [100%] Built target framework                      

If you encounter this, it means that your project has been build successfully. Now an executable has generated in your build/ directory called framework. Just type following in the final

            ./framework                      

And you can come across a blackness window on your computer screen like this

Screenshot-from-2019-09-29-18-52-51

You lot can click on cantankerous to terminate the window. Congrats! You lot have crossed the first checkpoint of this tutorial.

Lets empathize the code

And so, we have created a course chosen Framework. The constructor of Framework initializes two of import SDL initializers, SDL_Init() and SDL_CreateWindowAndRenderer(). The former initializes SDL library with some flag for case, nosotros have passed SDL_INIT_VIDEO flag. That means we are telling SDL to be initialized in a video manner. There many different modes for SDL. Only we won't be learning or discussing those in this commodity.

Moving frontwards, nosotros encounter another SDL function called SDL_SetRenderDrawColor() which requires renderer pointers and four more values. It sets the cartoon color for the renderer, in our example black because nosotros are passing all the values as 0. SDL uses 8-bit color values in Red-Light-green-Blue-Alpha order where alpha indicating transparency.

Next function we encounter is SDL_RenderClear() which clears the entire screen to which the passing renderer is pointing with the previously prepare renderer draw-color which in this case is black. The changes done to the screen won't be reflected unless you call SDL_RenderPresent(). At present yous might enquire, why not reflect the screen every time we update the renderer? If you practice that you might feel the lag on the screen as changing the pixels every time would increase the complexity by O(height x width). Then, brand sure yous only show what is important.

Now, I will uncover the mystery behind the SDL_Events issue line and below line of the code.

            // Below while loop checks if the window has terminated using shut in the     //  corner.     while(!(event.type == SDL_QUIT)){         SDL_Delay(10);  // setting some Delay         SDL_PollEvent(&event);  // Communicable the poll issue.     }                      

So, SDL_Events is merely a SDL custom data type which stores the event on the SDL window. Such as closing, mouse hovering, mouse click etc. We volition focus on issue when we press the terminate push or "cross" button. Lets merely say that we won't use these lines, what will happen? The object is created in the master role that means the window will exist created simply after that the program ends that ways destructor will exist called and SDL window will be destroyed. This all will happen in a separate 2nd. Then in order to let it open up, we take to create a loop that won't allow the program to get out from the main part. That'south why I have created a while loop which volition only exit when we click the close button on the window. And this close-button-click even is capture using SDL_PollEvent() function.

Drawing shapes.

Lets starting time with a circle! Copy and replace the main code with the below code which is updated to draw circle.

            #include <SDL.h> #include <cmath>  class Framework{ public:     // Contructor which initialize the parameters.     Framework(int height_, int width_): height(height_), width(width_){         SDL_Init(SDL_INIT_VIDEO);       // Initializing SDL as Video         SDL_CreateWindowAndRenderer(width, elevation, 0, &window, &renderer);         SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);      // setting draw color         SDL_RenderClear(renderer);      // Clear the newly created window         SDL_RenderPresent(renderer);    // Reflects the changes done in the                                         //  window.     }      // Destructor     ~Framework(){         SDL_DestroyRenderer(renderer);         SDL_DestroyWindow(window);         SDL_Quit();     }      void draw_circle(int center_x, int center_y, int radius_){         // Setting the color to be RED with 100% opaque (0% trasparent).         SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);          // Drawing circle         for(int ten=center_x-radius_; ten<=center_x+radius_; x++){             for(int y=center_y-radius_; y<=center_y+radius_; y++){                 if((std::prisoner of war(center_y-y,ii)+std::pow(center_x-x,2)) <=                      std::prisoner of war(radius_,two)){                     SDL_RenderDrawPoint(renderer, 10, y);                 }             }         }          // Testify the alter on the screen         SDL_RenderPresent(renderer);     }  individual:     int top;     // Height of the window     int width;      // Width of the window     SDL_Renderer *renderer = NULL;      // Arrow for the renderer     SDL_Window *window = Goose egg;      // Pointer for the window };  int chief(int argc, char * argv[]){      // Creating the object by passing Superlative and Width value.     Framework fw(200, 400);      // Calling the function that draws circumvolve.     fw.draw_circle(200, 100, l);      SDL_Event event;    // Event variable      // Below while loop checks if the window has terminated using shut in the     //  corner.     while(!(event.type == SDL_QUIT)){         SDL_Delay(10);  // setting some Delay         SDL_PollEvent(&effect);  // Catching the poll result.     } }                      

Later on changing the chief.cpp code with the to a higher place, y'all tin attempt building the projet again. For that, repeat the previously explained step where y'all have to go into build/ directory and type brand command in the terminal. You can get the below outcome when executing framework file.

Screenshot-from-2019-09-30-14-29-38

You can see a red circle, centered at the middle of the screen. Let me explain the changes in the lawmaking.

And then, I started past implementing a new method called draw_circle() which takes iii parameters, x & y coordinate of the circumvolve'due south center and radius of the circle.

In this method, I am changing the renderer's drawing colour to red by passing second argument as 255, and too I want it 100% opaque that'due south why I am passing 255 to the terminal argument.

Subsequently colour, lets talk over how I created a circle. At that place is ane method in SDL which can depict pixel on the screen, its called SDL_RenderDrawPoint(). I am passing the renderer and x-y coordinates of the screen to this function.

So, you might exist wondering that what would exist the logic backside drawing the circle. But before that allow'southward revise the math definition of circle.

MATH

All the points on the circle follows the post-obit equation

img

Where, h & k are the 10 and y coordinate of the eye, respectively. As well, x and y are the corresponding coordinate indicate on the circle. Now, lets manipulate the circle'southward formula a bit. Lets supercede the equal sign with less than equal sign. What would that correspond? All the points bounding the circle.

At present coming back to our draw_circle method, you lot can see the if condition in the for loop. I am checking the circle inequality in the if condition, and if the point is satisfy and so depict the point.

For the points, I start with by square which ranges from (centre point - radius) to (center signal + radius). Nosotros cheque each of these points if they satisfy the inequality they will be change using draw_circle method.

Congrats! you lot have completed 2nd milestone of the article!

Animation in SDL

For animation, we volition take the circle and move it up and down the screen. Permit'south get started! First of all y'all have to re-create the code beneath and supplant it with what you lot already accept.

            #include <SDL.h> #include <cmath> #include <vector>  form Framework{ public:     // Contructor which initialize the parameters.     Framework(int height_, int width_): height(height_), width(width_){         SDL_Init(SDL_INIT_VIDEO);       // Initializing SDL as Video         SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer);         SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);      // setting draw color         SDL_RenderClear(renderer);      // Clear the newly created window         SDL_RenderPresent(renderer);    // Reflects the changes done in the                                         //  window.     }      // Destructor     ~Framework(){         SDL_DestroyRenderer(renderer);         SDL_DestroyWindow(window);         SDL_Quit();     }      void draw_circle(int center_x, int center_y, int radius_){         // Setting the color to exist Ruby-red with 100% opaque (0% trasparent).         SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);          // Drawing circle         for(int x=center_x-radius_; x<=center_x+radius_; x++){             for(int y=center_y-radius_; y<=center_y+radius_; y++){                 if((std::prisoner of war(center_y-y,2)+std::pow(center_x-10,2)) <=                      std::pow(radius_,2)){                     SDL_RenderDrawPoint(renderer, x, y);                 }             }         }          // Show the change on the screen         SDL_RenderPresent(renderer);     }      void move_circle(){         // Setting the colour to be Red with 100% opaque (0% trasparent).                  SDL_Event event;    // Event variable         while(!(effect.blazon == SDL_QUIT)){              // Circle will get down!             for(int i=0; i<acme; i++){                 SDL_Delay(10);  // setting some Filibuster                 SDL_PollEvent(&result);  // Catching the poll effect.                 if(event.blazon == SDL_QUIT) return;                 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);                 SDL_RenderClear(renderer);                 draw_circle(width/2, i, 25);             }              // Circle will go up!             for(int i=height; i>0; i--){                 SDL_Delay(10);  // setting some Delay                 SDL_PollEvent(&outcome);  // Communicable the poll event.                 if(event.type == SDL_QUIT) return;                 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);                 SDL_RenderClear(renderer);                 draw_circle(width/2, i, 25);             }         }              }  private:     int height;     // Elevation of the window     int width;      // Width of the window     SDL_Renderer *renderer = NULL;      // Pointer for the renderer     SDL_Window *window = Zero;      // Arrow for the window };  int main(int argc, char * argv[]){      // Creating the object past passing Height and Width value.     Framework fw(200, 400);      // Starting the animation     fw.move_circle();          render 1; }                      

Now build the projection and run the executable. Now y'all tin run into the red circle moving up and downwards the screen. As always, you tin cease the window past clicking the cantankerous button. Did you noticed any modify to the code?

Y'all guessed it right! I have added a new member function called move_circle(). If you can see it carefully I have logically designed the for loop in such a style that it will get upwards and down continuously. Allow me explain in item nigh what happens in the for loop.

So the for loop starts with i=0 and increments past 1 every loop till max height of the screen. In the loop, beginning we are checking if the shut or cross button has been hitting. If it's been hit then exit the function and render to the primary function. At present assuming it'due south not been hit yet, we gear up the renderer's colour as black in the next line. Then after that we clear the screen with blackness color. And then we are calling the draw_circle method which draws the circle and calls SDL_RenderPresent() method which will reflect all changes that happen since terminal call.

Notation hither that I am calling SDL_RenderPresent() when I want to see the change. Also remember that not every alter is work showing on the screen. For eastward.chiliad. I am clearing the screen with black colour just I am not showing information technology on the screen. What will happen if I do that? I think you capable to play with it by yourself to know the reply. Try it and let me know in the comments.

Some untouched topics in SDL2

  • You lot can play effectually with textures.
  • You can access audio to make information technology an interactive application.
  • A fun and existent world application of SDL would exist using information technology to brand a arcade games.
  • Also, possibilities are endless.

Happy Coding...

Question

How would you lot change the equation of the circle to draw just the border?

Using both less than and greater than comparision

greater than comparing only

with just an equal to sign

None of the above

If you utilise equal sign only so y'all won't be able to see the edge quite round. That'due south why you lot have to use option A, because piddling threshold helps to visualize the border!