[笔记]音视频学习之SDL篇《七》用类封装SDL

简介: [笔记]音视频学习之SDL篇《七》用类封装SDL

前言

更好使用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;
  }
}

总结

demo地址

后续会继续进行封装作为个人使用库使用

相关文章
|
存储 编解码 Linux
FFmpeg+SDL播放器开发实践:解析、解码、渲染全流程详解
FFmpeg+SDL播放器开发实践:解析、解码、渲染全流程详解
[笔记]音视频学习之SDL篇《十四》简单的动画
[笔记]音视频学习之SDL篇《十四》简单的动画
[笔记]音视频学习之SDL篇《三》使用拓展库
[笔记]音视频学习之SDL篇《三》使用拓展库
|
6月前
|
Linux C语言 开发者
音视频-SDL的简单使用
音视频-SDL的简单使用
48 0
|
存储 Cloud Native Linux
音视频 SDL简介
音视频 SDL简介
|
设计模式
[笔记]设计模式实践_SDLGUI封装系列之开源库SDL2_gui编译
[笔记]设计模式实践_SDLGUI封装系列之开源库SDL2_gui编译
108 0
[笔记]音视频学习之SDL篇《四》事件驱动的编程
[笔记]音视频学习之SDL篇《四》事件驱动的编程
[笔记]音视频学习之SDL篇《九》 渲染yuv数据
[笔记]音视频学习之SDL篇《九》 渲染yuv数据
[笔记]音视频学习之SDL篇《八》计时器
[笔记]音视频学习之SDL篇《八》计时器