(Monogame)更新方法导致极端滞后

时间:2018-01-11 10:27:38

标签: c# visual-studio game-physics monogame

我目前正在以单一游戏创建一个2d平台游戏。 我创造了一个块,当玩家击中时,开始消失。当它消失时,我在它周围画一个矩形。每一块相同类型的瓷砖(BrittleTile)也会开始消失,直到整个连接的BrittleTiles暴徒都消失了。

问题在于,对于每一个被摧毁的BrittleTile,我的游戏运行速度明显变慢,直到它在10个左右的BrittleTiles被摧毁后成为幻灯片。我不知道是什么原因引起了这种情况,我一直试图简化类的Update方法,但似乎没有任何帮助。

有什么可能导致这种情况的想法吗?

    class BrittleTile: Tile, IIncludeSound 
{
    public Rectangle DestroyedCheckRectangle;
    private BrittleTile brittle;
    private bool _isPlayed;
    private bool _hasBroken;
    private SoundEffect _sfxBreak;
    private SoundEffectInstance _sfxiBreak;
    private TimeSpan _breakTimer = new TimeSpan();
    public Rectangle BrokenViewRectangle { get; set; }
    private bool _isBreaking = false;
    public BrittleTile(Texture2D texture, Rectangle baseViewRectangle, Rectangle brokenViewRectangle):base(texture, baseViewRectangle, true )
    {
        this.BrokenViewRectangle = brokenViewRectangle;
        this.ViewRectangle = baseViewRectangle;
    }

    public void Update(GameTime gameTime, Hero hero, Entity[,] grid)
    {
        if (!this._hasBroken)
        {
            if (!this._isBreaking && !this._hasBroken && this.hasCollision)
                _checkCollision(hero, grid);
            if (this._isBreaking)
            {
                if (!this._isPlayed)
                    _sfxiBreak.Play();
                this._isPlayed = true;
                this._breakTimer += gameTime.ElapsedGameTime;
                if (this._breakTimer.TotalMilliseconds < 250)
                    this.GhostMode(gameTime);
                else
                {
                    this._isBreaking = false;
                    this.hasCollision = false;
                    this._breakTimer -= this._breakTimer;
                }
            }
            else
            {
                if (!this.hasCollision && this.DestroyedCheckRectangle.Width == 0)
                {
                    this.DestroyedCheckRectangle.X = this.DestinationRectangle.X - 10;
                    this.DestroyedCheckRectangle.Y = this.DestinationRectangle.Y - 10;
                    this.DestroyedCheckRectangle.Height = this.DestinationRectangle.Height + 20;
                    this.DestroyedCheckRectangle.Width = this.DestinationRectangle.Width + 20;
                    this._hasBroken = true;
                }
            }
        }
    }
    public override void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(this.Texture, this.DestinationRectangle, this.BrokenViewRectangle, Color.White);
        if (this.hasCollision)
            spriteBatch.Draw(this.Texture, this.DestinationRectangle, this.ViewRectangle, Color.White * this.GhostDraw * 0.9f);
        spriteBatch.Draw(this.Texture, DestroyedCheckRectangle, new Rectangle(1, 1, 1, 1), Color.Yellow);
        Console.WriteLine(this.DestroyedCheckRectangle.X + ", " + this.DestroyedCheckRectangle.Y + ", " + this.DestroyedCheckRectangle.Width + ", " + this.DestroyedCheckRectangle.Height);
    }
    private void _checkCollision(Hero hero, Entity[,] grid)
    {
        if (this.DestinationRectangle.Intersects(hero.AttackHitBox))
        {
            this._isBreaking = true;
        }
        foreach (Shuriken star in hero.Stars)
        {
            if (this.DestinationRectangle.Intersects(star.DestinationRectangle))
                this._isBreaking = true;
        }
        foreach (Entity entityObject in grid)
        {
            if (hasCollision && entityObject.GetType() == typeof(BrittleTile)){
                brittle = entityObject.DeepCopy() as BrittleTile;
                if (this.DestinationRectangle.Intersects(brittle.DestroyedCheckRectangle))
                    this._isBreaking = true;
            }
        }
    }
    override public void LoadSounds(ContentManager content)
    {
        this._sfxBreak = content.Load<SoundEffect>("SFX/brittleBreak");
        _sfxiBreak = _sfxBreak.CreateInstance();
        _sfxiBreak.Volume = 0.2f;
    }
}

1 个答案:

答案 0 :(得分:3)

首先,这一行:

if (!this._isBreaking && !this._hasBroken && this.hasCollision)

!this._hasBroken是多余的。

我的第一个警告标志是这一行:

brittle = entityObject.DeepCopy() as BrittleTile;

我假设DeepCopy()创建了该对象的新版本,并复制了它的所有属性,对吧?看到它的代码可能有助于确定它,但在这个假设上......

对于每一个瓷砖,你都会在你网格中的每个对象中循环,并且你将这个对象完全复制为一个BrittleTile,为什么?

我的第一个改变是修改该foreach以使其中包含此内容:

var brittle = entityObject as BrittleTile
if (brittle != null && hasCollision){
    if (this.DestinationRectangle.Intersects(brittle.DestroyedCheckRectangle))
        this._isBreaking = true;
    }
}

不确定这是减速的主要原因,但这肯定是个问题。如果您正在克隆一个物体,然后立即扔掉一个物体,那么您几乎肯定会做错事。如果您正在克隆某个对象而您根本没有编辑该副本的属性(并使用这些编辑),那么您肯定做错了什么。在使用这样的方法之前我要小心谨慎,除非你真的确定这是你想要的。