[ Foro de C# ]
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));
}
}
}
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.)