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));
}
如下所示,其中右下角为动图
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);
最终效果相同