概述
本文使用SDL作为图形库,实现了在一个界面上, 隔一会就出来一个方块,算是学习SDL图形库的入门, 为了方便, 使用了Qt IDE, 而不是在Linux上构建。对于新手来说,对各个函数的名称, 参数, 作用, 返回值都不熟悉, 借用IDE能显著降低入门难度, 就不要逞能直接在vim里写项目了。
项目实现
逻辑流程
重要控制原语
PS:鉴于其他的函数看名字就知道是啥玩意, 在这里就不赘述,只把不太明显的讲解一下, 大家自己手动敲一遍, 就什么都明白了。
SDL_SetRenderTarget
把一个纹理设置为渲染目标。接下来的所有对render的操作其实都是操作了纹理。
/**
* \brief Set a texture as the current rendering target.
*
* \param renderer The renderer.
* \param texture The targeted texture, which must be created with the SDL_TEXTUREACCESS_TARGET flag, or NULL for the default render target
*
* \return 0 on success, or -1 on error
*
* \sa SDL_GetRenderTarget()
*/
extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer,
SDL_Texture *texture);
SDL_SetRenderDrawColor
这里是以RGB的形式, 定义了一种颜色, 此颜色将被用来在render上画各种图形
/**
* \brief Set the color used for drawing operations (Rect, Line and Clear).
*
* \param renderer The renderer for which drawing color should be set.
* \param r The red value used to draw on the rendering target.
* \param g The green value used to draw on the rendering target.
* \param b The blue value used to draw on the rendering target.
* \param a The alpha value used to draw on the rendering target, usually
* ::SDL_ALPHA_OPAQUE (255).
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_SetRenderDrawColor(SDL_Renderer * renderer,
Uint8 r, Uint8 g, Uint8 b,
Uint8 a);
SDL_RenderClear
用预设的颜色, 清空render: 说是清空, 其实就是用上一步预设的颜色把整个render都糊上。 这里的clear有很强的迷惑性, 从源码看, 就是把renderer结构体里的r、g、b、a参数, 赋值到了一个SDL_RenderCommand 中相应的变量中,然后就是一系列的回调函数了, 再次要感叹一下SDL的团队了, 把C语言函数指针用的炉火纯青。
/**
* \brief Clear the current rendering target with the drawing color
*
* This function clears the entire rendering target, ignoring the viewport and
* the clip rectangle.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer * renderer);
SDL_RenderDrawRect
在render上画一个矩形, 大家有心里有数, 这里的render 究竟是真的render还是texture冒充的
/**
* \brief Draw a rectangle on the current rendering target.
*
* \param renderer The renderer which should draw a rectangle.
* \param rect A pointer to the destination rectangle, or NULL to outline the entire rendering target.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderDrawRect(SDL_Renderer * renderer,
const SDL_Rect * rect);
SDL_RenderFillRect
使用预设的颜色, 填充当前render上的一个矩形
/**
* \brief Fill a rectangle on the current rendering target with the drawing color.
*
* \param renderer The renderer which should fill a rectangle.
* \param rect A pointer to the destination rectangle, or NULL for the entire
* rendering target.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderFillRect(SDL_Renderer * renderer,
const SDL_Rect * rect);
SDL_RenderCopy
把texture上srcrect 的内容 拷贝到 renderer上的dstrect上, 如果srcrect/dstrect为null, 则代表整个。
/**
* \brief Copy a portion of the texture to the current rendering target.
*
* \param renderer The renderer which should copy parts of a texture.
* \param texture The source texture.
* \param srcrect A pointer to the source rectangle, or NULL for the entire
* texture.
* \param dstrect A pointer to the destination rectangle, or NULL for the
* entire rendering target.
*
* \return 0 on success, or -1 on error
*/
extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_Rect * dstrect);
代码实现
#include <iostream>
#include <SDL2/SDL.h>
#undef main
using namespace std;
int main()
{
SDL_Window *window = nullptr;
SDL_Renderer *render = nullptr;
SDL_Texture *texture = nullptr;
SDL_Rect rect;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("sdl window", 30, 30, 700, 400, SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
if (window == nullptr) {
SDL_Log("create window failed\n");
goto _EXIT;
}
render = SDL_CreateRenderer(window, -1, 0);
if (render == nullptr) {
SDL_Log("create render failed\n");
goto _FREE_WINDOW;
}
texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, 700, 400);
if (!texture) {
SDL_Log("create Texture failed\n");
goto _FREE_RENDER;
}
rect.w = 10;
rect.h = 10;
while (1) {
SDL_WaitEventTimeout(&event, 100);
SDL_Log("event type = %d", event.type);
if (event.type == SDL_QUIT) {
SDL_Log("it will quit\n");
break;
}
rect.x = rand() % 700;
rect.y = rand() % 400;
//Set a texture as the current rendering target.
SDL_SetRenderTarget(render, texture);
//Set the color used for drawing operations (Rect, Line and Clear)
SDL_SetRenderDrawColor(render, 255, 155, 55, 255);
//Clear the current rendering target with the drawing color
SDL_RenderClear(render);
//Draw a rectangle on the current rendering target
SDL_RenderDrawRect(render, &rect);
SDL_SetRenderDrawColor(render, 200, 50, 200, 150);
//Fill a rectangle on the current rendering target with the drawing color
SDL_RenderFillRect(render, &rect);
SDL_SetRenderTarget(render, nullptr);
//Copy a portion of the texture to the current rendering target.
SDL_RenderCopy(render, texture, nullptr, nullptr);
SDL_RenderPresent(render);
}
SDL_DestroyTexture(texture);
_FREE_RENDER:
SDL_DestroyRenderer(render);
_FREE_WINDOW:
SDL_DestroyWindow(window);
_EXIT:
SDL_Quit();
return 0;
}
因为结果是一个动态的, 本人也比较懒惰, 请大家自己运行, 看一下效果!