<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SHAZAML! &#187; ControlStoryboardAction</title>
	<atom:link href="http://www.shazaml.com/archives/tag/controlstoryboardaction/feed" rel="self" type="application/rss+xml" />
	<link>http://www.shazaml.com</link>
	<description>The Blog for Design &#38; Development Superheroes</description>
	<lastBuildDate>Wed, 28 Jul 2010 21:02:54 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Hidden Object: Episode 14 – Shake it up</title>
		<link>http://www.shazaml.com/archives/hidden-object-episode-14</link>
		<comments>http://www.shazaml.com/archives/hidden-object-episode-14#comments</comments>
		<pubDate>Wed, 25 Nov 2009 13:05:17 +0000</pubDate>
		<dc:creator>Mark Tucker</dc:creator>
				<category><![CDATA[Hidden Object Game]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[Blend]]></category>
		<category><![CDATA[ControlStoryboardAction]]></category>
		<category><![CDATA[EventTrigger]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[GlobalCounterMaxReachedTrigger]]></category>
		<category><![CDATA[IncrementGlobalCounterAction]]></category>
		<category><![CDATA[SetGlobalCounterAction]]></category>
		<category><![CDATA[Storyboard]]></category>
		<category><![CDATA[TimerTrigger]]></category>
		<category><![CDATA[Trigger]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=385</guid>
		<description><![CDATA[If the player clicks too many times within a 5 second time frame trying to find an item, play the shake animation.]]></description>
			<content:encoded><![CDATA[<p>So far in the game, we have particles when an item is clicked, a hint to show the location of an unfound item, but what should we do if the player goes berserk and wildly clicks all over the place in hopes of finding a difficult-to-find item? In this episode of <a href="http://www.shazaml.com/archives/creating-a-hidden-object-game-in-silverlight-3">Creating a Hidden Object Game is Silverlight 3</a> we will add an earthquake effect if the player clicks too many times in a 5 second interval.</p>
<p>Let&#8217;s first start with the shake effect.  The magnifierCanvas Canvas contains the background image and all Paths for each clickable item. We will create a new storyboard called ShakeStoryboard that will animate the Left property of the Canvas:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec1.png" alt="" /></p>
<p> </p>
<p>Each of the 4 key frames set the Left property to a different value as shown in the storyboard XAML:</p>
<pre class="brush: xml; gutter: false;">
&lt;Storyboard x:Name=&quot;ShakeStoryboard&quot; RepeatBehavior=&quot;5x&quot; AutoReverse=&quot;False&quot; SpeedRatio=&quot;5&quot;&gt;
    &lt;DoubleAnimationUsingKeyFrames BeginTime=&quot;00:00:00&quot;
        Storyboard.TargetName=&quot;magnifierCanvas&quot;
        Storyboard.TargetProperty=&quot;(Canvas.Left)&quot;&gt;
            &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00&quot; Value=&quot;0&quot;/&gt;
            &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00.2000000&quot; Value=&quot;-10&quot;/&gt;
            &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00.4000000&quot; Value=&quot;10&quot;/&gt;
            &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00.6000000&quot; Value=&quot;0&quot;/&gt;
    &lt;/DoubleAnimationUsingKeyFrames&gt;
&lt;/Storyboard&gt;
</pre>
<p> </p>
<p>The Storyboard has the RepeatBehavior property set to repeat 5 times and the SpeedRatio property set to speed up the animation.</p>
<p>If the player clicks on the background image 10 times within a 5 second interval, then the ShakeStoryboard will play. To accomplish this we need three SetGlobalCounterAction instances and one ControlStoryboardAction added to the UserControl:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec2.png" alt="" /></p>
<p>The first SetGlobalCounterAction sets the values for the TooManyClicks counter when the UserControl loads:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec3.png" alt="" /></p>
<p> </p>
<p>The ControlStoryboardAction plays the ShakeStoryboard when the GlobalCounterMaxReachedTrigger is fired for the TooManyClicks key which we set previously to 10.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec4.png" alt="" /></p>
<p>When the counter reaches 10 we need to set it back to zero which is what the second SetGlobalCounterAction does:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec5.png" alt="" /></p>
<p>The final SetGlobalCounterAction uses the TimerTrigger to reset the counter every 5 seconds:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec6.png" alt="" /></p>
<p> </p>
<p>The only thing left to do is add the IncrementGlobalCounterAction to the background image to increment the counter by 1:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec7.png" alt="" /></p>
<p> </p>
<p>So with 5 Action instances, 3 Trigger types, 1 Storyboard, and 0 lines of code we were able to quickly add this feature to the game.</p>
<p><a href="http://www.shazaml.com/downloads/ClutteredCubeSource14.zip"><img class="alignnone size-full wp-image-319" title="Zip" src="http://www.shazaml.com/wp-content/uploads/2009/10/Zip.png" alt="Zip" width="93" height="96" /> Source Code</a></p>
<p><a href="http://www.shazaml.com/hidden-object-game-episode-14-demo"><img class="alignnone size-full wp-image-320" title="silverlight" src="http://www.shazaml.com/wp-content/uploads/2009/10/silverlight.png" alt="silverlight" width="93" height="96" /> Demo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/hidden-object-episode-14/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hidden Object: Episode 13 – Give me a Hint</title>
		<link>http://www.shazaml.com/archives/hidden-object-episode-13</link>
		<comments>http://www.shazaml.com/archives/hidden-object-episode-13#comments</comments>
		<pubDate>Tue, 17 Nov 2009 19:12:44 +0000</pubDate>
		<dc:creator>Mark Tucker</dc:creator>
				<category><![CDATA[Hidden Object Game]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[Behavior]]></category>
		<category><![CDATA[Blend]]></category>
		<category><![CDATA[ControlStoryboardAction]]></category>
		<category><![CDATA[EventTrigger]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[GoToStateAction]]></category>
		<category><![CDATA[HintBehavior]]></category>
		<category><![CDATA[Storyboard]]></category>
		<category><![CDATA[StoryboardCompletedTrigger]]></category>
		<category><![CDATA[Visual State Manager]]></category>
		<category><![CDATA[VSM]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=349</guid>
		<description><![CDATA[Creating the hint feature requires a few animations and a custom behavior.]]></description>
			<content:encoded><![CDATA[<p>This is episode 13 of <a href="http://www.shazaml.com/archives/creating-a-hidden-object-game-in-silverlight-3">Creating a Hidden Object Game is Silverlight 3</a>. In this episode, we will add a hint feature to the game to help the players when they can&#8217;t find an item. This will require various animations and a custom behavior.</p>
<p>The hint feature can be segmented into three parts:</p>
<ul>
<li>Recharging hint button</li>
<li>Hint overlay image with animation</li>
<li>HintBehavior to randomly position the hint overlay image</li>
</ul>
<p> </p>
<h1>Hint Button</h1>
<p><img class="alignnone size-full wp-image-350" title="Hint Button" src="http://www.shazaml.com/wp-content/uploads/2009/11/hintbutton.Gif" alt="Hint Button" width="123" height="99" /></p>
<p>To make the hint button, we will use an image of a laptop, a TextBlock (hintTextBlock), and a ProgressBar (progressBar) wrapped in a Canvas (hintCanvas):</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/111709_1912_HiddenObjec1.png" alt="" /></p>
<p>The idea is that the TextBlock will contain the text &#8220;HINT&#8221; and act as a button to trigger the hint feature. When the TextBlock is clicked, the TextBlock is hidden and the ProgressBar shown. This is accomplished by adding a HintStates group to the main UserControl:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/111709_1912_HiddenObjec2.png" alt="" /></p>
<p>When the HintState is active, the TextBlock is shown and its IsHitTestVisible property is set to true so that it can be clicked. When the RechargeState is active, the TextBlock&#8217;s Opacity property is set to 0 and its IsHitTestVisible property is set to false so that it can&#8217;t be clicked.</p>
<p>To set the RechargeState, we add a GoToStateAction to the TextBlock:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/111709_1912_HiddenObjec3.png" alt="" /></p>
<p>A storyboard is added to change the value of the ProgressBar to indicate that the hint is recharging.</p>
<pre class="brush: xml; gutter: false;">
&lt;Storyboard x:Name=&quot;RechargingStoryboard&quot;&gt;
    &lt;DoubleAnimationUsingKeyFrames BeginTime=&quot;00:00:00&quot;
        Storyboard.TargetName=&quot;progressBar&quot;
        Storyboard.TargetProperty=&quot;(RangeBase.Value)&quot;&gt;
        &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00&quot; Value=&quot;0&quot;/&gt;
        &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:10&quot; Value=&quot;100&quot;/&gt;
    &lt;/DoubleAnimationUsingKeyFrames&gt;
&lt;/Storyboard&gt;
</pre>
<p>In this example, the storyboard will recharge in 10 seconds. For the game, the recharge duration should be somewhere between 30 seconds and 2 minutes.</p>
<p>This storyboard is started using a ControlStoryboardAction on the TextBlock:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/111709_1912_HiddenObjec4.png" alt="" /></p>
<p> </p>
<p>The change from RechargeState to HintState is handled by the GoToStateAction and the StoryboardCompletedTrigger waiting on RechargingStoryboard. So as soon as the recharging animation ends, then the Hint button displays again.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/111709_1912_HiddenObjec5.png" alt="" /></p>
<p> </p>
<h1>Hint Overlay</h1>
<p><img class="alignnone size-medium wp-image-351" title="Hint Overlay" src="http://www.shazaml.com/wp-content/uploads/2009/11/hintoverlay.Gif" alt="Hint Overlay" width="300" height="300" /></p>
<p>The hint overlay was created in Expression Design and consists of 10 starbursts or flares set in a circular pattern. After the image is added to the project, drag it onto the LayoutRoot Canvas and locate it &#8220;off screen&#8221; (Left = 500, Top = -300). Set the ZIndex of the image to 99 so that it will be over any item on the game screen, but always under the cursor image.</p>
<p> </p>
<p>When the hint TextBlock is clicked, two storyboards are started. The ShowHintStoryboard changes the opacity from 0% to 80% in 2 seconds and then auto reverses back to 0% over the next 2 seconds. The RotateHintStoryboard uses a RotateTransform to rotate the overlay 360 degrees over 4 seconds.</p>
<pre class="brush: xml; gutter: false;">
&lt;Storyboard x:Name=&quot;ShowHintStoryboard&quot; AutoReverse=&quot;True&quot;&gt;
    &lt;DoubleAnimationUsingKeyFrames BeginTime=&quot;00:00:00&quot;
        Storyboard.TargetName=&quot;hintFlareImage&quot;
        Storyboard.TargetProperty=&quot;(UIElement.Opacity)&quot;&gt;
        &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00&quot; Value=&quot;0&quot;/&gt;
        &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:02&quot; Value=&quot;0.8&quot;/&gt;
    &lt;/DoubleAnimationUsingKeyFrames&gt;
&lt;/Storyboard&gt;

&lt;Storyboard x:Name=&quot;RotateHintStoryboard&quot;&gt;
    &lt;DoubleAnimationUsingKeyFrames BeginTime=&quot;00:00:00&quot;
        Storyboard.TargetName=&quot;hintFlareImage&quot;
        Storyboard.TargetProperty=&quot;(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)&quot;&gt;
        &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00&quot; Value=&quot;0&quot;/&gt;
        &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:04&quot; Value=&quot;360&quot;/&gt;
    &lt;/DoubleAnimationUsingKeyFrames&gt;
&lt;/Storyboard&gt;
 </pre>
<p>To start the storyboards, use the ControlStoryboardAction with the EventTrigger:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/111709_1912_HiddenObjec6.png" alt="" /></p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/111709_1912_HiddenObjec7.png" alt="" /></p>
<p> </p>
<h1>Hint Behavior</h1>
<p>The last thing we need to do is figure out where to put the hint overlay image. To do this, we will use a behavior that exposes a ShowHint command as well as a HintItems collection and a HintOverlayName property:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/111709_1912_HiddenObjec8.png" alt="" /></p>
<p>In the same way that the MouseCursorBehavior exposes the CursorName property to allow selection of the cursor, the HintBehavior exposes the HintOverlayName so that we can select the hint overlay image. An EventTrigger causes the ShowHint command to fire when the HINT TextBlock is clicked.</p>
<p>The HintItems collection contains one HintItem object for each item that can have a hint. The HintItem object contains a TargetName property to identify the Path or object representing the item and an X and Y variance for the location of the overlay.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/111709_1912_HiddenObjec9.png" alt="" /></p>
<p>The HintBehavior uses two NameResolver instances (see <a href="http://www.shazaml.com/archives/hidden-object-episode-12">episode 12</a>). The first NameResolver changes the HintOverlayName into a reference to the overlay image control. The second NameResolver is used once a HintItem is randomly picked to see if the object still exists and if so gets a reference to it. Even though a HintItem exists for all clickable items in the hidden object game, it may no longer exist in the visual tree as it could have been removed by the RemoveElementAction as discussed in <a href="http://www.shazaml.com/archives/hidden-object-episode-4">episode 4</a>.</p>
<p>When the ShowHint command is executed, the private OnShowHint method is called. This is the heart of the HintBehavior:</p>
<pre class="brush: csharp; gutter: false;">
private void OnShowHint()
{
  DependencyObject item = null;
 
  if (!this.IsHintOverlayNameSet)
    return;
 
  FrameworkElement hintOverlay = HintOverlay as FrameworkElement;
 
  //mix up the order of item names
  HintItems.Randomize();
 
  for (int index = 0; index &lt; HintItems.Count; index++)
  {
    this.ItemResolver.Name = HintItems[index].TargetName;
    item = this.ItemResolver.Object;
 
    if (item != null)
    {
      double itemX = (double)item.GetValue(Canvas.LeftProperty);
      double itemWidth = (double)item.GetValue(FrameworkElement.ActualWidthProperty);
      double itemY = (double)item.GetValue(Canvas.TopProperty);
      double itemHeight = (double)item.GetValue(FrameworkElement.ActualHeightProperty);
    
      double newX = RandomWithVariance(itemX + (itemWidth / 2) - (hintOverlay.ActualWidth / 2), HintItems[index].OriginXVariance);
      double newY = RandomWithVariance(itemY + (itemHeight / 2) - (hintOverlay.ActualHeight / 2), HintItems[index].OriginYVariance);
 
      hintOverlay.SetValue(Canvas.LeftProperty, newX);
      hintOverlay.SetValue(Canvas.TopProperty, newY);

      break;
    }
  }
}
</pre>
<p> </p>
<p>If the HintOverlayName is not set we exit the method, otherwise we get a reference to it. We then randomize the order of the items in the HintItems list. This is done using an extension method called Randomize(). Since some items named in the list may no longer exist on the Canvas, we do a null check after we access an item in the list and resolve it. If the item exists, then we determine the location of the item with its width and height so that we can center the overlay image over the item. The RandomWithVariance method uses the OriginXVariance and OriginYVariance values set on HintItem to make sure that the overlay image is over the item but that the item is not necessarily exactly centered.</p>
<p> </p>
<p>The hint feature of our hidden object game is fairly simple once we break it into its three main components and work on them individually. Stay tuned for the <a href="http://www.shazaml.com/archives/hidden-object-episode-14">next episode</a> of Creating a Hidden Object Game in Silverlight 3.</p>
<p><a href="http://www.shazaml.com/downloads/ClutteredCubeSource13.zip"><img class="alignnone size-full wp-image-319" title="Zip" src="http://www.shazaml.com/wp-content/uploads/2009/10/Zip.png" alt="Zip" width="93" height="96" /> Source Code</a></p>
<p><a href="http://www.shazaml.com/hidden-object-game-episode-13-demo"><img class="alignnone size-full wp-image-320" title="silverlight" src="http://www.shazaml.com/wp-content/uploads/2009/10/silverlight.png" alt="silverlight" width="93" height="96" /> Demo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/hidden-object-episode-13/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
