[ Foro de C# ]

como puedo optimizar este codigo para que valla mas rapido

11-Nov-2016 20:58
Invitado (mirr)
1 Respuestas

public partial class Form1 : Form
   {
       public Form1()
       {
           InitializeComponent();
       }
       
       private const int scale = 2;
       private World world = new World();
       private long frameCount = 0;
       private long frameTime = 0;

       private void Form1_Load(object sender, EventArgs e)
       {
           InitializeWorld();
           SetStyle(ControlStyles.OptimizedDoubleBuffer
               | ControlStyles.UserPaint
               | ControlStyles.AllPaintingInWmPaint,
               true);
       }
       private void InitializeWorld()
       {
           for (int i = 0; i < 5000; i++)
           {          
               Person entity = new Person();
               entity.Infected = i == 0;
               entity.Rotation = world.Random() * Math.PI * 2;
               entity.Position = world.RandomPoint();
               world.Add(entity);
           }
       }

       private void Form1_Paint(object sender, PaintEventArgs e)
       {
           e.Graphics.ScaleTransform(scale, scale);
           world.DrawOn(e.Graphics);
       }


       private void updateTimer_Tick(object sender, EventArgs e)
       {
           ClientSize = new Size(world.Width * scale, world.Height * scale);
           long begin = Environment.TickCount;
           world.Update();
           Refresh();
           long end = Environment.TickCount;
           RegisterFrameTime(end - begin);

           Text = string.Format("Objects: {0}, Average FPS: {1:00}, Current FPS: {2:00}",
               world.GameObjects.Count(),
               1000.0 / (frameTime / frameCount),
               1000.0 / (end - begin));  
       }

       private void RegisterFrameTime(long time)
       {
           frameTime += time;
           frameCount++;
       }

       private void lifeSpawner_Tick(object sender, EventArgs e)
       {
           IEnumerable<Person> persons = world.GameObjects.Cast<Person>();
           if (persons.All(p => p.Infected))
           {
               foreach (Person p in persons)
               {
                   p.Infected = false;
               }
               persons.First().Infected = true;
           }
       }}
}

abstract class GameObject
   {
       private Point position = new Point(0,0);
       private double rotation = 0;
       private Color color = Color.Black;
       private long lastUpdate = 0;

       public virtual long UpdateInterval { get { return 10; } }

       public Point Position
       {
           get { return position; }
           set { position = value; }
       }
       
       public double Rotation
       {
           get { return rotation; }
           set { rotation = value; }
       }

       public  Color Color
       {
           get { return color; }
           set { color = value; }
       }

       public Rectangle Bounds
       {
           get { return new Rectangle(Position, new Size(1, 1)); }
       }

       public void InternalUpdateOn(World world)
       {
           long now = Environment.TickCount;
           if (now - lastUpdate > UpdateInterval)
           {
               lastUpdate = now;
               UpdateOn(world);
           }

       }
       public virtual void UpdateOn(World world)
       {
           // Do nothing
           
       }

       public void Turn(int angle)
       {
           Rotation += Math.PI * angle / 180.0;
       }

       public void Forward(int dist)
       {
           //(direction degreeCos @ direction degreeSin) *distance + location
           Position = new Point((int)Math.Round(Math.Cos(rotation) * dist + Position.X),
                                (int)Math.Round(Math.Sin(rotation) * dist + Position.Y));
       }

       public void LookTo(Point p)
       {
           Rotation = Math.Atan2(p.Y - Position.Y, p.X - Position.X);
       }
   }
}

class Person : GameObject
   {
       public bool Infected { get; set; }

       public override void UpdateOn(World world)
       {
           IEnumerable<Person> near = world.ObjectsAt(Position).Cast<Person>();

           if (Infected)
           {
               Color = Color.Red;
               foreach (Person p in near)  
               {
                   p.Infected = true;
               }
               
           }
           else
           {
               Color = Color.Blue;
               if (near.Any(p => p.Infected))
               {
                   Infected = true;
               }
           }

           Forward(world.Random(1, 2));
           Turn(world.Random(-25, 25));
     }
   }
}

class World
   {
       private Random rnd = new Random();

       private const int width = 300;
       private const int height = 300;
       private Size size = new Size(width, height);
       private List<GameObject> objects = new List<GameObject>();

   public IEnumerable<GameObject> GameObjects {
           get
           {
               return objects.ToArray;
           }
       }

       public int Width { get { return width; } }
       public int Height { get { return height; } }

       public Point Center { get { return new Point(width / 2, height / 2); } }

       public bool IsInside(Point p)
       {
           return p.X >= 0 && p.X < width
               && p.Y >= 0 && p.Y < height;
       }

       public Point RandomPoint()
       {
           return new Point(rnd.Next(width), rnd.Next(height));
       }

       public float Random()
       {
           return (float)rnd.NextDouble();
       }

       public int Random(int min, int max)
       {
           return rnd.Next(min, max);
       }

       public void Add(GameObject obj)
       {
           objects.Add(obj);
        //   objects = objects.Concat(new GameObject[] { obj }).ToArray();
       }

       public void Remove(GameObject obj)
       {
            objects.Remove(obj);
          // objects = objects.Where(o => o != obj).ToArray();
       }

       public void Update()
       {
           foreach (GameObject obj in GameObjects)
           {
               obj.InternalUpdateOn(this);
               obj.Position = Mod(obj.Position, size);
           }
       }
       public void DrawOn(Graphics graphics)
       {
           graphics.FillRectangle(Brushes.Black, 0, 0, width, height);

           foreach (GameObject obj in GameObjects)
           {
               graphics.FillRectangle(new Pen(obj.Color).Brush, obj.Bounds);
           }
       }

       public double Dist(Point a, Point b)
       {
           return Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
       }

       public double Dist(int x1, int y1, int x2, int y2)
       {
           return Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2));
       }

       private static int Mod(int a, int n)
           int result = a % n;
           if ((a < 0 && n > 0) || (a > 0 && n < 0)) /
               result += n;
           return result;
       }
       private static Point Mod(Point p, Size s)
       {
           return new Point(Mod(p.X, s.Width), Mod(p.Y, s.Height));
       }

       public IEnumerable<GameObject> ObjectsAt(Point pos)
       {
           return GameObjects.Where(each => each.Position.Equals(pos));
       }    
   }
}


27-Nov-2016 11:34
Nacho Cabanes (+30)

Es un programa relativamente grande, y al ser parte de un programa de Windows Forms, no podremos probarlo. Por eso, mejor pregunta por zonas concretas del fuente, o bien usa el depurador de Visual Studio: en la versión 2015, incluso la Community, se te muestran tiempos de ejecución y consumos de memoria.






(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)