在处理曲面向量时,如何正确使用SDL_FreeSurface

时间:2009-11-13 14:53:36

标签: c++ memory vector sdl

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

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

我把它放到矢量中。

vector<projectile> shot;
projectile one_shot;

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

这样可以正常工作,但我看似随意的情况下“程序已停止工作”错误。

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

  • 之后我是否将它们全部释放?
  • 我退出屏幕时是否释放每张照片?
  • 或其他一些选择?

更新:

我已经找到了当我退出时崩溃的地方,当我开了几枪并且他们都退出了屏幕。我已经尝试用“{3}}的”正确复制方式“替换将表面添加到向量的代码,并且它仍然以相同的方式运行。

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

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

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

3 个答案:

答案 0 :(得分:2)

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

这样的缓存可以是一个简单的std :: map&lt; string,SDL ___ Surface *&gt;只使用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");
    ...
}

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

如果你不这样做:在弹丸的构造函数/析构函数中构建/加载曲面和释放。即:

struct projectile {
    SDL_Surface* surface;

    projectile() : surface(NULL) {
        surface = LoadImage(...);
    }

    ~projectile() {
        if(surface) {
             SDL_FreeSurface(surface);
             surface = NULL;
        }
    }

};