Spherical elastic and inelastic collisions in Silverlight
May 21, 2008 @ 2:51 pm in Microsoft, Silverlight
I recently took an interest in using some very basic physics within Silverlight 2. I took physics nearly 12 years ago and am certainly rusty, but thought it would be fun to simulate he effect two spheres have when they collide. Their are two types of collision; a perfectly elastic collision where there is no lose in kinetic energy and an inelastic collision where some or all of the kinetic energy is converted into internal energy. In the example below I try to demonstrate both types of collision along with a form of inelastic collision I call magnetic where upon collision energy is transferred in the direction of the collision and the sphere attaches itself to the object it is colliding with.
I am pretty certain I am taking some liberties with accuracy of each collision, but nonetheless one can see the effect two spheres have on momentum. Interestingly, if you allow the demo to run long enough most if not all of the balls will stop colliding. The first thing I needed to do to create my sample was to create a UserControl that would represent my sphere. Within this control I created a series of properties and two public Method: “Move()” and “Collision()”. Since each sphere will move through my container the same way, I can encapsulate this logic within the control itself. Here is that code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public void Move(Rect bounds)
{
//add the current vector to each X/Y
this.X += this.VX;
this.Y += this.VY;
//check to see if this sphere has collided with an adjacent wall
//if so, then reverse its vector. Since my bounding box is definable
//pass in a Rect struct
//check the left and the right of the bound box
if (this.X < bounds.X && this.VX < 0)
this.VX = -this.VX;
if(this.X > (bounds.Right-this.Distance) && this.VX > 0)
this.VX = -this.VX;
//check the top and the bottom
if (this.Y < bounds.Y && this.VY < 0)
this.VY = -this.VY;
if(this.Y > (bounds.Bottom-this.Distance) && this.VY > 0)
this.VY = -this.VY;
//move this sphere to its new X,Y position
_translate.X = this.X;
_translate.Y = this.Y;
} |
Since my container floats in the center of my Page.xaml I use a “Rect” struct to hold the X,Y, Width and Height of the UIElement that that will confine the spheres. I pass this “Rect” as an argument. Depending on the surface that the object is colliding with, I move the sphere and reverse the vector by either adding or subtracting itself from VX or VY. In addition to determining how itself moves, the sphere I also determines the effect of a collision. This method is pretty big, but is broken down into four sections. The first determines the time in which the two spheres collide where is the remaining determine the effect of each type of collision.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | public bool Collision(Sphere s)
{
// find the time when the two spheres really collide with each other.
double dx = (this.X + this._radius) - (s.X + s.Radius);
double dy = (this.Y + this._radius) - (s.Y + s.Radius);
//calculate the distance between two balls
double distance = dx * dx + dy * dy;
double distanceSqrt = Math.Sqrt(distance);
double dvx = this.VX - s.VX;
double dvy = this.VY - s.VY;
if (distanceSqrt > (this._radius + s.Radius))
return false;
//There are two basic kinds of collisions, elastic and inelastic:
//if an elastic collision occurs send both spheres rebounding backwards
//with no loss in total kinetic energy.
//Note: since both of our spheres have the same mass the only way to determine
//which type of collision will occur is to look at velocity.
double collision = 0.0;
if (this.CollisionType == CollisionTypes.Elastic ||
s.CollisionType == CollisionTypes.Elastic)
{
collision = dvx * dx + dvy * dy;
if (collision > 0)
return false;
collision /= distance;
double deltaVX = dx * collision;
double deltaVY = dy * collision;
//deflect this sphere
this._vx -= deltaVX;
this._vy -= deltaVY;
//deflect the sphere that was part of the collision
s.VX += deltaVX;
s.VY += deltaVY;
}
//if a partial inelastic collision occurs the spheres collide and some
//kinetic energy is lost...both masses decelerate
else if(this.CollisionType == CollisionTypes.Inelastic ||
s.CollisionType == CollisionTypes.Inelastic)
{
collision = dvx * dx + dvy * dy;
if (collision > 0)
return false;
collision /= distance*2;
double deltaVX = dx * collision;
double deltaVY = dy * collision;
//deflect this sphere
this._vx -= deltaVX;
this._vy -= deltaVY;
//deflect the sphere that was part of the collision
s.VX += deltaVX;
s.VY += deltaVY;
}
//if a magnetic collision occurs we would have a perfectly inelastic collision
else if (this.CollisionType == CollisionTypes.Magnetic &&
s.CollisionType == CollisionTypes.Magnetic)
{
//the sphere causing the collision will continue its forward momentum
//attaching itself to the adjacent sphere
s.VX = this.VX;
s.VY = this.VY;
}
return true;
} |
Code: SphericalCollision.zip
/p>
Tagged as 

May 22nd, 2008 at 6:05 am
[...] Spherical elastic and inelastic collisions in Silverlight - another animation from Joel Neubeck demonstrating both elastic and inelastic collisions. [...]