<?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; GoToStateAction</title>
	<atom:link href="http://www.shazaml.com/archives/tag/gotostateaction/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 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>
		<item>
		<title>Video: Creating a Silverlight 3 Casual Game using Blend 3 and Triggers, Actions, and Behaviors</title>
		<link>http://www.shazaml.com/archives/video-silverlight-casual-game</link>
		<comments>http://www.shazaml.com/archives/video-silverlight-casual-game#comments</comments>
		<pubDate>Mon, 09 Nov 2009 15:19:11 +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[ChangePropertyAction]]></category>
		<category><![CDATA[ContinuousPlayMediaBehavior]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[GlobalCounterMinReachedTrigger]]></category>
		<category><![CDATA[GoToStateAction]]></category>
		<category><![CDATA[IncrementGlobalCounterAction]]></category>
		<category><![CDATA[InvokeCommandAction]]></category>
		<category><![CDATA[MagnifierOverBehavior]]></category>
		<category><![CDATA[MouseCursorBehavior]]></category>
		<category><![CDATA[ParticlesBehavior]]></category>
		<category><![CDATA[PlaySoundAction]]></category>
		<category><![CDATA[RemoveElementAction]]></category>
		<category><![CDATA[SetGlobalCounterAction]]></category>
		<category><![CDATA[SetInteractionPropertyAction]]></category>
		<category><![CDATA[ShowGlobalCounterBehavior]]></category>
		<category><![CDATA[Trigger]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[Visual State Manager]]></category>
		<category><![CDATA[VSM]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=333</guid>
		<description><![CDATA[Video presentation from Desert Code Camp 2009 - Silverlight 3 Casual Game]]></description>
			<content:encoded><![CDATA[<p>On Saturday, November 7, 2009 at 9:00am I presented at the Desert Code Camp in Phoenix, AZ. The topic of my presentation was Silverlight casual game development. In less than an hour I demonstrated how to use triggers, actions, and behaviors in Blend 3 to create a hidden object game. Because all code was contained in the TABs (Triggers, Actions, and Behaviors) there was no code behind for the main UserControl.</p>
<p>Here is a link to the <a title="Video - Creating a Silverlight 3 Casual Game using Blend 3 and Triggers, Actions, and Behaviors" href="http://www.shazaml.com/downloads/DesertCodeCamp2009-Silverlight3CasualGame.wmv">presentation video</a> in WMV format.</p>
<p>If you like you can see <a href="http://www.shazaml.com/archives/creating-a-hidden-object-game-in-silverlight-3">all the episodes</a> and follow along with the tutorial.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/video-silverlight-casual-game/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
<enclosure url="http://www.shazaml.com/downloads/DesertCodeCamp2009-Silverlight3CasualGame.wmv" length="63294285" type="video/x-ms-wmv" />
		</item>
		<item>
		<title>Hidden Object: Episode 10 – Counting Items Found with Counter Triggers, Actions &amp; a Behavior</title>
		<link>http://www.shazaml.com/archives/hidden-object-episode-10</link>
		<comments>http://www.shazaml.com/archives/hidden-object-episode-10#comments</comments>
		<pubDate>Sun, 04 Oct 2009 07:10:46 +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[games]]></category>
		<category><![CDATA[GlobalCounterChangedTrigger]]></category>
		<category><![CDATA[GlobalCounterMaxReachedTrigger]]></category>
		<category><![CDATA[GlobalCounterMinReachedTrigger]]></category>
		<category><![CDATA[GoToStateAction]]></category>
		<category><![CDATA[IncrementGlobalCounterAction]]></category>
		<category><![CDATA[SetGlobalCounterAction]]></category>
		<category><![CDATA[ShowGlobalCounterBehavior]]></category>
		<category><![CDATA[Trigger]]></category>
		<category><![CDATA[Visual State Manager]]></category>
		<category><![CDATA[VSM]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=267</guid>
		<description><![CDATA[Using a custom behavior, triggers, and actions we are able to count the number of items found and change state when the last item is found.]]></description>
			<content:encoded><![CDATA[<p>In episode 9 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 added additional screens to the game. In this episode, we will add the Win screen and a collection of triggers, actions, &amp; behaviors that work with a global counter.</p>
<p>The Win screen is shown after all 13 items have been clicked. What we need is an integer counter that subtracts one for each item clicked and when the count gets to zero change the state of the <em>MainPage</em> UserControl to show the screen.</p>
<p>Similar to what we did in the last episode, create a new Canvas called <em>winCanvas</em> and position it to the left of the UserControl on the artboard.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec1.png" alt="" /></p>
<p>In the States panel, add the WinScreen state to the ScreenStates group:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec2.png" alt="" /></p>
<p>With recording mode on for the WinScreen state, set the Top and Left properties of <em>winCanvas</em> to 0.</p>
<p>All we need to do is figure out a way to trigger a state change to show this screen.</p>
<p>The solution is a variation of the <a href="http://electricbeach.org/?p=349">Global State Behavior sample</a> by Christian Schormann which uses a <a href="http://msdn.microsoft.com/en-us/library/ms954629.aspx">Singleton</a> object containing a Dictionary to hold values based on a key (or tag).</p>
<p>Let&#8217;s go step-by-step through the use of the GlobalCounter classes before we look at any code.</p>
<p>The counter store (GlobalCounterStore) has an empty dictionary keyed using a CounterKey. Some trigger invokes SetGlobalCounterAction which sets the initial values for Value, MinValue, and MaxValue in a dictionary item with a CounterKey of &#8220;HiddenItems&#8221;. In this case the trigger that sets the values is an EventTrigger on the <em>MainPage</em> UserControl for the Loaded event:</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec3.png"><img class="alignnone size-medium wp-image-253" title="100409_0710_HiddenObjec3.png" src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec3-300x157.png" alt="100409_0710_HiddenObjec3.png" width="300" height="157" /></a> </p>
<p> </p>
<p>Any time that an entry is changed in the counter store, the Changed event is raised which passes Key, Value, MinValue, and MaxValue. Both the ShowGlobalCounterBehavior and the GlobalCounterChangedTrigger handle this event. Since every instance of the GlobalCounterChangedTrigger &amp; ShowGlobalCounterBehavior handle the Changed event they need to have a CounterKey property to determine if they should take any action for that event. In the case of ShowGlobalCounterBehavior, the associated TextBlock&#8217;s Text property is set to Value. For the GlobalCounterChangedTrigger any actions are invoked. In this episode, the GlobalCounterChangedTrigger is not used but is included for completeness.</p>
<p>Now that the counter store has been initialized with values, we can use the IncrementGlobalCounterAction to increment the value. In this case we are incrementing the value by -1 which updates the value in the counter store causing the Changed event to fire which is handled by the ShowGlobalCounterBehavior which sets the text on the TextBlock.</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec4.png"><img class="alignnone size-medium wp-image-254" title="100409_0710_HiddenObjec4.png" src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec4-300x229.png" alt="100409_0710_HiddenObjec4.png" width="300" height="229" /></a></p>
<p> </p>
<p>The IncrementGlobalCounterAction is invoked for each Path object clicked until the counter reaches the MinValue:</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec5.png"><img class="alignnone size-medium wp-image-255" title="100409_0710_HiddenObjec5.png" src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec5-300x149.png" alt="100409_0710_HiddenObjec5.png" width="300" height="149" /></a></p>
<p> </p>
<p>The Changed event is fired to update the TextBlock, but the MinValueReached event is also fired. This is handled by the GlobalCounterMinReachedTrigger which compares its CounterKey with the Key passed in the event and if they match then the trigger invokes its actions. For this episode, there is a GoToStateAction associated with the UserControl that responds to the GlobalCounterMinReachedTrigger and sets the current state to WinScreen which shows <em>winCanvas</em>.</p>
<p>In cases where you want an incrementing counter instead of a decrementing one, pass a positive value for the IncrementCounterValueBy property of IncrementGlobalCounterAction and use the GlobalCounterMaxReachedTrigger.</p>
<p>The global counter classes can be used for many things including a lives counter, health, shield strength, or to keep track of a player&#8217;s score.</p>
<p>Here are a class diagram of the GlobalCounterStore and related classes:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec6.png" alt="" /></p>
<p>Besides the implementation of the Singleton pattern, the most interesting code can be found in the SaveToStore and IncrementCounter methods of GlobalCounterStore:</p>
<pre class="brush: csharp; gutter: false;">
internal sealed class GlobalCounterStore
{
    private Dictionary&lt;string, GlobalCounterItem&gt; store;

    internal void SaveToStore(string key, int value, int minValue, int maxValue)
    {
        if (key == null)
            return;
        var item = new GlobalCounterItem() {Value = value, MinValue = minValue, MaxValue = maxValue };

        if (store.ContainsKey(key))
        {
            store[key] = item;
        }
        else
        {
            store.Add(key, item);
        }

        OnChanged(key, item);
    }

    internal void IncrementCounter(string key, int incrementBy)
    {
        if ((key == null) || !store.ContainsKey(key))
            return;

        int newValue = store[key].Value + incrementBy;
        store[key].Value = newValue;

        OnChanged(key, store[key]);

        if (newValue &gt;= store[key].MaxValue)
            OnMaxValueReached(key, store[key]);

        if (newValue &lt;= store[key].MinValue)
            OnMinValueReached(key, store[key]);
    }
}
</pre>
<p> </p>
<p>The SetGlobalCounterAction is a TriggerAction that defines four dependency properties for CounterKey, CounterValue, CounterMinValue, and CounterMaxValue. The Invoke method calls the SaveToStore method on GlobalCounterStore.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec7.png" alt="" /></p>
<p>The IncrementGlobalCounterAction is a TargetedTriggerAction that defines dependency properties for CounterKey and IncrementCounterValueBy. It&#8217;s Invoke method calls the IncrementCounter method on GlobalCounterStore.</p>
<p> </p>
<p>The three triggers are very similar in that each defines a CounterKey dependency property and each adds a handler to an event raised by GlobalCounterStore:</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/10/GlobalCounterTriggers.png"><img class="alignnone size-full wp-image-268" title="GlobalCounterTriggers" src="http://www.shazaml.com/wp-content/uploads/2009/10/GlobalCounterTriggers.png" alt="GlobalCounterTriggers" width="266" height="679" /></a></p>
<p> </p>
<p>In the case of GlobalCounterMinReachedTrigger, the OnAttached method adds a handler for the GlobalCounterStore&#8217;s MinValueReached event whereas the handler is removed in the OnDetaching method:</p>
<pre class="brush: csharp; gutter: false;">
public class GlobalCounterMinReachedTrigger : TriggerBase&lt;DependencyObject&gt;
{
    protected override void OnAttached()
    {
        base.OnAttached();
        GlobalCounterStore.Instance.MinValueReached += Instance_MinValueReached;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        GlobalCounterStore.Instance.MinValueReached -= Instance_MinValueReached;
    }

    void Instance_MinValueReached(object sender, GlobalCounterEventArgs e)
    {
        if (CounterKey == null)
            return;

        if (CounterKey == e.Key)
            this.InvokeActions(e);
    }
}
</pre>
<p> </p>
<p>When the MinValueReached event is raised due to a change in the GlobalCounterStore to any dictionary entry regardless of its key, the passed key (e.Key) is compared to the CounterKey property. If the values match, then the actions for this trigger are invoked.</p>
<p> </p>
<p>ShowGlobalCounterBehavior is a behavior that can be attached to a TextBlock control and functions is a similar way as the triggers:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec9.png" alt="" /></p>
<p> </p>
<p>It defines the CounterKey property and handles the Changed event raised by GlobalCounterKey:</p>
<pre class="brush: csharp; gutter: false;">
public class ShowGlobalCounterBehavior : Behavior&lt;TextBlock&gt;
{
    protected override void OnAttached()
    {
        base.OnAttached();
        GlobalCounterStore.Instance.Changed += Instance_Changed;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        GlobalCounterStore.Instance.Changed -= Instance_Changed;
    }
 
    void Instance_Changed(object sender, GlobalCounterEventArgs e)
    {
        if (CounterKey == e.Key)
        {
            if (e.Value &gt; e.MaxValue)
                AssociatedObject.Text = e.MaxValue.ToString();
            else if (e.Value &lt; e.MinValue)
                AssociatedObject.Text = e.MinValue.ToString();
            else
                AssociatedObject.Text = e.Value.ToString();
        }
    }
}
</pre>
<p> </p>
<p>It is possible to increment the Value in the counter store by more than 1 so I added checks so that the TextBlock will never show values greater than MaxValue or less than MinValue.</p>
<p> </p>
<p>Now it is time to use these classes in Blend. Drop an instance of SetGlobalCounterAction on the UserControl, a GoToStateAction on LayoutRoot, and a IncrementGlobalCounterAction on a Path:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec10.png" alt="" /></p>
<p> </p>
<p>The values for SetGlobalCounterAction are set as follows:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec11.png" alt="" /></p>
<p> </p>
<p>The new GoToStateAction uses GlobalCounterMinReachedTrigger and sets the StateName to WinScreen:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec12.png" alt="" /></p>
<p> </p>
<p>Each path will have an IncrementGlobalCounterAction set with these values:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec13.png" alt="" /></p>
<p> </p>
<p> </p>
<p>Finally, we add a TextBlock to our Canvas to hold the count of remaining items and add the ShowGlobalCounterBehavior to it:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec14.png" alt="" /></p>
<p> </p>
<p> <a href="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec15.png"><img class="alignnone size-medium wp-image-265" title="100409_0710_HiddenObjec15.png" src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec15-300x156.png" alt="100409_0710_HiddenObjec15.png" width="300" height="156" /></a></p>
<p> </p>
<p> </p>
<p>The only property to set on the behavior is the CounterKey: </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec16.png" alt="" /></p>
<p> </p>
<p> </p>
<p>Once we add IncrementGlobalCounterAction to each Path, we can run the game and as we find items the counter will decrement by 1. When the value reaches 0, then the winning screen is shown.</p>
<p> </p>
<p><a href="http://www.shazaml.com/downloads/ClutteredCubeSource10.zip">Source code</a></p>
<p><a href="http://www.shazaml.com/hidden-object-episode-10-demo">Demo</a></p>
<p> </p>
<p>In the <a href=" http://www.shazaml.com/archives/hidden-object-episode-11 ">next episode</a> we will update the Particles Behavior to allow particle custom shapes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/hidden-object-episode-10/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Hidden Object: Episode 9 – Add the Splash, Menu &amp; Options Screens</title>
		<link>http://www.shazaml.com/archives/hidden-object-episode-9</link>
		<comments>http://www.shazaml.com/archives/hidden-object-episode-9#comments</comments>
		<pubDate>Tue, 29 Sep 2009 23:55:09 +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[games]]></category>
		<category><![CDATA[GoToStateAction]]></category>
		<category><![CDATA[Visual State Manager]]></category>
		<category><![CDATA[VSM]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=237</guid>
		<description><![CDATA[Adding the screen flow is easy with the Visual State Manager (VSM) and GoToStateAction.]]></description>
			<content:encoded><![CDATA[<p>This is episode 9 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 the last episode we added background music. Now we will create a screen to set the music volume. While we are at it, we will create the splash and menu screens.</p>
<p>When the game is finished, it will have a screen flow as follows:</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/09/HiddenObject-ScreenFlow.png"><img class="alignnone size-medium wp-image-243" title="HiddenObject-ScreenFlow" src="http://www.shazaml.com/wp-content/uploads/2009/09/HiddenObject-ScreenFlow-300x175.png" alt="HiddenObject-ScreenFlow" width="300" height="175" /></a></p>
<p> </p>
<p> Currently we have been working on the Game screen which in the project is a UserControl called <em>MainPage.xaml</em>. We are going to create the menu, options, and splash screens as Canvas objects that are off screen of <em>MainPage</em> and are at the bottom of the Objects tree (or top of the z-order) so they show up over all other controls. I chose to do this since I want the background music to play during all of these screens and the MediaElement on <em>MainPage</em> is the one that is playing it. There are various other ways to approach this.</p>
<p>Let&#8217;s open Blend, add 3 Canvas controls, and name them <em>splashCanvas</em>, <em>menuCanvas</em>, and <em>optionsCanvas</em>. Make each Canvas have a black background and position them on the artboard so that they are to the left of <em>MainPage</em>:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec2.png" alt="" /></p>
<p> </p>
<p>On <em>splashCanvas</em>, add 4 TextBlock controls and enter the title information:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec3.png" alt="" /></p>
<p> </p>
<p>On <em>menuCanvas</em>, add the page title in a TextBlock and 2 Buttons:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec4.png" alt="" /></p>
<p> </p>
<p>On <em>optionsCanvas</em>, add a TextBlock for the page title, a TextBlock for the slider title, a Slider control, and a Button:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec5.png" alt="" /></p>
<p>Since the silder&#8217;s Value property will be used in a Binding for the MediaElement&#8217;s Volume property, we will name the slider as <em>sliderMusicVolume</em>.</p>
<p> </p>
<p>To control the screen flow, we will use the States panel to create a <em>ScreenStates</em> group with the following states: <em>GameScreen</em>, <em>SplashScreen</em>, <em>MenuScreen</em>, <em>OptionsScreen</em>.</p>
<p>On the States tab, click the <em>Add state group</em> button:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec6.png" alt="" /></p>
<p>Then next to the <em>ScreenStates</em> group, click the <em>Add state</em> button:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec7.png" alt="" /></p>
<p>As I entered the following states, I didn&#8217;t worry about setting any properties for any of the controls and after adding <em>OptionsScreen</em> I just turned off recording.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec8.png" alt="" /></p>
<p>The <em>GameScreen</em> state represents when the <em>MainPage</em> is visible which is how it currently is shown on the artboard. No change will need to be made for this state. Click on the <em>SplashScreen</em> state in the States tab to turn on recording mode. Then click <em>splashCanvas</em> and change its Top and Left properties both to 0. Turn off recording of the <em>SplashScreen</em> state.</p>
<p>Repeat for the <em>MenuScreen</em> and <em>OptionsScreen</em> states so that when one of these states is active, MainPage will be covered by <em>menuCanvas</em> or <em>optionsCanvas</em>.</p>
<p>Click on the Base state at the top of the States tab to make sure you are completely out of state editing mode.</p>
<p>We now need to add a TextBlock with the Text property set to &#8220;MENU&#8221; and add it to LayoutRoot in <em>MainPage</em>. Because I added this control after the Canvas controls for the other screens, I need to change its order in the Objects tree so that it doesn&#8217;t appear above those screens. We will worry about making the MENU TextBlock into a Button at a later time.</p>
<p> </p>
<p>Now it is time to use the GoToStateAction to connect the screen flow. Drop the first GoToStateAction onto LayoutRoot and change the EventName to <em>Loaded</em> and the StateName to <em>SplashScreen</em>:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec9.png" alt="" /></p>
<p>This will cause the splash screen to show first.</p>
<p>NOTE: While we are still in development, we can set the loaded StateName to GameScreen to reduce testing time.</p>
<p> </p>
<p>Drop another GoToStateAction onto <em>splashCanvas</em> and change the StateName to <em>MenuScreen</em>. When the splash screen is clicked, we will advance to the menu screen:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec10.png" alt="" /></p>
<p>Drop two more GoToStateAction actions onto the <em>Start</em> and <em>Options</em> buttons on <em>menuCanvas</em>. Change the StateNames to <em>GameScreen</em> and <em>OptionsScreen</em> respectively.</p>
<p>Start button:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec11.png" alt="" /></p>
<p> </p>
<p>Options button:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec12.png" alt="" /></p>
<p> </p>
<p>Drop another GoToStateAction onto the Close button in <em>optionsCanvas</em> and change the StateName to <em>MenuScreen</em>:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec13.png" alt="" /></p>
<p> </p>
<p>Finally, drop the last GoToStateAction onto the MENU TextBlock in <em>MainPage</em> and set the StateName to <em>MenuScreen</em>:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec14.png" alt="" /></p>
<p> </p>
<p>We have just put together the majority of our screen flow with 6 instances of GoToStateAction and no code!</p>
<p> </p>
<p>The last thing we need to do is to connect the slider value to the volume of the background music. In the Objects tree, select the <em>musicMediaElement</em> and in the Properties pane, click the peg to the right of the Volume property and click Data Binding to open the Create Data Binding window:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec15.png" alt="" /></p>
<p> </p>
<p>Select the ElementProperty tab. In the Scene elements list, open <em>optionsCanvas</em> and select <em>sliderMusicVolume</em>. In the Properties list, select Value. Now when the slider in the options screen is changed, it will set the volume on the MediaElement playing the background music.</p>
<p>The last thing we need to do is set some values on the slider control. Select the control and change the following properties found in the Common Properties group: LargeChange, Maximum, and Value.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092909_2354_HiddenObjec16.png" alt="" /></p>
<p> </p>
<p>In the <a href=" http://www.shazaml.com/archives/hidden-object-episode-10">next episode</a>, we will try to figure out a way to determine when all the objects have been found so we can show a Win screen.</p>
<p><a href="http://www.shazaml.com/hidden-object-episode-9-demo">Demo</a><br />
<a href="http://www.shazaml.com/downloads/ClutteredCubeSource9.zip">Source code</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/hidden-object-episode-9/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
