level 7
内个小谁
楼主
在使用IMAGE的时候,我们总会有如下问题:图片大小不一致,资源里序列图和单图的统一,如何方便获取图片,等等。对于这些问题,我使用了两层封装来解决
首先:创建一个Object类,该类仅有一个成员变量m_id,作为同类资源的唯一编号
class Object {
public:
Object(int id) : m_id(id) {}
virtual ~Object() = default;
inline int GetID() const { return m_id; }
private:
int m_id;
};
然后:创建Texture类,该类继承Object
class Texture : public Object {
Texture(int id, IMAGE& img) : Object(id), m_img(img) {}
public:
~Texture();
void Render(const Rect& position, const Rect& texCoord);
static Texture* Create(int id, const std::string& file);
private:
IMAGE m_img;
};
考虑到loadimage失败的可能,直接创建Texture并不合适,所以在Create内部先加载IMAGE,再根据结果决定是否创建Texture对象。
Rect可以理解为包含上下左右的方框,使用Render函数,position代表绘制左下和右上角坐标,texCoord的值在0~1之间,代表使用图片中的哪部分。
接下来就是在Texture的基础上在封装一层
class Sprite : public Object {
Sprite(int id, Texture *texture) : Object(id), m_texture(texture);
public:
~Sprite();
void Render(/*...*/);
private:
Texture* m_texture;
Rect m_texCoord;
Vec2D m_center;
}
利用m_texCoord,对图片上的多个动作进行分割,摆脱直接控制Texture,而m_center,这个属性其实非常有用,比如,我们有两个Sprite,一个站立,宽度较小,另一个是一个攻击动作,较宽。宽的Sprite因为有攻击特效,人物可能不是在正中心,那么就可以修改m_center,使其在人物的下方,最后在绘制的时候进行计算即可。
最后,我们可以写一个资源管理器,包含一系列的静态函数
class Resource {
public:
static Texture* RegisterTexture(int id, const std::string& filename);
static Texture* LoadTexture(int id);
static void RemoveTexture(int id);
static Sprite* RegisterSprite(int id, int textureID);
static Sprite* LoadSprite(int id);
static void RemoveSprite(int id);
private:
static std::unordered_map<int, Texture*> s_textures;
static std::unordered_map<int, Sprite*> s_sprites;
}
将Texture和Sprite的构造函数和析构函数全部设为私有,再将Resource设置为他们的友元类,后续使用的时候直接使用Resource就可以了例如:
enum {
TEXTURE_HERO,
SPRITE_HERO_IDLE_0,
SPRITE_HERO_IDLE_1,
SPRITE_HERO_IDLE_2,
SPRITE_HERO_IDLE_3,
SPRITE_HERO_WALK_0,
SPRITE_HERO_WALK_1,
SPRITE_HERO_WALK_2,
SPRITE_HERO_WALK_3,
SPRITE_HERO_WALK_4
};
Resource::RegisterTexture(TEXTURE_HERO, "hero.jpg");
Resource::RegisterSprite(SPRITE_HERO_IDLE_0, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_IDLE_1, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_IDLE_2, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_IDLE_3, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_0, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_1, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_2, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_3, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_4, TEXTURE_HERO);
2025年09月27日 15点09分
1
首先:创建一个Object类,该类仅有一个成员变量m_id,作为同类资源的唯一编号
class Object {
public:
Object(int id) : m_id(id) {}
virtual ~Object() = default;
inline int GetID() const { return m_id; }
private:
int m_id;
};
然后:创建Texture类,该类继承Object
class Texture : public Object {
Texture(int id, IMAGE& img) : Object(id), m_img(img) {}
public:
~Texture();
void Render(const Rect& position, const Rect& texCoord);
static Texture* Create(int id, const std::string& file);
private:
IMAGE m_img;
};
考虑到loadimage失败的可能,直接创建Texture并不合适,所以在Create内部先加载IMAGE,再根据结果决定是否创建Texture对象。
Rect可以理解为包含上下左右的方框,使用Render函数,position代表绘制左下和右上角坐标,texCoord的值在0~1之间,代表使用图片中的哪部分。
接下来就是在Texture的基础上在封装一层
class Sprite : public Object {
Sprite(int id, Texture *texture) : Object(id), m_texture(texture);
public:
~Sprite();
void Render(/*...*/);
private:
Texture* m_texture;
Rect m_texCoord;
Vec2D m_center;
}
利用m_texCoord,对图片上的多个动作进行分割,摆脱直接控制Texture,而m_center,这个属性其实非常有用,比如,我们有两个Sprite,一个站立,宽度较小,另一个是一个攻击动作,较宽。宽的Sprite因为有攻击特效,人物可能不是在正中心,那么就可以修改m_center,使其在人物的下方,最后在绘制的时候进行计算即可。
最后,我们可以写一个资源管理器,包含一系列的静态函数
class Resource {
public:
static Texture* RegisterTexture(int id, const std::string& filename);
static Texture* LoadTexture(int id);
static void RemoveTexture(int id);
static Sprite* RegisterSprite(int id, int textureID);
static Sprite* LoadSprite(int id);
static void RemoveSprite(int id);
private:
static std::unordered_map<int, Texture*> s_textures;
static std::unordered_map<int, Sprite*> s_sprites;
}
将Texture和Sprite的构造函数和析构函数全部设为私有,再将Resource设置为他们的友元类,后续使用的时候直接使用Resource就可以了例如:
enum {
TEXTURE_HERO,
SPRITE_HERO_IDLE_0,
SPRITE_HERO_IDLE_1,
SPRITE_HERO_IDLE_2,
SPRITE_HERO_IDLE_3,
SPRITE_HERO_WALK_0,
SPRITE_HERO_WALK_1,
SPRITE_HERO_WALK_2,
SPRITE_HERO_WALK_3,
SPRITE_HERO_WALK_4
};
Resource::RegisterTexture(TEXTURE_HERO, "hero.jpg");
Resource::RegisterSprite(SPRITE_HERO_IDLE_0, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_IDLE_1, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_IDLE_2, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_IDLE_3, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_0, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_1, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_2, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_3, TEXTURE_HERO);
Resource::RegisterSprite(SPRITE_HERO_WALK_4, TEXTURE_HERO);







