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

发布于 2024-08-11 06:09:40 字数 736 浏览 7 评论 0原文

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

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

,我把它放入一个向量中。

vector<projectile> shot;
projectile one_shot;

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

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

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

  • 之后我要把它们全部释放吗?
  • 当每个镜头退出屏幕时,我是否可以释放它?
  • 或者还有其他选择?

更新:

我发现当我退出时,当我开了几枪并且它们都退出屏幕时,它崩溃了。我尝试用“正确的复制方式”替换将表面添加到向量的代码,如

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

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

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

I have setup a small shooter game as a tutorial for myself in SDL. I have a struct of a projectile

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

And I put that into a vector.

vector<projectile> shot;
projectile one_shot;

And when I press space I create a new projectile and add it to the vector and then they're blitted when they're rendered.

This works fine, but I'm in seemingly random cases getting a "program has stopped working" error.

So I'm wondering what is the proper way to free the surfaces.

  • Do I free them all afterwards?
  • Do I free each individual shot when it exits the screen?
  • Or some other choice?

UPDATE:

I have found where it crashes when I quit, when I have fired a few shots and they have all exited the screen. I have tried replacing the code that adds the surface to the vector with the "proper way to duplicate" as seen in this example, and it still behaves in the same way.

This is how I free the surface.

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

Anyone have an idea or some sample code I can look at to figure this out.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

自由范儿 2024-08-18 06:09:40

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

这样的缓存可以是一个简单的 std::map<字符串,SDL___Surface* >仅具有 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");
    ...
}

If several projectiles use the same sprite (as in almost all sprite-based games), it's probably better to use an image cache containing all the images used by your games and do memory management only there. Fill it at start or on demand and flush it when exiting. Then projectiles just need to ask to this cache a pointer to "arrow.png", the cache loads it (if needed) and returns the surface pointer.

Such cache can be a simple std::map< string, SDL___Surface* > with just functions like get_surface(string) and flush().

EDIT: an implementation of this idea:

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");
    ...
}
自在安然 2024-08-18 06:09:40

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

You should free the surface when you destroy the projectile. When you destroy the projectile is a game design decision; probably when it leaves the screen at the latest, but also of course when (if) it hits a target.

她说她爱他 2024-08-18 06:09:40

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

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

struct projectile {
    SDL_Surface* surface;

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

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

};

Do you use the same surface also elsewhere? Because if so, you cannot free it as long as it is used somewhere else.

In case you don't do that: Make the constructing/loading of your surface and the freeing in the constructor / destructor of projectile. I.e.:

struct projectile {
    SDL_Surface* surface;

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

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

};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文