(Monogame)更新方法导致极度滞后
(Monogame) Update method causes extreme lag
我目前正在用单人游戏制作 2d 平台游戏。
我创建了一个块,当被玩家击中时,它开始消失。当它消失时,我在它周围画了一个矩形。每个相同类型的 Tile (BrittleTile) 也开始消失,直到整个连接的 BrittleTiles 生物消失。
问题是对于每个被销毁的 BrittleTile,我的游戏运行速度明显变慢,直到在 10 个左右的 BrittleTiles 被销毁后它变成幻灯片。我不知道是什么原因造成的,我一直在尝试简化 class 的更新方法,但似乎无济于事。
知道是什么原因造成的吗?
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;
}
}
首先,这一行:
if (!this._isBreaking && !this._hasBroken && this.hasCollision)
!this._hasBroken 是多余的。
我的第一个警告标志是这一行:
brittle = entityObject.DeepCopy() as BrittleTile;
我假设 DeepCopy() 创建了对象的新版本,并复制了它的所有属性,对吗?查看其中的代码可能有助于确定它,但基于该假设...
对于每个 Tile,您循环遍历网格中的每个对象,并且完全复制该对象作为 BrittleTile,为什么?
我的第一个更改是修改 foreach 以将其包含在其中:
var brittle = entityObject as BrittleTile
if (brittle != null && hasCollision){
if (this.DestinationRectangle.Intersects(brittle.DestroyedCheckRectangle))
this._isBreaking = true;
}
}
不确定这是速度变慢的主要原因,但这绝对是一个问题。如果您正在克隆一个对象然后立即丢弃一个对象,那么您几乎可以肯定做错了什么。如果您正在克隆一个对象而您根本没有编辑该副本的属性(并使用这些编辑),那么您肯定做错了什么。在使用这样的方法之前我会很小心,除非你真的确定那是你想要的。
我目前正在用单人游戏制作 2d 平台游戏。 我创建了一个块,当被玩家击中时,它开始消失。当它消失时,我在它周围画了一个矩形。每个相同类型的 Tile (BrittleTile) 也开始消失,直到整个连接的 BrittleTiles 生物消失。
问题是对于每个被销毁的 BrittleTile,我的游戏运行速度明显变慢,直到在 10 个左右的 BrittleTiles 被销毁后它变成幻灯片。我不知道是什么原因造成的,我一直在尝试简化 class 的更新方法,但似乎无济于事。
知道是什么原因造成的吗?
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;
}
}
首先,这一行:
if (!this._isBreaking && !this._hasBroken && this.hasCollision)
!this._hasBroken 是多余的。
我的第一个警告标志是这一行:
brittle = entityObject.DeepCopy() as BrittleTile;
我假设 DeepCopy() 创建了对象的新版本,并复制了它的所有属性,对吗?查看其中的代码可能有助于确定它,但基于该假设...
对于每个 Tile,您循环遍历网格中的每个对象,并且完全复制该对象作为 BrittleTile,为什么?
我的第一个更改是修改 foreach 以将其包含在其中:
var brittle = entityObject as BrittleTile
if (brittle != null && hasCollision){
if (this.DestinationRectangle.Intersects(brittle.DestroyedCheckRectangle))
this._isBreaking = true;
}
}
不确定这是速度变慢的主要原因,但这绝对是一个问题。如果您正在克隆一个对象然后立即丢弃一个对象,那么您几乎可以肯定做错了什么。如果您正在克隆一个对象而您根本没有编辑该副本的属性(并使用这些编辑),那么您肯定做错了什么。在使用这样的方法之前我会很小心,除非你真的确定那是你想要的。