英文版作者代码:https://github.com/Twinklebear/TwinklebearDev-Lessons
中文版翻译:http://adolfans.github.io/sdltutorialcn/blog/2013/01/28/lesson-2-dont-put-everything-in-main/
觉得中文版翻译讲得有些繁琐,就按照自己的理解,整理如下:
main.cpp文件中:
#include <SDL.h> #include <string> #include <iostream> #include "cleanup.h" //屏幕的宽高常量 const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; 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 = nullptr; SDL_Surface *loadedImage = SDL_LoadBMP(file.c_str()); if (loadedImage != nullptr) { texture = SDL_CreateTextureFromSurface(ren, loadedImage); SDL_FreeSurface(loadedImage); if (texture == nullptr) { logSDLError(std::cout, "CreateTextureFromSurface"); } } else { logSDLError(std::cout, "LoadBMP"); } return texture; } void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y) { SDL_Rect dst; dst.x = x; dst.y = y; SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); SDL_RenderCopy(ren, tex, NULL, &dst); } int main(int argc, char *args[]) { if (SDL_Init(SDL_INIT_VIDEO) != 0) { logSDLError(std::cout, "SDL_Init"); return 1; } SDL_Window *window = SDL_CreateWindow("Lesson 2", 100, 100, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (window == nullptr) { logSDLError(std::cout, "CreateWindow"); SDL_Quit(); return 1; } SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (renderer == nullptr) { logSDLError(std::cout, "CreateRenderer"); cleanup(window); SDL_Quit(); return 1; } //The textures we'll be using SDL_Texture *background = loadTexture("background.bmp", renderer); SDL_Texture *image = loadTexture("image.bmp", renderer); if (background == nullptr || image == nullptr) { cleanup(background, image, renderer, window); SDL_Quit(); return 1; } for (int i = 0; i < 3; ++i) { SDL_RenderClear(renderer); int bW, bH; SDL_QueryTexture(background, NULL, NULL, &bW, &bH); renderTexture(background, renderer, 0, 0); renderTexture(background, renderer, bW, 0); renderTexture(background, renderer, 0, bH); renderTexture(background, renderer, bW, bH); int iW, iH; SDL_QueryTexture(image, NULL, NULL, &iW, &iH); int x = SCREEN_WIDTH / 2 - iW / 2; int y = SCREEN_HEIGHT / 2 - iH / 2; renderTexture(image, renderer, x, y); SDL_RenderPresent(renderer); SDL_Delay(1000); } cleanup(background, image, renderer, window); SDL_Quit(); return 0; }
clearn.h文件中:
#ifndef CLEANUP_H #define CLEANUP_H #include <utility> #include <SDL.h> /* * Recurse through the list of arguments to clean up, cleaning up * the first one in the list each iteration. */ template<typename T, typename... Args> void cleanup(T *t, Args&&... args){ //Cleanup the first item in the list cleanup(t); //Clean up the remaining arguments cleanup(std::forward<Args>(args)...); } /* * These specializations serve to free the passed argument and also provide the * base cases for the recursive call above, eg. when args is only a single * item one of the specializations below will be called by * cleanup(std::forward<Args>(args)...), ending the recursion */ template<> inline void cleanup<SDL_Window>(SDL_Window *win){ if (!win){ return; } SDL_DestroyWindow(win); } template<> inline void cleanup<SDL_Renderer>(SDL_Renderer *ren){ if (!ren){ return; } SDL_DestroyRenderer(ren); } template<> inline void cleanup<SDL_Texture>(SDL_Texture *tex){ if (!tex){ return; } SDL_DestroyTexture(tex); } template<> inline void cleanup<SDL_Surface>(SDL_Surface *surf){ if (!surf){ return; } SDL_FreeSurface(surf); } #endif
运行结果:
背景是4张小图片平铺而成,看for循环中就可以看到。