C# XNA - 当图形被收集后,请释放它们。

14 浏览
0 Comments

C# XNA - 当图形被收集后,请释放它们。

我一直遇到同样的问题,当玩家从游戏中收集一个物体后,它被移除,但游戏仍然认为它仍在那里,并抛出以下错误:\n

\n未处理的异常类型 \'System.ComponentModel.Win32Exception\' 发生在 System.Drawing.dll 中\n附加信息:操作成功完成\n

\n我已经阅读了一些其他帖子,它们似乎在说你应该在收集图形后使用Dispose()来释放一些内存,但我不确定这是否是适合我的正确解决方案,也不知道如何做到这一点。\n上面的警告发生在我的Object类中(特别是突出显示public Obj(Vector2 pos)这一行),如下所示。\n

class Obj : Microsoft.Xna.Framework.Game
{
    public Vector2 position;
    public float rotation = 0.0f;
    public Texture2D spriteIndex;
    public string spriteName;
    public float speed = 0.0f;
    public float scale = 1.0f;
    public bool alive = true;
    public Rectangle area;
    public bool solid = false;
    public int score;
    public Obj(Vector2 pos)
    {
        position = pos;
    }
    private Obj()
    {
    }
    public virtual void Update()
    {
        if (!alive) return;
        UpdateArea();
        pushTo(speed, rotation);
    }
    public virtual void LoadContent(ContentManager content)
    {
        spriteIndex = content.Load("sprites\\" + spriteName);
        area = new Rectangle((int)position.X - (spriteIndex.Width / 2), (int)position.Y - (spriteIndex.Height / 2), spriteIndex.Width, spriteIndex.Height);
    }
    public virtual void Draw(SpriteBatch spriteBatch)
    {
        if (!alive) return;
        Rectangle Size;
        Vector2 center = new Vector2(spriteIndex.Width / 2, spriteIndex.Height / 2);
        spriteBatch.Draw(spriteIndex, position, null, Color.White, MathHelper.ToRadians(rotation), center, scale, SpriteEffects.None, 0);
    }
    public bool Collision(Vector2 pos, Obj obj)
    {
        Rectangle newArea = new Rectangle(area.X, area.Y, area.Width, area.Height);
        newArea.X += (int)pos.X;
        newArea.Y += (int)pos.Y;
        foreach (Obj o in Items.objList)
        {
            if (o.GetType() == obj.GetType() && o.solid)
                if (o.area.Intersects(newArea))
                    return true;
        }
        return false;
    }
    public Obj Collision(Obj obj)
    {
        foreach (Obj o in Items.objList)
        {
            if (o.GetType() == obj.GetType())
                if (o.area.Intersects(area))
                    return o;
        }
        return new Obj();
    }
    public void UpdateArea()
    {
        area.X = (int)position.X - (spriteIndex.Width / 2);
        area.Y = (int)position.Y - (spriteIndex.Height / 2);
    }
    public T CheckCollisionAgainst() where T : Obj
    {
        // 如果检测到碰撞,返回碰撞对象;否则返回null。
        return Items.objList
            .OfType()
            .FirstOrDefault(o => o.area.Intersects(area));
    }
    public virtual void pushTo(float pix, float dir)
    {
        float newX = (float)Math.Cos(MathHelper.ToRadians(dir));
        float newY = (float)Math.Sin(MathHelper.ToRadians(dir));
        position.X += pix * (float)newX;
        position.Y += pix * (float)newY;
    }
}

0
0 Comments

问题的原因是在C# XNA中,当收集了图形对象后,应该将其销毁,以释放内存空间。解决方法是在类的Dispose方法中添加代码来销毁对象。具体的解决方法是在类的Dispose方法中添加代码spriteIndex.Dispose()来销毁spriteIndex对象。另外,还需要将Dispose方法的访问修饰符修改为protected override。

代码实现如下:

protected override void Dispose(bool disposing)
{
    spriteIndex.Dispose();
    // any other object to dispose
    base.Dispose(disposing);
}

这段代码应该添加在Obj类中。如果在添加后出现错误提示"Microsoft.Xna.Framework.Vector2 does not contain a definition for Dispose and no extension method Dispose accepting first argument of type",可以尝试将代码修改为spriteIndex.Dispose()。

如果修改后仍然出现警告提示"public override void Dispose(bool disposing) cannot change access modifiers when overriding protected inherited member Microsoft.Xna.Framework.Game.Dispose(bool)",可以将Dispose方法的访问修饰符修改为protected override void Dispose(bool disposing)。

最后,需要注意的是,如果在public Obj(Vector2 pos)这一行出现了警告提示,可能是其他地方还有问题,需要进一步检查代码。

0