The Seeker – Version 2.0
Dec
18
Written by:
12/18/2009 9:41 PM
Version 1.0 was ok for displaying some simple concepts in action, but it’s not very interesting.
See Version 2 live at this link:
http://www.adefwebserver.com/Richard/The%20SeekerSite/Default.html
Version 2.0 keeps some continuous action going by introducing Prey for the seekers to follow around. The Prey has a true graphic representation, a green circle created by choosing an Ellipse from the Asset panel, then drawing it with the shift key held down so it will be constrained to circular dimensions. The Seeker now watches its target after initially becoming aware of it through an event – which is generated when a new prey is created through a left mouse click.

Important Concepts:
- Holding a reference to a UserControl
- Calculating the position of a point a specified distance in a particular direction
- Chaining animations
- Finding the position of a UserControl
- Using timers and random number generators to do old school animation
Sequence of Events:
The program begins pretty much the same as Seeker 1 except there is no green rectangle. Now however, whenever the left mouse is clicked on the screen a new Prey is created. Each seeker becomes aware of the Prey through a SightingEvent. To keep the seekers from always moving in tandem, there is a 30% chance that the event will be ignored. As the prey wanders around, the seeker follows.
Holding a reference to a UserControl
The following code shows what the Seeker does when it catches a SightingEvent. Note that SightingEventArgs has been modified to pass a reference to the Prey that was “sighted” and if the Seeker decides to chase the Prey it saves the reference in _acquiredTarget:
public void HandleSightingEvent(object sender, SightingEventArgs e)
{
// 70% chance we'll respond to the sighting
if (_randValue.Next(100) > 30)
{
_acquiredTarget = e.SightedPrey;
Point sightingPosition = e.Position;
// Move partway towards the target before taking another look
MoveToWayPoint(sightingPosition);
}
}
Now, instead of just moving towards the target until interception or until it receives another event, it just moves a certain way towards the target.
private void MoveToWayPoint(Point targetPoint)
{
// Calculate a point the specified distance along the target vector
Point WayPoint = PlotWayPoint(targetPoint, _wayPointDistance);
// Move there in the specified number of seconds
MoveTo(WayPoint, new Duration(TimeSpan.FromSeconds(_secondsToWayPoint)));
}
Calculating the position of a point a specified distance in a particular direction
PlotWayPoint is much like the code you’ve already seen that plots the direction to the target. The additional code, shown below, determines a point
the specified distance along the vector to the target:
private Point PlotWayPoint(Point targetPoint, Double distanceOnVector)
{
…
Double portion = distanceOnVector / distance;
// ... the result is used to calculate the proportional distance along the x and y axes
Double xFragment = xDistance * portion;
Double yFragment = yDistance * portion;
// ... calculate the target point by adjusting my position towards the target by the proportionate amount
return new Point(myLeft + xFragment, myTop + yFragment);
}
Chaining Animations
At the end of every move, we want to take a new look at where the target is and move towards it again. Storyboard animations make this easy because you can specify an event to be called when each animation ends. To do that, we just add a single line at the end of the MoveTo method
private void MoveTo(Point destination, Duration duration)
{
…
// When the animation is done, call this handler to re acquire the target and
// start the next animation
sbMove.Completed+=new System.EventHandler(sbMove_Completed);
}
Finding the position of a UserControl
sbMove_Completed uses the stored reference to determine the target’s new position and move towards it again.
private void sbMove_Completed(object sender, System.EventArgs e)
{
// Reacquire the prey's position and move towards it
Double preyLeft = Convert.ToDouble(_acquiredTarget.GetValue(Canvas.LeftProperty));
Double preyTop = Convert.ToDouble(_acquiredTarget.GetValue(Canvas.TopProperty));
MoveToWayPoint(new Point(preyLeft, preyTop));
}
This Seeker is still pretty dumb, so he’ll just keep trying to move towards the target even when he’s right on top of it.
Using timers and random number generators to do old school animation
The Prey just moves randomly around the screen. See the code in Prey.xaml.cs for details. Mostly interesting because it makes you appreciate how much easier Silverlight makes animation.
The code is here:
http://www.adefwebserver.com/Richard/TheSeekerv2.zip