πŸ“œ ⬆️ ⬇️

Playing SDL is easy

Surely, everyone had the idea to write some kind of graphic game or program. But there is not always time or desire to master the graphics in programming. I hope this article will help you learn how to write (or just write) a simple but very funny game.
Finished project


It will be a well-known Flood-It. The idea is extremely simple:
It is required to paint over the entire field in one color, despite the fact that you can only paint the entire part of one color adjacent to the upper left square.

Initialization


')
Each program on the SDL must begin with a very important matter - initializing the necessary subsystems and setting the basic parameters. In our example, we only need to initialize the video.
This process is performed using the SDL_Init command.
which takes as a parameter constants (separated by a logical "or") responsible for one or another part. So, for the video subsystem you need to write
SDL_Init(SDL_INIT_VIDEO) 



If you need other systems you can use this list:



Oh, if and then everything was so simple. In fact, this may not always succeed, and you need to crash in case of failure. And for this you just need to follow the value returned by SDL_Init - in case of failure, a negative number is always returned.

 if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { printf( "Unable to init SDL"); return 1; } 



Not too informative. It is useful for users (and us) to know what caused the problem. SDL_GetError () will always return the text of the problem. Using this function we will make the error message more pleasant.

 if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { printf( "Unable to init SDL: %s", SDL_GetError()); return 1; } 


Surfaces



Well, now that we are ready to start creating, we need to figure out how this happens. Images are stored on surfaces (surfaces), with which you can do a lot of useful things - overlay each other, draw on them and so on.
The visible part of the screen will also require a surface. It is not difficult to set this surface, for this there is the SDL_SetVideoMode command that will set the size
this surface (and hence the program screen), the number of bits per color, as well as all sorts of important parameters, including hardware / software acceleration and much more.

There is also one useful parameter SDL_DOUBLEBUF, which adds a buffer to this surface. All actions will not be displayed on the screen until the desired moment. This will speed up our program well (although it is not at all demanding, but it’s more pleasant and cultural).

So, creating the surface as follows

 SDL_Surface * screen = SDL_SetVideoMode(550, 420, 16, SDL_HWSURFACE | SDL_DOUBLEBUF); /// 550x420 β€”     .    16-.     -  SDL_HWSURFACE //     ,   SDL_SWSURFACE( ) 



again we may not get the desired result. Again, we will display an error message and terminate the execution if there is no surface.

 If (!screen) { printf("Can't set videomode: %s", SDL_GetError()); return 1; } 



Images



Now that we have covered all possible problems, nothing bad should happen.
The 14x14 game board will consist of blocks of 6 colors. Each block is nothing more than a simple picture. Frustrating, but SDL can only work with BMP images. However, this problem is solved by connecting the SDL_Image library, but in our example we do not have huge amounts of images, and BMP is enough for us.
You can upload an image to the surface in the following way:

 int InitImages() { for (int i = 0; i < 6; i++) //    6  { char path[20]; for (int j = 0; j < 20; j++) path[j] = 0; sprintf(path, "Block%d.bmp", i); block[i] = SDL_LoadBMP(path); //  BMP     block[i] if (!block[i]) return -1; } return 1; } 



And if something goes wrong during the image upload process, a negative value will be returned (and then we know what to do).
The image after loading is represented by the type already known to us - surface. Therefore, we will store the blocks in an array of block surfaces. It seems that we have everything to bring the playing field. Except for one ... There is a surface with an image, there is a surface of the screen, but how to transfer another surface (or part) to the screen?

For these purposes, there is an SDL_BlitSurface that can rewrite a rectangle from one surface with coordinates x1, y1 and dimensions w, h to another surface at x2, y2. Somehow a lot of parameters, and besides, the coordinates are not transmitted by simple numbers. Once we will display everything only on the screen surface, then we will write a small procedure

 void DrawImage(SDL_Surface * img, int x, int y, int w, int h, int sx, int sy) { SDL_Rect desc; // ,    . desc.x = x; desc.y = y; SDL_Rect src; //  . src.x = sx; src.y = sy; src.w = w; src.h = h; SDL_BlitSurface(img, &src, screen, &desc); } 



Let us analyze the transmitted parameters:
img - the surface, part of which we will add. X, Y - coordinates to which you want to display. SX, SY, W, H - parameters of the displayed rectangle (coordinates of the angle and size). The magic of the transmitted values ​​is that the coordinates must be specified in the type SDL_Rect (from the rectangle), which has 4 values ​​- X, Y, W, H. Well, after specifying the coordinates in the new type, overlaying is performed.

Now is precisely the time to create and, most importantly, draw the playing field. Create a GenMap field generation routine that fills the map with random numbers from 0 to 5 (indicating the color).

 void GenMap() { for (int i = 0; i < maps; i++) for (int j = 0; j < maps; j++) map[i][j] = rand() % 6; } 



Let's add another procedure that displays the image in its rightful place according to the block coordinates (for the X, Y block it will be a rectangle with 30 * X, 30 * Y, 30 * (X + 1), 30 * (Y + 1), for blocks 30x30 pixels).

 void DrawBlock(int x, int y) { DrawImage(block[map[x][y]], 30 * x, 30 * y, 30, 30, 0, 0); //    30*x, 30*y  30x30 } 



And at the same time immediately and create the whole field

 void DrawMap() { for (int i = 0; i < maps; i++) // maps(map size) β€”   . for (int j = 0; j < maps; j++) DrawBlock(i, j); } 



Time to check out what happened. We generate a field, output, and ... Nothing! How so? It seems everything is correct, but ... Screen buffer, do not forget to display it. This is done simply

  GenMap(); DrawMap(); SDL_Flip(screen); 



It is SDL_Flip that will perform the desired action with the screen. And now you can see the result:
Result

Great, it works.
On this, perhaps, it is worth stopping in this article. Continued here .

Source: https://habr.com/ru/post/134936/


All Articles