XAML:
<UserControl x:Class="SimpleKinetics.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="500" Height="350">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas x:Name="Container">
<Button x:Name="ButtonAdd" Canvas.Top="10" Canvas.Left="8" ClickMode="Release" Content="New balls" Click="ButtonAdd_Click" />
<Rectangle x:Name="Controls" Canvas.Top="0" Canvas.Left="0" Width="75" Height="300">
</Rectangle>
</Canvas>
</Grid>
</UserControl>
code behind:
public partial class Page : UserControl
{
List<Vector> vectors = new List<Vector>();
const int RADIUS = 5;
Random rand = new Random();
public Page()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 30);
timer.Tick += new EventHandler(OnTick);
timer.Start();
}
private void OnTick(object sender, EventArgs e)
{
List<Vector> deads = new List<Vector>();
foreach (Vector vector in vectors)
{
vector.Transition();
if (vector.IsDead)
deads.Add(vector);
}
deads.ForEach(dead =>
{
vectors.Remove(dead);
Container.Children.Remove(dead.ellipse);
});
}
private void ButtonAdd_Click(object sender, RoutedEventArgs e)
{
for (int explosions = 0; explosions < rand.Next(10)+1; explosions++)
GenerateExplode();
}
private void GenerateExplode()
{
Point point = new Point(rand.Next((int)Width), rand.Next((int)Height));
for (int i = 0; i < 100; i++)
{
Ellipse ellipse = new Ellipse();
ellipse.Width = RADIUS;
ellipse.Height = RADIUS;
Vector vector = new Vector(rand.Next(360), (rand.Next(30) / 10D) + 0.5D, ellipse);
vectors.Add(vector);
// make it a random colour
ellipse.Fill = new SolidColorBrush(
Color.FromArgb(
255,
GetRandomColour(),
GetRandomColour(),
GetRandomColour()));
// add it to the interface
Container.Children.Add(ellipse);
// put it in a random location
vector.Point = point;
}
}
private byte GetRandomColour()
{
return (byte)rand.Next(byte.MaxValue);
}
private Point Offset(Point inpoint, double offset)
{
Point point = new Point(inpoint.X + offset, inpoint.Y + offset);
return point;
}
private static Point GetPoint(DependencyObject sobj)
{
Point point = new Point((double)sobj.GetValue(Canvas.LeftProperty), (double)sobj.GetValue(Canvas.TopProperty));
return point;
}
}
which depends on my Vector class:
internal class Vector
{
public double direction;
public double magnitude;
public Ellipse ellipse;
public Vector(double direction, double magnitude, Ellipse ellipse)
{
this.direction = direction;
this.magnitude = magnitude;
this.ellipse = ellipse;
}
public Point Point
{
get
{
Point point = new Point((double)ellipse.GetValue(Canvas.LeftProperty), (double)ellipse.GetValue(Canvas.TopProperty));
return point;
}
set
{
ellipse.SetValue(Canvas.LeftProperty, value.X);
ellipse.SetValue(Canvas.TopProperty, value.Y);
}
}
internal void Transition()
{
Point newPoint = CalculateNextPosition();
Point = newPoint;
double fade = ((magnitude * magnitude) / magnitude) / 800d;
ellipse.Fill.Opacity -= fade;
}
public bool IsDead
{
get
{
return !(ellipse.Fill.Opacity > 0);
}
}
private double DegreesToRadians(double angle)
{
return ((angle*Math.PI) / 180f);
}
private double RadiansToDegrees(double angle)
{
return ((angle*180) / Math.PI);
}
private Point CalculateNextPosition()
{
double vx = magnitude * Math.Cos(DegreesToRadians(direction));
double vy = magnitude * Math.Sin(DegreesToRadians(direction));
Point current = this.Point;
double x = current.X + vx;
double y = current.Y + vy;
CheckCollision(vx, vy, x, y);
Point newPoint = new Point(x, y);
return newPoint;
}
private void CheckCollision(double vx, double vy, double x, double y)
{
const int maxX = 500;
const int maxY = 500;
if (x < 0 x > maxX)
vx *= -1;
if (y < 0 y > maxY)
vy *= -1;
magnitude = Math.Sqrt((vx * vx) + (vy * vy));
direction = RadiansToDegrees(Math.Atan2(vy, vx));
}
}
No comments:
Post a Comment