我在一个填充了矩形的大型列表中进行迭代,每个帧应该向下移动1个像素,但由于大量的矩形,我得到了巨大的fps掉落了我的代码:
for (var x = 0; x < Water3.Count(); x++ )
{
bool intersect = false;
Rectangle rect = Water3[x];
List<Rectangle> Water2 = new List<Rectangle>(Water3);
Water2.RemoveAt(x);
rect.Y++;
foreach (Rectangle check in Water2)
{
if (check.IntersectsWith(rect))
{
intersect = true;
break;
}
}
if (rect.Y >= 699 || intersect == true)
{
rect.Y--;
}
Water[x] = rect;
frameGraphics.FillRectangle(new SolidBrush(Color.Red), Water3[x]);
}
这是我现在的代码:
private void render()
{
int framesRendered = 0;
long startTime = Environment.TickCount;
Bitmap frame = new Bitmap(Game.CANVAS_WIDTH, Game.CANVAS_HEIGHT);
Graphics frameGraphics = Graphics.FromImage(frame);
#region Brushes
SolidBrush Black = new SolidBrush(Color.Black);
SolidBrush Red = new SolidBrush(Color.Red);
#endregion
while (true)
{
frameGraphics.FillRectangle(Black, 0, 0, Game.CANVAS_WIDTH, Game.CANVAS_HEIGHT);
List<Rectangle> Water3 = new List<Rectangle>(Water);
for (var x = 0; x < Water3.Count; x++)
{
Rectangle rect = Water3[x];
rect.Y++;
bool intersect = Water3.Where((t, i) => i != x).Any(check => check.IntersectsWith(rect));
if (rect.Y >= 699 || intersect)
rect.Y--;
Water[x] = rect;
frameGraphics.FillRectangle(Red, Water3[x]);
}
drawHandle.DrawImage(frame, 0, 0);
//benchmarking
framesRendered++;
if (Environment.TickCount >= startTime + 1000)
{
Console.WriteLine("Engine: " + framesRendered + " fps");
framesRendered = 0;
startTime = Environment.TickCount;
答案 0 :(得分:0)
您正在循环中反复复制列表:
List<Rectangle> Water2 = new List<Rectangle>(Water3);
这会给你一个巨大的n ^ 2性能。
答案 1 :(得分:0)
正如Yishai已经说过的那样,你在每个循环中创建了一个巨大的Water3列表。这是在每个周期中分配和释放大量内存,这会对性能产生巨大影响。这样可以更好地使用您已有的列表。
for (var x = 0; x < Water3.Count; x++)
{
bool intersect = false;
Rectangle rect = Water3[x];
rect.Y++;
for (var i = 0; i < Water3.Count; i++)
{
if (i == x)
continue;
Rectangle check = Water3[i];
if (check.IntersectsWith(rect))
{
intersect = true;
break;
}
}
if (rect.Y >= 699 || intersect)
rect.Y--;
Water[x] = rect;
// painting 1000 rects like this takes about 12msec
// frameGraphics.FillRectangle(Brushes.Red, rect);
}
// painting all 1000 rects at once will take only 3msec
frameGraphics.FillRectangles(Brushes.Red, Water.ToArray());
或者使用LINQ表达式:
for (var x = 0; x < Water3.Count; x++)
{
Rectangle rect = Water3[x];
rect.Y++;
bool intersect = Water3.Where((t, i) => i != x).Any(check => check.IntersectsWith(rect));
if (rect.Y >= 699 || intersect)
rect.Y--;
Water[x] = rect;
// painting 1000 rects like this takes about 12msec
// frameGraphics.FillRectangle(Brushes.Red, rect);
}
// painting all 1000 rects at once will take only 3msec
frameGraphics.FillRectangles(Brushes.Red, Water.ToArray());
关于内存泄漏的另一个评论。您不应该在循环中反复创建SolidBrush。而是在循环外创建画笔并将其放入using语句中,以便之后处理它。如果你需要一个典型的颜色 - 就像你:红色 - 那么不要创建自己的画笔,而是使用静态成员Brushes.Red。