Let’s say I want to draw a circle that follows the user’s mouse around the viewport. I imagine I would have to draw and undraw the circle at every mouse motion. Drawing the circle using SDL functions is not the problem, but how exactly would I “undraw” the circle?
Specifically, if there is a complex drawing underneath the circle, I wouldn’t want that to be erased.
Games normally redraw everything each frame. As long as you use the Render API (or the new GPU API) it should normally be fast enough to do so. The docs for SDL_RenderPresent says “The backbuffer should be considered invalidated after each present; do not assume that previous contents will exist between frames.” so if you use that function you don’t really have a choice but to redraw everything each time.
I am using SDL_Render to draw a green crosshair which follows the user’s mouse over the viewport. When the user’s mouse is still, the crosshair is still, when the user’s mouse moves, the crosshair moves – just like the normal cursor.
I am checking for the mouse motion case within the event loop and only drawing the cross hair when the mouse is moved. Every time I poll a new event, I clear the viewport and re-draw all my entities, including the crosshair. Below is my attempt:
Do not draw to the default render target (which is invalidated every frame) but instead draw to a target texture. Then you can do your circle drawing in the old-school way: first draw the background, then draw the circle to follow the user’s mouse, etc.
No ‘undrawing’ is necessary (unless you want to offer the user an ‘undo’ feature, which would be more tricky). Every frame you blit the target texture to the screen, to satisfy the needs of the renderer, but otherwise you can forget about the requirement for periodic refreshing.
I should have been clearer in my question. I have a board game where pieces are captured. Those pieces have to disappear from the board once they are captured. I am using the Render API so I can draw textures to the viewport (the “pieces” that should be removed are the textures). If I have a bunch of other pieces on the board, I don’t want them to get removed by redrawing. Plus even if I do redraw, I don’t want there to be a sudden flash. Should I still stick to using the Render API or is there a way to do this with SDL_Surface?
You can use such optimized rendering for textures, but only if you create your own texture on which you will render the contents of the game frame. The contents of such a texture will not change without your knowledge, so you can repaint selected regions of it, only those that require repainting.
Such a texture is a simple back buffer, on which you first render what is needed, and then render this texture in the window. I use this technique myself, except that I have several back buffer textures, in different sizes, but I still render each frame from scratch. Multiple buffers allow me to render a game frame in low resolution (336x224, sharp pixel art), then scale it and apply various filters (ultimately shaders), and then use them to render a window decoration, a game frame in a given aspect ratio, and fill the remaining client space.
If you do not create your own back buffer texture, you can still repaint only selected regions of the window, but there is no guarantee that the contents of the window will always be available. Therefore, in such case, each game frame is rendered from scratch.
If you redraw everything that should be visible (including the background) and only call SDL_RenderPresentonce at the end then there shouldn’t be any “flash”.
I restructured my game loop to load everything onto the renderer’s backbuffer (that I want to be displayed for that frame), and only after that I call SDL_RenderPresent. It’s working now. I also figured how to implement a little-crosshair that follows the user’s cursor around on the board to guide them in placing pieces. Thank you guys for the the help !