cocos2dx3.3开发FlappyBird总结四:资源管理类

本文介绍了一个用于游戏资源管理的全局共享类AtlasLoader,包括如何加载和获取精灵帧,以及实现细节和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

游戏中需要全局管理很多的资源,如图片、音频文件等。下面我们设计一个骨骼资源管理类,名叫:AtlasLoader,设计为全局共享类,用于载入资源和通过资源名称获取精灵帧。

下面先上头文件:


#ifndef __EngryBird__AtlasLoader__
#define __EngryBird__AtlasLoader__

#include "cocos2d.h"

/**
 * The struct of the atlas file
 */
typedef struct tag_atlas {
  char name[255];               // the image's name
  int width;                    // the image's width
  int height;                   // the image's height
  cocos2d::Vec2 startPosition;  // the image's start position
  cocos2d::Vec2 endPosition;    // the image's end position
} Atlas;

/**
 * The hepler class for loading the resources of atlas.png/atlas.txt
 *
 * @Note This is a global shared class, just call the getInstance class method
 * to get the object
 */
class AtlasLoader {
public:
  /**
   * Get the instance of AtlasLoader
   */
  static AtlasLoader* getInstance();

  /**
   * Destroy the instance of AtlasLoader,and will free all memory it takes
   */
  static void destroy();

  /**
   * Load with file name of an atlas and default load the atlas.png to texture
   *
   * @param filename the name of an atlas file
   *
   * @note This function load the images sync,so it will delay the main thread.
   * You can call like that: AtlasLoader::getInstance()->loadAtlas("filename");
   */
  void loadAtlas(std::string filename);

  /**
   * Load with file name of an atlas
   *
   * @param filename the name of an atlas file
   * @param texture the Texture2D object,using to create a sprite frame
   *
   * This function load the images sync,so it will delay the main thread.
   * You can call like that: AtlasLoader::getInstance()->loadAtlas("filename", texture);
   */
  void loadAtlas(std::string filename, cocos2d::Texture2D *texture);

  /**
   * Get the sprite frame with an image name
   *
   * @param imageName the name of image
   *
   * @return the sprite frame object related to an image
   */
  cocos2d::SpriteFrame* getSpriteFrame(std::string imageName);

protected:
  /**
   * The default constructor
   */
  AtlasLoader();

  /**
   * Initializes the instance of AtlasLoader
   *
   * @note When you are porting Cocos2d-x to a new platform, you may need to take care of
   * this method.
   *
   * @return true if succeeded, otherwise false
   */
  virtual bool init();

private:
  /**
   * The singleton pointer of AtlasLoader
   */
  static AtlasLoader* s_sharedAtlasLoader;

  /**
   * The container to store all the sprite frames that has already loaded
   */
  cocos2d::Map<std::string, cocos2d::SpriteFrame*> _spriteFrames;
};

#endif /* defined(__EngryBird__AtlasLoader__) */

声明了Atlas枚举,与atlas.txt文件中每一行结构是一一对应的。
骨骼文件中,会记录着精灵的图片名称、宽度、高度、起始位置和终止位置,这样就可以通过读取文件来获取精灵应该放置在哪里了。

此类为人全局共享的,因此必须通过下面的方法来创建或获取:

  /**
   * Get the instance of AtlasLoader
   */
  static AtlasLoader* getInstance();

我们在编码的时候,尽量与cocos2dx引擎的代码风格一致,这样更易于阅读。静态方法是类方法,不是某个对象的方法,这样就是共享的了。

接下来是实现文件。
关于怎么写单例,这里只说一遍,后面的文章中不会重复再说明,因为写法是一样的,只是名称变了而已。

// Initializes the shared object to be nullptr
AtlasLoader* AtlasLoader::s_sharedAtlasLoader = NULL;

AtlasLoader* AtlasLoader::getInstance() {
  if (s_sharedAtlasLoader == NULL) {
    s_sharedAtlasLoader = new AtlasLoader();

    if (!s_sharedAtlasLoader->init()) {
      delete s_sharedAtlasLoader;

      s_sharedAtlasLoader = NULL;
      CCLOG("Error: could not init s_sharedAtlasLoader object");
    }
  }

  return s_sharedAtlasLoader;
}

静态成员变量s_sharedAtlasLoader不能放在构造函数中初始化,所以需要在全局中初始化。
下面是getInstance方法的实现,这里通过判断全局共享变量是否为NULL,如果为NULL表示没有创建过,则创建之,否则不再创建,而是直接使用。这就是所谓的单例。当创建失败时,就把资源给释放掉了。

注意:这里是没有考虑线程安全的,在iOS中,我们写单例都会考虑到线程的安全问题。

下面说说加载资源最重要的方法:

void AtlasLoader::loadAtlas(std::string filename, cocos2d::Texture2D *texture) {
// 这里通过文件操作,读取文件,如atlas.txt文件
// FileUtils是一个文件操作辅助类,是引擎自带的类,获取的是字符串
  std::string data = FileUtils::getInstance()->getStringFromFile(filename);

  // 这里是通过分割读取行,一行一行的读取后(换行符是分割符),把对应的字段写入到Atlas结构中,然后获取精灵在骨骼中的区域,就可以获取到精灵帧了,并放到_spriteFrames中,这个是一个Map类型对象,可通过精灵的名称(key)来获取到精灵帧(value)
  size_t pos = data.find_first_of("\n");
  std::string line = data.substr(0, pos);
  data = data.substr(pos + 1);
  Atlas atlas;
  while (line.length() > 0) {
    sscanf(line.c_str(), "%s %d %d %f %f %f %f",
           atlas.name,
           &atlas.width,
           &atlas.height,
           &atlas.startPosition.x,
           &atlas.startPosition.y,
           &atlas.endPosition.x,
           &atlas.endPosition.y);

    atlas.startPosition.x *= 1024;
    atlas.startPosition.y *= 1024;
    atlas.endPosition.x *= 1024;
    atlas.endPosition.y *= 1024;

    // 读取下一行
    pos = data.find_first_of("\n");
    line = data.substr(0, pos);
    data = data.substr(pos + 1);

    // fix 1px edge bug
    if (atlas.name == std::string("land")) {
      ++atlas.startPosition.x;
    }


    // use the data to create a sprite frame
    Rect rect = Rect(atlas.startPosition.x, atlas.startPosition.y, atlas.width, atlas.height);
    auto spriteFrame = SpriteFrame::createWithTexture(texture, rect);
    _spriteFrames.insert(std::string(atlas.name), spriteFrame);
  }
}

好了,这个类已经说得很明白了吧,如果还有不明白的地方,可以联系我哦!!!!

下一步,说说这个屏幕适配的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值