【c++|SDL】三、画图类抽象

every blog every motto: You can do more than you think.
https://blog.csdn.net/weixin_39190382?type=blog

0. 前言

画图类的抽象

1. 画图类抽象

之前将画图(显示图像)放在Game.cpp中,现在将其单独放在一个类中,

编译运行为:

g++ m14main.cpp Game.cpp TextureManager.cpp  -o m14 -lSDL2 -lSDL2_image
./m14

TextureManager.h
包含加载图片,显示图片,显示动画三个方法

#ifndef __TextureManager__
#define __TextureManager__

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <string>
#include <iostream>
#include <map>

using namespace std;

class TextureManager
{
    
    

public:
    TextureManager() {
    
    };
    ~TextureManager() {
    
    };

    bool load(std::string fileName,std::string id, SDL_Renderer* pRenderer);
    // draw
    void draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
    // drawframe
    void drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer* pRenderer,SDL_RendererFlip flip = SDL_FLIP_NONE);
    
    std::map<std::string, SDL_Texture*> m_textureMap;
    
// private:
//     bool m_bRunning;

};

#endif /* defined(__Game__) */

TextureManager.cpp

#include "TextureManager.h"

bool TextureManager::load(std::string fileName, std::string id, SDL_Renderer* pRenderer)
{
    
    
    SDL_Surface* pTempSurface = IMG_Load(fileName.c_str());
    if(pTempSurface == 0)
    {
    
    
        return false;
    }
    SDL_Texture* pTexture = SDL_CreateTextureFromSurface(pRenderer, pTempSurface);
    SDL_FreeSurface(pTempSurface);
    // everything went ok, add the texture to our list
    if(pTexture != 0)
    {
    
    
        m_textureMap[id] = pTexture;
        return true;
    }
    // reaching here means something went wrong
    return false;
}

void TextureManager::draw(std::string id,int x, int y, int width, int height,SDL_Renderer* pRenderer, SDL_RendererFlip flip)
{
    
    
    SDL_Rect srcRect;
    SDL_Rect destRect;
    srcRect.x = 0;
    srcRect.y = 0;
    srcRect.w = destRect.w = width;
    srcRect.h = destRect.h = height;
    destRect.x = x;
    destRect.y = y;
    SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect, &destRect, 0, 0, flip);
}

void TextureManager::drawFrame(std::string id, int x, int y, int width, int height,int currentRow, int currentFrame,SDL_Renderer *pRenderer, SDL_RendererFlip flip)
{
    
    
    SDL_Rect srcRect;
    SDL_Rect destRect;
    srcRect.x = width * currentFrame;
    srcRect.y = height * (currentRow - 1);
    srcRect.w = destRect.w = width;
    srcRect.h = destRect.h = height;
    destRect.x = x;
    destRect.y = y;
    SDL_RenderCopyEx(pRenderer,m_textureMap[id], &srcRect, &destRect, 0, 0, flip);
}

之前Game.cpp中的加载显示等相关操作需要删除,并进行修改

Game.h

#ifndef __Game__
#define __Game__

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// #include "TextureManager.h"
#include "TextureManager.h"
class Game
{
    
    

public:
    Game() {
    
    };
    ~Game() {
    
    };
    // simply set the running variable to true
    bool init(const char* title, int xpos, int ypos,int width, int height, bool fullscreen);
    void render();
    void update();
    void handleEvents();
    void clean();
    // a function to access the private running variable
    bool running() {
    
     return m_bRunning; }
private:
    bool m_bRunning;
    // SDL_Window* m_pWindow;
    // SDL_Renderer* m_pRenderer;

    SDL_Window* m_pWindow;
    SDL_Renderer* m_pRenderer;
    // SDL_Texture* m_pTexture; // the new SDL_Texture variable
    // SDL_Rect m_sourceRectangle; // the first rectangle
    // SDL_Rect m_destinationRectangle; // another rectangle

    int m_currentFrame;
    TextureManager m_textureManager;
};

#endif /* defined(__Game__) */

Game.cpp

#include "Game.h"
#include <iostream>

using namespace std;

