BugCamSmash Dissected part 3 – Give the Bugs Brains

This part of of the series explaining how BugCamSmash was made is truly the quiet before the storm.  The tipping point before the big finale.  In part 1, we created a bug we could smash with a rock.  In part 2, we gave the bug the ability to crawl towards a location specified by a mouse click (to be then smashed with a rock). In this part, we will cover giving the bugs their own will to move and making sure they are not too coordinated in their movements.

Giving the Bugs some direction

Now that the bugs can crawl to a point, its time to give them the power to decide when and where to move on their own.  I created another short Storyboard called destTimer to choose a new point to MoveTo after a random amount of time. The following code was added to the Bug class to handle the completed event of the new Storyboard:

void destTimer_Completed(object sender, EventArgs e)
{
    parent = Parent as FrameworkElement;
    destTimer.Stop();
    MoveTo(new Point(r.NextDouble() * parent.ActualWidth – this.ActualWidth, 
                     r.NextDouble() * parent.ActualHeight – this.ActualHeight));
    destTimer.Duration = TimeSpan.FromMilliseconds(r.Next(3000, (10000));
    destTimer.Begin();
}

The time between movement is defined by the Duration of destTimer which is randomly generated on load as well as every time the Storyaboard Completes. During that time a new Point is randomly chosen within the bounds of the LayoutRoot Canvas and the move is executed using the MoveTo method from before.

Randomizing the Bugs

Now that I had the bug moving on its on, I thought it was time to give it some friends. On the first run of the SizeChanged event of MainPage, I added a four more calls to the AddBug method. As expected, when the app was run, five bugs appeared randomly positioned on the stage.

Unexpectedly though, it was evident that they were all choosing the same location to move towards.  After the second point they merged to fill the same space and look as if they were a single bug with extra thick legs.  This was due to the fact that the Random class is only a “pseudo-random number generator”.

From the MSDN site on the Random class:

The random number generation starts from a seed value. If the same seed is used repeatedly, the same series of numbers is generated. One way to produce different sequences is to make the seed value time-dependent, thereby producing a different series with each new instance of Random. By default, the parameterless constructor of the Random class uses the system clock to generate its seed value, while its parameterized constructor can take an Int32 value based on the number of ticks in the current time. However, because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.

Because my goal was to keep this experiment simple, I went with hard-coding a few numbers as seed values and then passing those through the constructor of the Bug class.

One way to improve performance and avoid this problem is to create one Random object to generate many number over time.

For a truly random number you can use the something like the RNGCryptoServiceProvider class.

Hooking up the WebCam

With the bugs on the move (and ehading towards different locations) its time to bring in the WebCam. In MainPage.xaml, I added a new Grid to LayoutRoot called screenGrid and inside that Grid I added a Rectangle called screen. I removed the BugSmashDrag behavior and added an EventHandler to the MouseLeftButtonUp event of the Rock Canvas.

The following code requests from the user access to the WebCam and creates a CaptureSource object. The CaptureSource object is then used as the source for a VideoBrush which is painted as the Fill of the screen Rectangle.

private void Rock_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
   if (CaptureDeviceConfiguration.AllowedDeviceAccess ||
                             CaptureDeviceConfiguration.RequestDeviceAccess())
   {
      VideoCaptureDevice vcd = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
      if (vcd != null)
      {
         cs = new CaptureSource();
         cs.VideoCaptureDevice = vcd;
         cs.Start();

         VideoBrush videoBrush = new VideoBrush();
         videoBrush.Stretch = Stretch.Uniform;
         videoBrush.SetSource(cs);
         screen.Fill = videoBrush;
      }
   }
}

Bugs running around, WebCam in place, next its time bring in Mantis Boy!

The next part wi
ll cover the hit detection using image diff and multi-threads

This entry was posted in Client Technologies, Tutorials and tagged , , . Bookmark the permalink.