Questo è quello che ho scritto, come vedi ho scritto anche delle classi Vector, Point, Bound, tutte cose che in NetFramework da qualche parte ci sono. Questo perchè ho scritto lo stesso codice in Objective-C e volevo fare un confronto.
namespace Spheres
{
public class Scene
{
public List<Sphere> Spheres { get; set; }
public Bounds Bounds { get; set; }
public Scene()
{
Spheres = new List<Sphere>();
Bounds = new Bounds(0, 0, 800, 600);
}
public void Move(double elapsedSec)
{
foreach (Sphere sphere in Spheres)
{
sphere.Move(elapsedSec);
sphere.CheckBounds(Bounds);
sphere.Flag = false;
}
foreach (Sphere sphere in Spheres)
{
if (!sphere.Flag)
sphere.CheckCollision(this);
}
}
}
public class Point
{
public double X { get; set; }
public double Y { get; set; }
public Point(double x, double y)
{
X = x;
Y = y;
}
public double Distance(Point p)
{
double a = X - p.X;
double b = Y - p.Y;
return Math.Sqrt(a * a + b * b);
}
}
public class Vector
{
public double X { get; set; }
public double Y { get; set; }
public Vector(double x, double y)
{
X = x;
Y = y;
}
public Vector(Point p1, Point p2)
{
X = p2.X - p1.X;
Y = p2.Y - p1.Y;
}
public static Vector Add(Vector a, Vector b)
{
return new Vector(a.X + b.X, a.Y + b.Y);
}
public double DotProduct(Vector v) // Prodotto scalare
{
return X * v.X + Y * v.Y;
}
public double Magnitude // Norma
{
get { return Math.Sqrt(X * X + Y * Y); }
}
public Vector Multiply(double d) // moltiplicazione per uno scalare
{
return new Vector(X * d, Y * d);
}
public Vector Normalize
{
get { return Multiply(1 / Magnitude); }
}
public Vector Ortogonal
{
get { return new Vector(-Y, X); }
}
public Vector Project(Vector v)
{
Vector vn = v.Normalize;
return vn.Multiply(DotProduct(vn));
}
}
public class Bounds
{
public double Left { get; set; }
public double Bottom { get; set; }
public double Right { get; set; }
public double Top { get; set; }
public Bounds(double left, double bottom, double right, double top)
{
Left = left;
Bottom = bottom;
Right = right;
Top = top;
}
}
public class Sphere
{
public Point Center { get; set; }
public Vector Velocity { get; set; }
public double Radius { get; set; }
public bool Flag { get; set; }
public double Density { get; set; }
public Sphere()
{
Center = new Point(0, 0);
Velocity = new Vector(0, 0);
Radius = 1;
Density = 1;
}
public bool Collision(Sphere other)
{
double distanceOfCenters = Center.Distance(other.Center);
return distanceOfCenters <= Radius + other.Radius;
}
public void CheckCollision(Scene scene)
{
foreach (Sphere sphere in scene.Spheres)
{
if ((sphere != this) && Collision(sphere))
{
Vector centers = new Vector(this.Center, sphere.Center).Normalize;
double c1 = Velocity.DotProduct(centers);
double c2 = sphere.Velocity.DotProduct(centers);
if (c2 > c1)
continue;
double w1;
double w2;
ElasticCollision(c1, c2, Mass, sphere.Mass, out w1, out w2);
Vector ortho1 = Velocity.Project(centers.Ortogonal);
Velocity = Vector.Add(centers.Multiply(w1), ortho1);
Vector ortho2 = sphere.Velocity.Project(centers.Ortogonal);
sphere.Velocity = Vector.Add(centers.Multiply(w2), ortho2);
Flag = true;
sphere.Flag = true;
}
}
}
public double Mass
{
get { return Volume * Density; }
}
public void Move(double elapsedTime)
{
Center.X += Velocity.X * elapsedTime;
Center.Y += Velocity.Y * elapsedTime;
}
private void ElasticCollision(double velocity1, double velocity2, double mass1,
double mass2, out double outVelocity1, out double outVelocity2)
{
outVelocity1 = (velocity1 * (mass1 - mass2) + 2 * mass2 * velocity2) /
(mass1 + mass2);
outVelocity2 = (velocity2 * (mass2 - mass1) + 2 * mass1 * velocity1) /
(mass2 + mass1);
}
public void CheckBounds(Bounds bounds)
{
if (Right > bounds.Right)
{
Center.X = bounds.Right - Radius;
Velocity.X = -Math.Abs(Velocity.X);
}
if (Top > bounds.Top)
{
Center.Y = bounds.Top - Radius;
Velocity.Y = -Math.Abs(Velocity.Y);
}
if (Left < bounds.Left)
{
Center.X = bounds.Left + Radius;
Velocity.X = Math.Abs(Velocity.X);
}
if (Bottom < bounds.Bottom)
{
Center.Y = bounds.Bottom + Radius;
Velocity.Y = Math.Abs(Velocity.Y);
}
}
public double Bottom { get { return Center.Y - Radius; } }
public double Left { get { return Center.X - Radius; } }
public double Right { get { return Center.X + Radius; } }
public double Top { get { return Center.Y + Radius; } }
public double Volume
{
get { return (4.0 * Math.PI * Radius * Radius * Radius) / 3.0; }
}
}
}