bool Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{
    
       
    int flags = 0;
    if (fullscreen)
    {
    
    
        flags = SDL_WINDOW_FULLSCREEN;
    }
    // attempt to initialize SDL
    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
    
    
        std::cout << "SDL init success\n";
        // init the window
        m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
        if(m_pWindow != 0) // window init success
        {
    
    
            std::cout << "window creation success\n";
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
            if(m_pRenderer != 0) // renderer init success
            {
    
    
                std::cout << "renderer creation success\n";
                SDL_SetRenderDrawColor(m_pRenderer,255,0,0,255);
            }
            else
            {
    
    
                std::cout << "renderer init fail\n";
                return false; // renderer init fail
            }
        }
        else
        {
    
    
            std::cout << "window init fail\n";
            return false; // window init fail
        }
    }
    else
    {
    
    
        std::cout << "SDL init fail\n";
        return false; // SDL init fail
    }
    std::cout << "init success\n";

    // // SDL_Surface* pTempSurface = SDL_LoadBMP("assets/rider.bmp");
    // // SDL_Surface* pTempSurface = SDL_LoadBMP("assets/animate.bmp");
    // // SDL_Surface* pTempSurface = IMG_Load("assets/animate.png");
    // SDL_Surface* pTempSurface = IMG_Load("assets/animate-alpha.png");
    // m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer, pTempSurface);
    // SDL_FreeSurface(pTempSurface);

    // SDL_QueryTexture(m_pTexture, NULL, NULL,&m_sourceRectangle.w,&m_sourceRectangle.h); // 获取长宽

    // m_sourceRectangle.x = 0;
    // m_sourceRectangle.y = 0;
    // m_sourceRectangle.w = 128;
    // m_sourceRectangle.h = 82;

    // m_destinationRectangle.x = 0;
    // m_destinationRectangle.y = 0;

    
    // // m_destinationRectangle.x = m_sourceRectangle.x = 0;
    // // m_destinationRectangle.y = m_sourceRectangle.y = 0;
    // m_destinationRectangle.w = m_sourceRectangle.w;
    // m_destinationRectangle.h = m_sourceRectangle.h;

    m_textureManager.load("assets/animate-alpha.png", "animate", m_pRenderer);
    m_bRunning = true; // everything inited successfully, start the main loop
    return true;
}

void Game::render()
{
    
    
    // SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
    // // SDL_RenderCopy(m_pRenderer, m_pTexture,0,0);
    // // SDL_RenderCopy(m_pRenderer, m_pTexture,&m_sourceRectangle,&m_destinationRectangle);
    // SDL_RenderCopyEx(m_pRenderer, m_pTexture,&m_sourceRectangle, &m_destinationRectangle,0, 0, SDL_FLIP_HORIZONTAL); // pass in the horizontal flip
    // SDL_RenderPresent(m_pRenderer); // draw to the screen

    SDL_RenderClear(m_pRenderer);
    m_textureManager.draw("animate", 0,0, 128, 82,m_pRenderer);
    m_textureManager.drawFrame("animate", 100,100, 128, 82, 1, m_currentFrame, m_pRenderer);
    SDL_RenderPresent(m_pRenderer);
}


void Game::handleEvents()
{
    
    
    SDL_Event event;
    if(SDL_PollEvent(&event))
    {
    
    
        switch (event.type)
    {
    
    
        case SDL_QUIT:
            m_bRunning = false;
        break;

        default:
        break;
    }
    }
}

void Game::clean()
{
    
    
    std::cout << "cleaning game\n";
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    SDL_Quit();
}

void Game::update()
{
    
    
    // m_sourceRectangle.x = 128 * int(((SDL_GetTicks() / 100) % 6));
    m_currentFrame = int(((SDL_GetTicks() /100) % 6));

}

如下所示,其中右下角为动图

在这里插入图片描述

扫描二维码关注公众号,回复: 17278446 查看本文章

2. 单例模式

我们想在整个游戏中重用这个TextureManager,所以我们不想让它成为game类的成员,因为那样我们就必须把它传递给draw函数。对我们来说,一个很好的选择是将TextureManager实现为单例。单例是一个只能有一个实例的类

TextureManager.h

#ifndef __TextureManager__
#define __TextureManager__

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <string>
#include <iostream>
#include <map>

using namespace std;

class TextureManager
{
    
    

public:

    bool load(std::string fileName,std::string id, SDL_Renderer* pRenderer);
    // draw
    void draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
    // drawframe
    void drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer* pRenderer,SDL_RendererFlip flip = SDL_FLIP_NONE);
    
    std::map<std::string, SDL_Texture*> m_textureMap;
    
    static TextureManager* Instance()
    {
    
    
        if(s_pInstance == 0)
        {
    
    
            s_pInstance = new TextureManager();
            return s_pInstance;
        }
        return s_pInstance;
    }
private:
    TextureManager() {
    
    };
    ~TextureManager() {
    
    };
    static TextureManager* s_pInstance;
//     bool m_bRunning;

};

typedef TextureManager TheTextureManager;

#endif /* defined(__Game__) */

TextureManager.cpp 中添加如下代码

TextureManager* TextureManager::s_pInstance = 0;

Game.h注释掉如下代码

TextureManager m_textureManager;

Game.cpp中读取图片替换为:

// to load
if(!TheTextureManager::Instance()->load("assets/animate-alpha.png", "animate",m_pRenderer))
{
    
    
    return false;
}

显示图片替换为:

// to draw
TheTextureManager::Instance()->draw("animate",0,0, 128, 82, m_pRenderer);
TheTextureManager::Instance()->drawFrame("animate", 100,100, 128, 82, 1, m_currentFrame, m_pRenderer);

最终效果相同

猜你喜欢

转载自blog.csdn.net/weixin_39190382/article/details/134710725
今日推荐