📜 ⬆️ ⬇️

Playing SDL is doubly easy

This article is a continuation of this post .
This time we will look at keyboard and mouse key events, text drawing using the finished library and hands. And besides, we get moral satisfaction by completing the game to the end.


Developments



Now that we have a fully working drawing of the map, we need to respond to the actions of the player.
In general, every user action (closing a program, pressing a key, moving a mouse) can be obtained using SLD_PollEvent. As a parameter, a variable (more precisely, its address) of type SDL_Event is passed, which will store the last event. Having received the event, we must check whether it is necessary for us at all. To begin with, we are implementing the important thing - closing the program on an exit event. We will walk endlessly around the cycle in anticipation of the event we need, and once we receive it, we will exit the main loop.
while (!done) { while (SDL_PollEvent(&event)) //       { swtich(event.type) { case SDL_QUIT: //   done = true; } } } 


')
Run and check the result. Now the window will close on completion events (ALT + F4 and the corresponding button of the program window). But, here we did not consider one important thing. If we do not have an event, then the program will uselessly waste processor time, going on a cycle:



Instead, let's just wait for the event:

 while (!done) { SDL_WaitEvent(&event); //   } 


Thereby greatly reducing the needs of the game.
The result is significant:



Implement a mouse click event. The player can, by clicking on any block, select the color he needs. Blocks lie in coordinates from 0 to 30 * maps. Therefore, any clicks do not interest us.

 case SDL_MOUSEBUTTONDOWN: { if (event.button.button = SDL_BUTTON_LEFT) { int x = event.button.x, y = event.button.y; //   if (x < 30 * maps && y < 30 * maps) AddColor(map[x / 30][y / 30]); DrawStep(); //    ,     . SDL_Flip(screen); } break; } 



The AddColor procedure is a deep search with drawing of each changed cell using DrawBlock and changing the count of the number of moves to 1, so it is not of particular interest to us.

Implementing a move on a given key is not more difficult, but you will have to consider each button separately:

 case SDL_KEYDOWN: { switch(event.key.keysym.sym) { case SDLK_ESCAPE: //      Esc { done = true; break; } case SDLK_b: //  B { AddColor(COLOR_BLUE), DrawStep(), SDL_Flip(screen); // COLOR_BLUE — define   break; } case SDLK_g: { AddColor(COLOR_GREEN), DrawStep(), SDL_Flip(screen); break; } case SDLK_o: { AddColor(COLOR_ORANGE), DrawStep(), SDL_Flip(screen); break; } case SDLK_r: { AddColor(COLOR_RED), DrawStep(), SDL_Flip(screen); break; } case SDLK_v: { AddColor(COLOR_VIOLETT), DrawStep(), SDL_Flip(screen); break; } case SDLK_y: { AddColor(COLOR_YELLOW), DrawStep(), SDL_Flip(screen); } } break; } 



What is missing is the output of the number of moves.

Text rendering



Standardly in the SDL is not implemented text support. And there are 2 options for how to proceed:

1) Do it yourself
2) Use the library SDL_ttf.h

The first method is obvious - the letter can also be drawn as an image and output the desired one, as with blocks. Blanks can be stored in different ways. Either each letter in a separate image, or create one large drawing and display a piece corresponding to the desired letter.


In this case, you will need SDL_SetColorKey, which will set the color selected on the surface to be pro-valued (in this picture - 255 0 255)

 SDL_SetColorKey(img, SDL_SRCCOLORKEY, SDL_MapRGB(img->format,255, 0, 255)); 


The color (255, 0, 255) will now be transparent on the img surface.

Which way to choose is up to you. In this example, I chose the second method as less laborious. But it is worth considering that this method is also slower.
It is also somewhat more convenient, allowing each time to set the text color without unnecessary trouble. All you need is a TTF format font.

First you need to do as with the SDL - initialize. This time no parameters will be required.

 TTF_Init(); 



The text output code is the following:

 void WriteText(int x, int y, char text[100], int sz, int r, int g, int b) { SDL_Color clr; //   . 4  — R, G, B  A, . clr.r = r; clr.g = g; //    clr.b = b; TTF_Font * fnt = TTF_OpenFont("courier.ttf", sz); //       sz SDL_Rect dest; dest.x = x; dest.y = y; SDL_Surface * TextSurface = TTF_RenderText_Blended(fnt, text, clr); //          SDL_BlitSurface(TextSurface, NULL, screen, &dest); SDL_FreeSurface(TextSurface); //      TTF_CloseFont(fnt); //   } 



Now we can consider the implementation of DrawStep

First, it uses the CleanImage () procedure, which will clean up the area with the specified dimensions for further text output there.

 void CleanImage(int x, int y, int w, int h) { SDL_Rect desc; desc.x = x; desc.y = y; desc.w = w; desc.h = h; SDL_FillRect(screen, &desc, 0); //    (  0) } void DrawStep() { CleanImage(430, 50, 150, 100); for (int i = 0; i < 100; i++) tmpch[i] = 0; if (FinishGame()) //       { CleanImage(430, 50, 150, 20); for (int i = 0; i < 100; i++) tmpch[i] = 0; if (step <= 25) //      25 sprintf(tmpch, "You win!"), WriteText(430, 50, tmpch, 20, 0, 255, 0); //  - (0, 255, 0) else sprintf(tmpch, "Not bad!"), WriteText(430, 50, tmpch, 20, 255, 255, 0); for (int i = 0; i < 100; i++) tmpch[i] = 0; sprintf(tmpch, "Result:%d", step); WriteText(430, 80, tmpch, 20, 255, 255, 0); step = 0; GenMap(); //   ,       DrawMap(); } else { sprintf(tmpch, "%d%s", step, "/25"); if (step <= 25) WriteText(430, 50, tmpch, 20, 0, 255, 0); //  ,      25 else WriteText(430, 50, tmpch, 20, 255, 0, 0); } } 



It is time to start the project and see what happened:



That's all, you can play a couple of tens, hundreds of times or add something.
Sources that contain small additions to the code, you can say here .

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


All Articles