前言
更好使用SDL库 封装成类可以更好使用
封装过程 如别人教程 我稍作修改了 直接贴源码好了
主要封装
1.载入图片
2.载入字体
3.事件循环
…
实现
Window.h
#ifndef WINDOW_H #define WINDOW_H #include <string> #include <stdexcept> #include <memory> #include <SDL2/SDL.h> #include <functional> #include <vector> //What we think our window class should look like class Window { public: //Start SDL and TTF, create the window and renderer static void Init(std::string title); //Quit SDL and TTF static void Quit(); //Draw an SDL_Texture static void Draw(SDL_Texture* tex, SDL_Rect& dstRect, SDL_Rect* clip, float angle, int xPivot, int yPivot,SDL_RendererFlip flip); //Load an image static SDL_Texture* LoadImage(std::string file); //Render some text static SDL_Texture* RenderText(std::string strText, std::string file, SDL_Color color, int fontSize); static void HandleEvents(const std::function<void(SDL_Event&)>& cbFunction); //Clear window static void Clear(); //Present renderer static void Present(); //Get the window's box static SDL_Rect Box(); public: static std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> m_pWindow; static std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> m_pRenderer; static SDL_Rect m_pBox; static bool m_eventQuit; }; #endif
Window.cpp
#include <string> #include <stdexcept> #include <memory> #include <fstream> #include <iostream> #include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <SDL2/SDL_ttf.h> #include<algorithm> #include "window.h" //Initialize the unique_ptr's deleters here std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> Window::m_pWindow = std::unique_ptr<SDL_Window, void (*)(SDL_Window*)>(nullptr, SDL_DestroyWindow); std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> Window::m_pRenderer = std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)>(nullptr, SDL_DestroyRenderer); bool Window::m_eventQuit = false; //Other static members SDL_Rect Window::m_pBox; void Window::Init(std::string title = "Window") { //initialize all SDL subsystems if (SDL_Init(SDL_INIT_EVERYTHING) == -1) throw std::runtime_error("SDL Init Failed"); if (TTF_Init() == -1) throw std::runtime_error("TTF Init Failed"); //Setup our window size m_pBox.x = 0; m_pBox.y = 0; m_pBox.w = 640; m_pBox.h = 480; //Create our window m_pWindow.reset(SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_pBox.w, m_pBox.h, SDL_WINDOW_SHOWN)); //Make sure it created ok if (m_pWindow == nullptr) throw std::runtime_error("Failed to create window"); //Create the renderer m_pRenderer.reset(SDL_CreateRenderer(m_pWindow.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)); //Make sure it created ok if (m_pRenderer == nullptr) throw std::runtime_error("Failed to create renderer"); } void Window::Quit() { TTF_Quit(); SDL_Quit(); } void Window::Draw(SDL_Texture* tex, SDL_Rect& dstRect, SDL_Rect* clip = NULL, float angle = 0.0, int xPivot = 0, int yPivot = 0,SDL_RendererFlip flip = SDL_FLIP_NONE) { } SDL_Texture* Window::LoadImage(std::string file) { SDL_Surface* bmp = IMG_Load(file.c_str()); if (bmp == nullptr) { throw std::runtime_error("SDL_LoadBMP Error"); std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl; return nullptr; } //SDL_Texture来用硬件加速绘制图像 SDL_Texture* tex = SDL_CreateTextureFromSurface(m_pRenderer.get(), bmp); SDL_FreeSurface(bmp); if (tex == nullptr) { std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl; throw std::runtime_error("SDL_CreateTextureFromSurface Error"); return nullptr; } SDL_RenderClear(m_pRenderer.get()); //texture画上去 //第一个NULL是一个指向源矩形的指针,也就是说,从图像上裁剪下的一块矩形 //而另一个是指向目标矩形的指针。我们将NULL传入这两个参数, //是告诉SDL绘制整个源图像(第一个NULL),并把它画在屏幕上(0,0 )的位置,并拉伸这个图像让它填满整个窗口(第二个NULL) SDL_RenderCopy(m_pRenderer.get(), tex, NULL, NULL);// SDL_RenderPresent(m_pRenderer.get());// SDL_RenderPresent来更新屏幕的画面 return tex; } SDL_Texture* Window::RenderText(std::string message, std::string fontFile, SDL_Color color, int fontSize){ //Open the font TTF_Font* font = TTF_OpenFont(fontFile.c_str(), fontSize); if (font == nullptr) { printf("TTF_OpenFont error"); return nullptr; } //We need to first render to a surface as that's what TTF_RenderText returns, then //load that surface into a texture SDL_Surface* surf = TTF_RenderText_Blended(font, message.c_str(), color); if (surf == nullptr) { TTF_CloseFont(font); printf("TTF_RenderText error"); return nullptr; } SDL_Texture* texture = SDL_CreateTextureFromSurface(m_pRenderer.get(), surf); if (texture == nullptr) { printf("CreateTexture"); return nullptr; } //Clean up the surface and font SDL_FreeSurface(surf); TTF_CloseFont(font); SDL_Rect* clip = nullptr; SDL_Rect pos = { Window::Box().w / 2 - 150 / 2, Window::Box().h / 2 - 150 / 2, 150, 150 }; //The angle to draw at, so we can play with it int angle = 0; SDL_RenderCopy(m_pRenderer.get(), texture, clip, &pos); SDL_RenderPresent(m_pRenderer.get()); return texture; } void Window::HandleEvents(const std::function<void(SDL_Event&)> &cbFunction) { m_eventQuit = false; SDL_Event e; while (!m_eventQuit) { while (SDL_PollEvent(&e)) { cbFunction(e); } } } void Window::Clear(){ SDL_RenderClear(m_pRenderer.get()); } void Window::Present() { SDL_RenderPresent(m_pRenderer.get()); } SDL_Rect Window::Box() { //Update mBox to match the current window size SDL_GetWindowSize(m_pWindow.get(), &m_pBox.w, &m_pBox.h); return m_pBox; }
main.cpp
#include <string> #include <iostream> #include <SDL2/SDL.h> #include <SDL2/SDL_ttf.h> #include "Window.h" #include "res_path.h" #include "cleanup.h" int main() { //Show A Window //In main() //Load up an image and some text SDL_Texture* img, * msg; try { //Start our window Window::Init("Shiver's GUI"); Window::HandleEvents([](SDL_Event e) { switch (e.key.keysym.sym) { case SDLK_q: case SDLK_ESCAPE: Window::m_eventQuit = true; break; } if (e.key.keysym.sym == SDLK_a) { printf("keydown A \n"); Window::Clear(); std::string fontFile = "..\\..\\res\\06sdl_learn\\sample.ttf"; std::string text = "TTF Fonts too!"; SDL_Color color = { 255, 255, 255 }; Window::RenderText(text, fontFile, color, 25); } if (e.key.keysym.sym == SDLK_f) { printf("keydown F \n"); //Load the image std::string imgFile = "..\\..\\res\\01sdl_learn\\preview2.bmp"; Window::LoadImage(imgFile); } }); } catch (const std::runtime_error& e) { //Catch error and crash std::cout << e.what() << std::endl; Window::Quit(); return -1; } }
总结
后续会继续进行封装作为个人使用库使用