一个精灵图,由多个固定间隔的图标组成。利用精灵图的好处就是不必将图标逐个读入内存进行操作。我们可以将精灵图中需要的部分用一个个矩形截取下来,然后再输出到渲染器上。
环境:SDL2 + VC++2015
下面的代码将打开sprite.png,并对相应的操作做出响应。
上面就是一个精灵图,由多个固定间隔的图标组成。利用精灵图的好处就是不必将图标逐个读入内存进行操作。我们可以将精灵图中需要的部分用一个个矩形截取下来,然后再输出到渲染器上。 环境:SDL2 + VC++2015 下面的代码将打开sprite.png,并对相应的操作做出响应。 #include <stdexcept> #include <string> #include <iostream> #include "SDL.h" #include "SDL_image.h" //屏幕宽度 const int SCREEN_WIDTH = 500; const int SCREEN_HEIGHT = 500; //全局窗口和渲染器 SDL_Window *window = nullptr; SDL_Renderer *renderer = nullptr; //记录SDL错误 void logSDLError(std::ostream &os, const std::string &msg) { os << msg << " error: " << SDL_GetError() << std::endl; } //加载图像材质 SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren) { SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str()); if (texture == nullptr) logSDLError(std::cout, "LoadTexture"); return texture; } //根据坐标生成截取区域并复制输出到渲染器 void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, SDL_Rect *clip = nullptr) { //目标截面区域初始化,提供目标在渲染器的坐标 SDL_Rect dst; dst.x = x; dst.y = y; //源截面区域不为空,将其值赋给目标截面 if (clip != nullptr) { dst.w = clip->w; dst.h = clip->h; } //将截面输出到渲染器 SDL_RenderCopy(ren, tex, clip, &dst); } int main(int argc, char** argv) { //初始化SDL if (SDL_Init(SDL_INIT_EVERYTHING) == -1) { std::cout << SDL_GetError() << std::endl; return 1; } //创建窗口 window = SDL_CreateWindow("Lesson 5", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (window == nullptr) { std::cout << SDL_GetError() << std::endl; return 2; } //创建渲染器 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (renderer == nullptr) { std::cout << SDL_GetError() << std::endl; return 3; } //创建纹理 SDL_Texture *image = nullptr; try { image = loadTexture("sprite.png", renderer); } catch (const std::runtime_error &e) { std::cout << e.what() << std::endl; return 4; } //iW,iH 表示截面宽高 int iW = 100, iH = 100; //x,y 分别为截面在渲染器输出的坐标 int x = SCREEN_WIDTH / 2 - iW / 2; int y = SCREEN_HEIGHT / 2 - iH / 2; //为精灵图设置截面 SDL_Rect clips[4]; //初始化截面信息 for (int i = 0; i < 4; ++i) { clips[i].x = i / 2 * iW; clips[i].y = i % 2 * iH; clips[i].w = iW; clips[i].h = iH; } //表示将要输出的截面 int useClip = 0; SDL_Event e; bool quit = false; //主循环 while (!quit) { //事件轮询 while (SDL_PollEvent(&e)) { //按右上角的X退出 if (e.type == SDL_QUIT) quit = true; //点击鼠标随机输出截面 if (e.type == SDL_MOUSEBUTTONDOWN) useClip = rand() % 4; //使用数字键决定输出截面,分别有1,2,3,4 if (e.type == SDL_KEYDOWN) { switch (e.key.keysym.sym) { case SDLK_1: case SDLK_KP_1: useClip = 0; break; case SDLK_2: case SDLK_KP_2: useClip = 1; break; case SDLK_3: case SDLK_KP_3: useClip = 2; break; case SDLK_4: case SDLK_KP_4: useClip = 3; break; case SDLK_ESCAPE: quit = true; break; default: break; } } } //清空渲染器 SDL_RenderClear(renderer); //绘制材质 renderTexture(image, renderer, x, y, &clips[useClip]); //呈现渲染器 SDL_RenderPresent(renderer); } //释放资源 SDL_DestroyTexture(image); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。