2D rendering in SDL

    imageFor a long time I did not want to write this article - I thought how to submit the material. But, it can be seen today that the stars have developed successfully and the article about SDL to be. Although, this is just a draft. In the future, this article will be divided into several separate ones - there is enough material and code.

    For those who are not familiar with this old, but very good cross-platform graphics library, I would advise reading this post .
    You can download the library from the official site , I think it will not be difficult. I will not go into details, since it turns out to be simply immense, they can be found here .

    Today we will write a program from scratch that will fill the screen with three colors.

    So let's get started:
    We will have 3 auxiliary classes and the main part of the program, which will “light” the pixels on the screen in any colors. I repeat once again that only the very basics that will be of interest to the reader will be described here.

    First of all, you need to declare a class that will directly load the library and operate with all its functions. Such as (once) a screen lock, working with pixels and the surface on which we will "draw". The main part of the code located in this class is in the help files of our library. Although how it works and why pixels are lit, it would still be useful to find out, it seems to me, but this is beyond the scope of the article.

    SDL_Interface.cpp
    1. #include
    2. #include "Vector_2D.cpp"
    3. #include "Color.h"
    4.  
    5. class SDL_Interface{
    6.   public:
    7.     SDL_Interface(int, int, int);
    8.     ~SDL_Interface();
    9.     void putpixel(int x, int y, const Color&);
    10.     void putpixel(const Vector_2D&, const Color&);
    11.     int const h(); /*Высота экрана экрана*/
    12.     int const w(); /*Ширина экрана*/
    13.     bool const key_wait(int);
    14.  
    15.     void const screen_unlock();
    16.     int const screen_lock();
    17.     void const screen_update(Sint32, Sint32, Sint32, Sint32);
    18.   protected:
    19.     SDL_Surface *screen;
    20.     SDL_Event event;
    21. };
    22.  
    23. SDL_Interface::SDL_Interface(int width, int height, int color_depth) {
    24.  
    25.   /* Инициализация SDL */
    26.   if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
    27.     fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
    28.     exit(1);
    29.   }
    30.  
    31.   screen = SDL_SetVideoMode(width, height, color_depth, SDL_SWSURFACE);
    32.   if ( screen == NULL ) {
    33.     fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
    34.     exit(1);
    35.   }
    36. }
    37.  
    38. SDL_Interface::~SDL_Interface(){
    39.   SDL_Quit();
    40. }
    41.  
    42. int const SDL_Interface::w(){
    43.   return screen->w;
    44. }
    45.  
    46. int const SDL_Interface::h(){
    47.   return screen->h;
    48. }
    49.  
    50. int const SDL_Interface::screen_lock(){
    51.   /* Блокировка экрана для доступа к пикселям */
    52.   if ( SDL_MUSTLOCK(screen) ) {
    53.     if ( SDL_LockSurface(screen) < 0 ) {
    54.       fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
    55.       return 0;
    56.     }
    57.   }
    58.   return 0;
    59. }
    60.  
    61. void const SDL_Interface::screen_unlock(){
    62.   if ( SDL_MUSTLOCK(screen) ) {
    63.     SDL_UnlockSurface(screen);
    64.   }
    65. }
    66.  
    67. void const SDL_Interface::screen_update(Sint32 x, Sint32 y, Sint32 w, Sint32 h){
    68.   SDL_UpdateRect(screen, x, y, w, h);
    69. }
    70.  
    71. bool const SDL_Interface::key_wait(int key_id){
    72.     while ( SDL_WaitEvent(&event) >= 0 ) {
    73.         Uint8 *keys;  
    74.         keys = SDL_GetKeyState(NULL);
    75.     if ( keys[key_id] == SDL_PRESSED ) {
    76.             return true;
    77.         }
    78.         if (event.type == SDL_QUIT){
    79.             exit(0);
    80.         }
    81.      }
    82.     return false;
    83. }
    84.  
    85. void SDL_Interface::putpixel(const Vector_2D& vector_2d, const Color& color)
    86. {
    87.   putpixel(vector_2d.x_coord, vector_2d.y_coord, color);
    88. }
    89.  
    90. /*Вставка пиксела в заданные координаты экрана с указанием цвета*/
    91. void SDL_Interface::putpixel(int x, int y, const Color& color)
    92. {
    93.   Uint32 pixel = SDL_MapRGB(screen->format, color.R, color.G, color.B);
    94.   SDL_Surface *surface = screen;
    95.   int bpp = surface->format->BytesPerPixel;
    96.   Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
    97.  
    98.   switch(bpp) {
    99.   case 1:
    100.     *p = pixel;
    101.     break;
    102.  
    103.   case 2:
    104.     *(Uint16 *)p = pixel;
    105.     break;
    106.  
    107.   case 3:
    108.     if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    109.       p[0] = (pixel >> 16) & 0xff;
    110.       p[1] = (pixel >> 8) & 0xff;
    111.       p[2] = pixel & 0xff;
    112.     } else {
    113.       p[0] = pixel & 0xff;
    114.       p[1] = (pixel >> 8) & 0xff;
    115.       p[2] = (pixel >> 16) & 0xff;
    116.     }
    117.     break;
    118.  
    119.   case 4:
    120.     *(Uint32 *)p = pixel;
    121.     break;
    122.   }
    123. }
    * This source code was highlighted with Source Code Highlighter.


    The class for working with color will be trivial and very small, of course you can add arithmetic operations with colors to it, your own color palettes, but we will not do this.

    Color.h
    1. class Color{
    2.     public:
    3.         Color(Uint8 red, Uint8 green, Uint8 blue) : R(red), G(green), B(blue) {};
    4.         double R, G, B;
    5. };
    * This source code was highlighted with Source Code Highlighter.


    And now, gradually, we are getting closer to the most interesting class, which will guide our points. As we know, each pixel on the screen has two coordinates, so we will pass them to the class constructor. We agree to call a specific point on the screen a vector, and define arithmetic operations between vectors (it is worth noting that all these operations are performed coordinatewise). This is done so that geometric operations on vectors do not cause problems in the future.

    Vector_2D.cpp
    1. class Vector_2D{
    2. public:
    3.     Vector_2D(void) : x_coord(0), y_coord(0) {};
    4.     Vector_2D(int X, int Y);
    5.     Vector_2D operator- (const Vector_2D&) const;
    6.     Vector_2D operator+ (const Vector_2D&) const;
    7.     Vector_2D operator* (const Vector_2D&) const;
    8.  
    9.     int x_coord, y_coord;
    10. };
    11.  
    12. Vector_2D::Vector_2D(int X, int Y){
    13.     x_coord = X;
    14.     y_coord = Y;
    15. }
    16.  
    17. Vector_2D Vector_2D::operator -(const Vector_2D &rhs) const
    18. {
    19.     Vector_2D Point;
    20.     Point.x_coord = (this->x_coord - rhs.x_coord);
    21.     Point.y_coord = (this->y_coord - rhs.y_coord);
    22.  
    23.     return Point;
    24. }
    25.  
    26. Vector_2D Vector_2D::operator +(const Vector_2D &rhs) const
    27. {
    28.     Vector_2D Point;
    29.     Point.x_coord = (this->x_coord + rhs.x_coord);
    30.     Point.y_coord = (this->y_coord + rhs.y_coord);
    31.  
    32.     return Point;
    33. }
    34.  
    35. Vector_2D Vector_2D::operator *(const Vector_2D &rhs) const
    36. {
    37.     Vector_2D Point;
    38.     Point.x_coord = (this->x_coord * rhs.x_coord);
    39.     Point.y_coord = (this->y_coord * rhs.y_coord);
    40.  
    41.     return Point;
    42. }
    * This source code was highlighted with Source Code Highlighter.


    And here is the most important part of our program. This is the whole logic of drawing and control.
    test.cpp
    1. #include
    2. #include "SDL_Interface.cpp"
    3.  
    4. int main(int argc, char** argv) {
    5.  
    6.   //Объявляем поверхность на которой мы будем рисовать с размерами экрана и глубиной цвета
    7.   SDL_Interface *mySDL = new SDL_Interface(800, 600, 32);
    8.  
    9.     //Определяем цвета
    10.     Color blue   (0x00, 0x00, 0xff);
    11.     Color red    (0xff, 0x00, 0x00);
    12.     Color green   (0x00, 0xff, 0x00);
    13.     
    14.     mySDL->screen_lock(); //Блокируем экран перед началом рисования
    15.  
    16.   /*Рисуем путём заливания экрана тремя цветами*/
    17.   for (int x=0; xw(); x++){
    18.         for(int y=0; yh(); y++){
    19.             if(y < (mySDL->h())/3)
    20.                 mySDL->putpixel(Vector_2D(x,y), green);
    21.             else if(y < ((mySDL->h())/3)*2)
    22.                 mySDL->putpixel(Vector_2D(x,y), red);
    23.             else
    24.                 mySDL->putpixel(Vector_2D(x,y), blue);
    25.         }
    26.     }
    27.  
    28.   mySDL->screen_unlock();
    29.   mySDL->screen_update(0,0,0,0);
    30.  
    31.   if (mySDL->key_wait(SDLK_ESCAPE)) exit(0); //Выходим если ESC
    32.     
    33.   return 0;
    34. }
    * This source code was highlighted with Source Code Highlighter.


    In conclusion, I will say that this library conquered me with scope for action. Yes, a lot of what you have to write yourself has been implemented for a long time, but for beginners and for those who just want to play around or create their own game “Life” in c ++ this will be a great choice!

    Also popular now: