【问题标题】:How do I correctly use SDL_FreeSurface when dealing with a vector of surfaces处理曲面向量时如何正确使用 SDL_FreeSurface
【发布时间】:2009-11-13 14:53:36
【问题描述】:

我在 SDL 中为自己设置了一个小型射击游戏作为教程。我有一个弹丸结构

struct projectile
{
    SDL_Surface* surface;
    int x;
    int y;
};

然后我把它放入一个向量中。

vector<projectile> shot;
projectile one_shot;

当我按下空格键时,我会创建一个新的射弹并将其添加到向量中,然后在渲染时它们会被 blitted。

这工作正常,但我在看似随机的情况下收到“程序已停止工作”错误。

所以我想知道释放表面的正确方法是什么。

  • 之后我会释放它们吗?
  • 我是否会在每个单独的镜头退出屏幕时释放它?
  • 或者其他选择?

更新:

我发现当我退出时它崩溃的地方,当我开了几枪并且它们都退出了屏幕时。我尝试用“正确的复制方式”替换为seen in this example 将曲面添加到向量的代码,它的行为仍然相同。

这就是我释放表面的方式。

if(shot.at(i).y < 0 - shot.at(i).surface->h)
{
    SDL_FreeSurface(shot.at(i).surface);
    shot.erase(shot.begin() + i);
}

任何人都有一个想法或一些示例代码,我可以看看这个来解决这个问题。

【问题讨论】:

    标签: c++ memory vector sdl


    【解决方案1】:

    如果多个射弹使用相同的精灵(就像在几乎所有基于精灵的游戏中一样),最好使用包含游戏使用的所有图像的图像缓存并仅在那里进行内存管理。在开始时或按需填充并在退出时冲洗。然后射弹只需要向这个缓存请求一个指向“arrow.png”的指针,缓存会加载它(如果需要)并返回表面指针。

    这样的缓存可以是一个简单的 std::map,只有 get_surface(string) 和 flush() 之类的函数。

    编辑:这个想法的实现:

    class image_cache{
        map<string, SDL_Surface*> cache_;
        public:
        SDL_Surface* get_image(string file){
            map<string, SDL_Surface*>::iterator i = cache_.find(file);
            if(i == cache_.end()) {
                SDL_Surface* surf = SDL_LoadBMP(file.c_str());
                i = cache_.insert(i, make_pair(file, surf));
            }
            return i->second;
        } 
        void flush(){
            map<string, SDL_Surface*>::iterator i = cache_.begin();
            for(;i != cache_.end();++i)
                SDL_FreeSurface(i->second);
            cache_.clear();
        }
        ~image_cache() {flush();}
    };
    
    image_cache images;
    // you can also use specialized caches instead of a global one
    image_cache projectiles_images;
    
    int main()
    {
        ...
        SDL_Surface* surf = images.get_image("sprite.png");
        ...
    }
    

    【讨论】:

    • 我已经接受了这个解决方案,因为我稍后会在路上使用这样的东西。谢谢。
    【解决方案2】:

    你应该在摧毁射弹时释放表面。何时摧毁弹丸是游戏设计决定;可能是它最迟离开屏幕时,当然也可能是(如果)它击中目标时。

    【讨论】:

      【解决方案3】:

      您是否也在其他地方使用相同的表面?因为如果是这样,只要在其他地方使用,就无法释放它。

      如果您不这样做:构建/加载您的表面并在射弹的构造函数/析构函数中释放。即:

      struct projectile {
          SDL_Surface* surface;
      
          projectile() : surface(NULL) {
              surface = LoadImage(...);
          }
      
          ~projectile() {
              if(surface) {
                   SDL_FreeSurface(surface);
                   surface = NULL;
              }
          }
      
      };
      

      【讨论】:

      • 我认为这可能会引导我走向正确的方向。我正在处理代码,因为添加它不能 100% 工作(当我开第二枪时崩溃)
      猜你喜欢
      • 1970-01-01
      • 2023-04-03
      • 2016-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-25
      相关资源
      最近更新 更多