2017-03-26 414 views
-2

我正在创建一个游戏作为一个学校项目,并认为这将是一个好主意,使用colormapping创建水平,但我使用的方法是由于某种原因缓慢。为什么我的C#嵌套for循环很慢?

 public List<Entity> LoadLevel(Level level) 
    { 
     List<Entity> ents = new List<Entity>(); 
     Color[] clrs = new Color[level.getColorMap.Height*level.getColorMap.Width]; 
     level.getColorMap.GetData(clrs); 
     for (int x = 0; x < level.getColorMap.Width; x++) 
     { 
      for (int y = 0; y < level.getColorMap.Height; y++) 
      { 
       if (clrs[x + y * level.getColorMap.Width] == new Color(0, 0, 0)) 
       { 
        ents.Add(new Terrain(new Vector2(x, y))); 
        ents.Last().Animation.setImageIndex(0); 
        ents.Last().Animation.Play(); 
       } 
       if (clrs[x + y * level.getColorMap.Width] == new Color(6, 6, 6)) 
       { 
        ents.Add(new Terrain(new Vector2(x, y))); 
        ents.Last().Animation.setImageIndex(6); 
        ents.Last().Animation.setSpeed(69); 
        ents.Last().Animation.Play(); 
       } 
       if (clrs[x + y * level.getColorMap.Width] == new Color(9, 9, 9)) 
       { 
        ents.Add(new Terrain(new Vector2(x, y))); 
        ents.Last().Animation.setImageIndex(9); 
        ents.Last().Animation.setSpeed(69); 
        ents.Last().Animation.Play(); 
       } 
      } 
     } 
     return ents; 


    } 

我在LoadContent()中调用这个函数,执行大约需要半分钟,为什么它很慢?

+0

这更适合[code review](http://codereview.stackexchange.com/) – Rob

+0

'level.getColorMap.Height'和'level.getColorMap.Width'有多大? – Unlocked

+0

他们都是2048大。 –

回答

0

我对编码风格有一些注释。很可能这不是你的问题的原因,但更快知道更早。一般来说,你应该避免做重复和不必要的工作。我甚至不会称之为优化,我会称之为规则。它应该是你总是编码的方式。

  • 如果level.getColorMap需要一段时间?即使你不需要这样做,你可以一遍又一遍地重复它。你通常不应该依赖这个事实,即财产很便宜。调用一次并记住它的结果。

  • ents.Last()相当快,但不是免费的。如果你不需要它,不要打电话给它。建立新的地形并记住它的指针。

  • 在每个循环中新的Color(0, 0, 0)是坏的。不要把循环提升视为理所当然。即使您实际需要三个颜色对象,您也很可能会构建1200万个颜色对象。

  • 你的代码也有很多的重复。一般来说,在复制和粘贴代码之前请三思。 DRY

  • 循环顺序不好。您从一行到另一行跳转破坏缓存局部性。你应该处理整行,然后转到下一个。

  • 当您只需添加时避免乘法运算。的改进

实施例:

public void AddTerrain(List<Entity> ents, int selector, int x, int y) 
{ 
    Terrain newT = new Terrain(new Vector2(x, y)); 
    ents.Add(newT); 
    var animation = newT.Animation; 
    animation.setImageIndex(selector); 
    if (selector > 0) 
    { 
     animation.setSpeed(69); 
    } 
    animation.Play(); 
} 



public List<Entity> LoadLevel(Level level) 
{ 
    List<Entity> ents = new List<Entity>(); 
    var colorMap = level.getColorMap; 
    int colorMapWidth = colorMap.Width; 
    int colorMapHeight = colorMap.Height; 
    Color[] clrs = new Color[colorMapWidth * colorMapHeight]; 
    Color[] colors = new Color[] { new Color(0, 0, 0), new Color(6, 6, 6), new Color(9, 9, 9) }; 
    colorMap.GetData(clrs); 

    int ci = 0; 
    for (int y = 0; y < colorMapHeight; y++) 
    { 
     for (int x = 0; x < colorMapWidth; x++) 
     { 
      Color c = clrs[ci++]; 
      for (int i = 0; i < colors.Length; ++i) 
      { 
       if (c == colors[i]) 
       { 
        AddTerrain(ents, c.R, x, y); 
        break; 
       } 
      } 
     } 
    } 

    return ents; 
} 
+0

非常好的建议。反转x和y循环可能是最大的变化。缓存是一件非常重要的事情。 – vyrp

0

(发布代表OP的)

这个问题实际上是在terrainobject的构造函数中,创建它的collider的函数显得非常不好优化,感谢您的帮助!