SDL Game Development-第2章-5.实现纹理管理器Texture Manager


1.创建TextureManager.h
//首先是load()方法,用来根据文件名装载纹理
bool load(std::string fileName, std::string id, SDL_Renderer* pRenderer);
//三个参数:文件名,字串ID,渲染器指针

2.创建绘制draw()和绘制帧drawFrame()方法
//draw()方法,根据ID识别纹理,x,y是位置,w,h是高宽
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);    //默认为不翻转

   
3.使用标准容器map存储纹理指针
//使用std::map容器放置纹理,键key为std::string指向的ID
std::map<std::string, SDL_Texture*> m_textureMap;

====================完整的TextureManager.h内容:====================

#ifndef __TEXTURE_MANAGER__
    #define __TEXTURE_MANAGER__
#include <string>
#include <map>

#include <SDL.h>
#include <SDL_image.h>

class TextureManager
{
public:
    bool load(std::string fileName, std::string id, SDL_Renderer* pRenderer);
    void draw(std::string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);	//默认为不翻转
    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);  //参数中指定行和帧

private:
    std::map <std::string, SDL_Texture*> m_textureMap;

};
#endif // __TEXTURE_MANAGER__
====================


4.在TextureManager.cpp中实现
//TextureManager.cpp实现load()
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);
 //将新的纹理指针放入map中
 if(pTexture != 0)
 {
  m_textureMap[id] = pTexture;
  return true;
 }
 return false;    //运行到这里表示错误,处理错误
}


5.绘制整个图片的方法实现
//实现draw()
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);
}


6.单帧绘制方法的实现
//实现drawFrame()
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);
}


7.使用定义好的纹理管理类
1).在Game.h中,包含:
#include "TextureManager.h"

2).私有成员修改为:
    //SDL_Texture* m_pTexture;    //纹理指针
    //SDL_Rect m_srcRect; //纹理的矩形位置
    //SDL_Rect m_destRect;    //绘制到屏幕上的位置矩形
    int m_currentFrame;
    TextureManager m_textureManager;

3).Game.cpp的init()方法中,删除原有的图片装载和方框赋值,添加代码为:
//使用新的纹理管理类进行图片装载
m_textureManager.load("assets/animate-alpha.png", "animate", m_pRenderer);
//load()方法是bool值,可以在这里加入判断,失败直接返回
    std::cout << "init success\n";
    m_bRunning = true;  //所有初始都成功,可以开始主循环了
    return true;


4).渲染方法的修改:
    //绘制纹理对象,调用纹理管理类的draw方法
    //注意参数的使用
    m_textureManager.draw("animate", 0, 0, 128, 82, m_pRenderer);
    m_textureManager.drawFrame("animate", 100, 100, 128, 82, 1, m_currentFrame, m_pRenderer);


5).更新方法的修改:
    //直接计算Game类的私有成员:当前帧
    m_currentFrame = int(((SDL_GetTicks() / 100) % 6));


测试运行:


优势:将纹理的装载和绘制封装,以后只需要循环遍历纹理指针,即可实现图片在屏幕上的呈现。

最后,将TextureManager类定义为单例,在程序中保证只有一个实例在运行,实现重复性使用。

1).在TextureManager.h类定义中,将构造函数声明为私有

private:
    std::map <std::string, SDL_Texture*> m_textureMap;
    static TextureManager* s_pInstance;
    TextureManager() {} //将构造声明为私有


2).定义静态内联函数Instance()

public:

...

    static TextureManager* Instance()   //静态实例
    {
        if(s_pInstance == 0)
        {
            s_pInstance = new TextureManager();
            return s_pInstance;
        }
        return s_pInstance; //如果实例已存在,直接返回实例指针
    }



3).类型定义,提示实例

};

typedef TextureManager TheTextureManager;


4)..cpp中声明全局实例

#include "TextureManager.h"

TextureManager* TextureManager::s_pInstance = 0;



5).使用:

//Game.h中注释掉m_textureManager成员变量

//Game.cpp中修改调用的方法:init()中

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


//render()中

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



运行,查看效果
展开阅读全文

没有更多推荐了,返回首页