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__
====================
//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);
运行,查看效果