【问题标题】:C++ / SDL: vector / surface issuesC++/SDL:向量/表面问题
【发布时间】:2011-09-15 22:14:26
【问题描述】:

这是我遇到的最新问题。我有一个名为 Projectiles 的课程,它包含射弹的基本构成。它是坐标,以及它使用的图像。这是基本结构:

class Projectile
{
    private:
        void load();

    public:
        SDL_Surface *surface;
        SDL_Surface* returnSurface()
        {
            return surface;
        }

        Projectile( int );
        void coordinates( int, int );

        int type;
        int width, height;

        int positionX, positionY;

        bool alive;
};

Projectile::Projectile( int type )
{
    type = 1;
    alive = true;
    width  = 83;
    height = 46;
}

void Projectile::load()
{
    SDL_Surface* loadedImage = NULL;

    loadedImage = IMG_Load( "hero.png" );
    surface = SDL_DisplayFormat( loadedImage );

    SDL_FreeSurface( loadedImage );
}

void Projectile::coordinates( int x, int y )
{
    positionX = x;
    positionY = y;
}

现在,我也有我的英雄类,它将射弹对象保存在一个矢量中,如下所示:

矢量 射弹;

我在 hero 类中有一个方法,它可以制造一个新的射弹并将其推入这个向量,如下所示:

void Hero::newProjectile( int type )
{
    projectiles.push_back( Projectile( type ) );
    projectileCount++;
}

然后是在我的主循环结束时调用的 draw 方法,它执行以下操作:

void Hero::drawProjectileState( SDL_Surface* destination )
{   
    for( int i = 0; i < projectileCount; i++ )
    {
        SDL_Rect offset;
        offset.x = positionX;
        offset.y = positionY;
        SDL_BlitSurface( projectiles[i].returnSurface(), NULL, destination, &offset );
    }
}

从概念上讲,我认为这会很好。最初我的射弹类将所有射弹坐标保存在它自己的向量中,但是当我想删除它们时遇到了一个问题。由于它们都使用相同的表面资源,因此在屏幕上删除一个时会导致游戏崩溃。我认为这会解决问题(每个都有自己的表面资源),但我得到了

访问冲突读取位置0xccccccf8。

当它试图在以下位置绘制弹丸时:

SDL_BlitSurface( projectiles[i].returnSurface(), NULL, destination, &amp;offset );

我感觉我误解了表面引用的工作方式。为每个弹丸提供自己的表面以便我可以独立删除它们的最佳方法是什么?

编辑: 只是为了消除可能的混淆,我希望能够独立地释放表面。一旦一个弹丸死亡,但另一个弹丸仍在屏幕上,释放一个表面是最初导致崩溃的原因。

【问题讨论】:

  • 给他们每个人自己的表面?为什么不使用std::shared_ptr&lt;surface&gt;,它会在不再使用表面后自动删除它?或者在节目期间制作一个表面并让他们都使用这个?
  • 另外,你为什么用projectileCount而不是projectiles.size()
  • 这给了我一个有符号/无符号的不匹配。
  • @Mooing Duck 当它们共享同一个表面时我遇到的问题是,每次发射弹丸时,它仍然分配在内存中。我相信每次拍摄需要 12kb,所以一段时间后,它占用了大量内存。但是,我不知道共享表面。这会避免这个问题吗?
  • 我是否可以建议在你的类中有一个类型字段是一些继承魔法应该覆盖的东西。保存您稍后需要执行的开关(类型)内容。

标签: c++ sdl access-violation


【解决方案1】:
Projectile::Projectile( int type )
{
    type = 1;
    alive = true;
    width  = 83;
    height = 46;
}

void Hero::newProjectile( int type )
{
    projectiles.push_back( Projectile( type ) );
    projectileCount++;
}

在上面的代码中,您从未加载过表面。你甚至从未初始化surface,所以它指向空间,因此当你这样做时drawProjectileState 中的访问冲突:

SDL_BlitSurface( projectiles[i].returnSurface(), NULL, destination, &offset );

【讨论】:

  • 表面被加载并存储在 Projectile 类中。
  • @Headspin:在哪里?显示完成的代码。你展示了load 函数,但我没有看到你在任何地方调用它。
  • 我的印象是它被加载到了 projectile 类中并返回 projectiles[i].returnSurface() 对不起,我对这一切还是陌生
  • 防止此类错误的一种方法是始终初始化构造函数/初始化器列表中的所有变量,即使它们为NULL。
  • 这是否会破坏希望每个射弹拥有自己的表面资源的目的,以便我可以独立释放它们?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多