<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Niners/c4f.Justin-Petersen/Posts/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9</title>
      <link>http://channel9.msdn.com/Niners/c4f.Justin-Petersen/Posts</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/Niners/c4f.Justin-Petersen/Posts</link>
    <language>en</language>
    <pubDate>Wed, 19 Jun 2013 10:44:06 GMT</pubDate>
    <lastBuildDate>Wed, 19 Jun 2013 10:44:06 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>1</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>Silverlight 8-Ball</title>
      <description><![CDATA[<span id="c4fmetadata">
<table cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td width="50"><img height="48" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/8BallSmall.png" width="48"></td>
<td><span class="entry_description">In this article, I will discuss how I have built a 2 player 8-Ball game in Silverlight (<a href="http://employees.claritycon.com/jpetersen/Silverlight8Ball/">play here</a>). I will explain how I used the Expression tools
 to design the graphics and various .NET techniques to enable user control and game animation.
</span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author">Justin Petersen</div>
<div class="entry_company"><a href="http://www.claritycon.com/coding4fun">Coding4Fun at Clarity</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Intermediate</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
6-10 hours</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input"><a href="http://msdn2.microsoft.com/en-us/vstudio/">Visual Studio 2008 Beta 2</a>,
<a href="http://msdn2.microsoft.com/en-us/silverlight/">Silverlight 1.1 Alpha Refresh</a>,
<a href="http://www.microsoft.com/expression/products/overview.aspx?key=design">Expression Design</a>,
<a href="http://www.microsoft.com/expression/products/features.aspx?key=blend2preview">
Expression Blend 2 Preview</a> </span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input"></span></div>
<div class="entry_details"><b>Download: </b><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/342985_Silverlight8Ball.zip">Download</a>
</div>
</td>
</tr>
</tbody>
</table>
</span>
<p></p>
<p>In this article, I will discuss how I have built a 2 player 8-Ball game in Silverlight (<a href="http://employees.claritycon.com/jpetersen/Silverlight8Ball/">play here</a>). I will explain how I used the Expression tools to design the graphics and various
 .NET techniques to enable user control and game animation.&nbsp; </p>
<p>The following components must be implemented to complete this game: </p>
<ol>
<li>Graphics (pool table, pool ball, and pool stick) </li><li>Vector animation and collision physics </li><li>User interaction&nbsp; </li><li>Game state and control</li></ol>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/Silverlight8Ball18.png"><img height="335" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/Silverlight8Ball_thumb12.png" width="439" border="0"></a>
</p>
<p>Before I continue, I'd like to point out that I did not originate all of the code and XAML for this solution. I came up with the idea of creating a Silverlight 8-Ball game after stumbling upon a 2-D “bouncing bubble” animation here:
<a href="http://www.bubblemark.com/">http://www.bubblemark.com/</a>&nbsp;created by Alexey Gavrilov.&nbsp;
</p>
<p>The original intent for this solution was to compare the performance of the bouncing bubbles across&nbsp;various platforms.&nbsp; I found this very useful, but was personally interested in making something fun and interactive out of it.&nbsp;
</p>
<h1></h1>
<h2><b>Getting Started</b></h2>
<h5><strong>Prerequisites </strong></h5>
<p>The following tools were used to implement this solution: </p>
<ul>
<li>Visual Studio 2008 Beta 2 </li><li>Silverlight 1.1 Alpha Refresh&nbsp; </li><li>Expression Design </li><li>Expression Blend</li></ul>
<h5><strong>Learning more about game development</strong> </h5>
<p>If you'd like to learn more about game development, I found a number Coding4Fun posts&nbsp;under Gaming helpful.&nbsp; In particular,&nbsp;the&nbsp;<a href="http://blogs.msdn.com/coding4fun/archive/2007/02/20/1727608.aspx">2D Game Primer</a>&nbsp;by &quot;ZMan&quot; gives a good overview
 of the basics (e.g. GameLoop, Sprites, etc.)</p>
<h2><b>Graphics</b> </h2>
<p>I am not much of a&nbsp;graphic&nbsp;designer.&nbsp; In fact, I've spent the majority of my career designing and implementing line of business apps for enterprise customers (typically not a very graphically intensive task).&nbsp; So I believe it is a decent testament to the&nbsp;effectiveness
 of the Microsoft Expression suite that I could, in short order, create the graphics for this game.&nbsp;
</p>
<p>I used Expression Design to build the graphics of the pool table.&nbsp; Modeling my design&nbsp;after the standard dimension of a 9 foot billiards table,&nbsp;I drew the main structure&nbsp;as a rectangle with rounded corners.&nbsp;&nbsp;I drew a smaller green rectangle centered over
 it for the playing surface (of course following standard dimensions).&nbsp; Next, I created 6 black circles placed one level behind the playing surface to give the impression of pockets.&nbsp; Lastly, I added the wood texture to the outside rectangle (which was super
 easy as there is a set of wood textures available by default), and drew a simple rounded rectangle beneath the table to serve as a status bar.&nbsp;
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image03.png"><img height="272" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image0_thumb1.png" width="437" border="0"></a>
</p>
<p>I also created the graphics for my pool stick using Expression Design.&nbsp; This consisted of a few tapered polygons and 2 half circles for the butt and tip.
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image011.png"><img height="229" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image0_thumb5.png" width="433" border="0"></a>
</p>
<p>After exporting the associated XAML, I imported each element into my project.&nbsp; From here, I could view and refine the design through a scaled down visual editor or the associated XAML.
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image021.png"><img height="271" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image0_thumb9.png" width="433" border="0"></a>
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image024.png"><img height="270" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image0_thumb10.png" width="433" border="0"></a>
</p>
<p>Lastly, I inspected the&nbsp;XAML markup for the pool ball I reused from Alexey's Bubblemark solution.&nbsp; I needed to understand the properties of this object so that I could modify the color of the balls later on.
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image018.png"><img height="272" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5002772/image0_thumb8.png" width="436" border="0"></a>
</p>
<h2><b>Vector Animation and Collision Physics</b> </h2>
<p>The root of Silverlight8Ball is a Storyboard (x:Name=”GameLoop”) that acts as a triggering mechanism for determining ball velocity, direction, and redirection due to collision. Whereas some Storyboards are implemented with predetermined paths and timelines
 directly in XAML, the action taken at each tick must be determined dynamically in this game. So we simply set the duration to 00:00:0, and handle the Completed event to trigger our positioning logic. This design effectively creates what game developers call
 a “Game Loop” that triggers continuous processing to determine application state.
</p>
<p>The resulting “GameLoop_Completedhandler” becomes the root processing agent for all of the game's ball movement logic.&nbsp;&nbsp;
</p>
<p><strong>C#</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>void</span> GameLoop_Completed(<span>object</span> sender, EventArgs e)</pre>
<pre><span>   2:</span> {</pre>
<pre><span>   3:</span>     <span>switch</span> (m_ActionState)</pre>
<pre><span>   4:</span>     {</pre>
<pre><span>   5:</span>         <span>case</span> m_ActionStates.BallsMoving:</pre>
<pre><span>   6:</span> &nbsp;</pre>
<pre><span>   7:</span>             <span>// prep</span></pre>
<pre><span>   8:</span>             List&lt;Ball&gt; removeList = <span>new</span> List&lt;Ball&gt;();</pre>
<pre><span>   9:</span>             <span>bool</span> someBallsAreMoving = <span>false</span>;</pre>
<pre><span>  10:</span> &nbsp;</pre>
<pre><span>  11:</span>             <span>// move each ball</span></pre>
<pre><span>  12:</span>             <span>foreach</span> (Ball ball <span>in</span> m_GameBalls)</pre>
<pre><span>  13:</span>             {</pre>
<pre><span>  14:</span>                 ball.Move();</pre>
<pre><span>  15:</span>                 <span>if</span> (ball.InPocket) removeList.Add(ball);</pre>
<pre><span>  16:</span>                 <span>else</span> <span>if</span> (ball.IsMoving) someBallsAreMoving = <span>true</span>;</pre>
<pre><span>  17:</span>             }</pre>
<pre><span>  18:</span> &nbsp;</pre>
<pre><span>  19:</span>             <span>// store balls sunk on shot and update ui </span></pre>
<pre><span>  20:</span>             <span>foreach</span> (Ball ball <span>in</span> removeList)</pre>
<pre><span>  21:</span>             {</pre>
<pre><span>  22:</span>                 sunkBalls.Add(ball);</pre>
<pre><span>  23:</span>                 RemoveBall(ball);</pre>
<pre><span>  24:</span>             }</pre>
<pre><span>  25:</span> &nbsp;</pre>
<pre><span>  26:</span>             <span>if</span> (someBallsAreMoving)</pre>
<pre><span>  27:</span>             {</pre>
<pre><span>  28:</span>                 <span>// update vectors for ball collisions</span></pre>
<pre><span>  29:</span>                 <span>for</span> (<span>int</span> i = 0; i &lt; m_GameBalls.Count; i&#43;&#43;)</pre>
<pre><span>  30:</span>                 {</pre>
<pre><span>  31:</span>                     <span>for</span> (<span>int</span> j = i &#43; 1; j &lt; m_GameBalls.Count; j&#43;&#43;)</pre>
<pre><span>  32:</span>                     {</pre>
<pre><span>  33:</span>                         m_GameBalls[i].DoCollide(m_GameBalls[j]);</pre>
<pre><span>  34:</span>                     }</pre>
<pre><span>  35:</span>                 }</pre>
<pre><span>  36:</span>             }</pre>
<pre><span>  37:</span>             <span>else</span></pre>
<pre><span>  38:</span>             {</pre>
<pre><span>  39:</span>                 <span>// determine shot results</span></pre>
<pre><span>  40:</span>                 ShotResults results = EvaluateShot();</pre>
<pre><span>  41:</span> &nbsp;</pre>
<pre><span>  42:</span>                 <span>// apply state and ui changes</span></pre>
<pre><span>  43:</span>                 UpdateGameState(results);</pre>
<pre><span>  44:</span>             }</pre>
<pre><span>  45:</span> &nbsp;</pre>
<pre><span>  46:</span>             <span>break</span>;</pre>
<pre><span>  47:</span>     }</pre>
<pre><span>  48:</span> &nbsp;</pre>
<pre><span>  49:</span>     <span>// restart the storyboard</span></pre>
<pre><span>  50:</span>     <span>if</span> (m_IsRunning)</pre>
<pre><span>  51:</span>     {</pre>
<pre><span>  52:</span>         GameLoop.Begin();</pre>
<pre><span>  53:</span>     }</pre>
<pre><span>  54:</span> &nbsp;</pre>
<pre><span>  55:</span> }</pre>
</div>
</div>
<p><strong>VB</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>Private</span> <span>Sub</span> GameLoop_Completed(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> EventArgs)</pre>
<pre><span>   2:</span> &nbsp;</pre>
<pre><span>   3:</span>     <span>Select</span> <span>Case</span> m_ActionState</pre>
<pre><span>   4:</span> &nbsp;</pre>
<pre><span>   5:</span>         <span>Case</span> m_ActionStates.BallsMoving</pre>
<pre><span>   6:</span> &nbsp;</pre>
<pre><span>   7:</span>             <span>' prep</span></pre>
<pre><span>   8:</span>             <span>Dim</span> removeList <span>As</span> List(Of Ball) = <span>New</span> List(Of Ball)()</pre>
<pre><span>   9:</span>             <span>Dim</span> someBallsAreMoving <span>As</span> <span>Boolean</span> = <span>False</span></pre>
<pre><span>  10:</span> &nbsp;</pre>
<pre><span>  11:</span>             <span>' move each ball</span></pre>
<pre><span>  12:</span>             <span>For</span> <span>Each</span> ball <span>As</span> Ball <span>In</span> m_GameBalls</pre>
<pre><span>  13:</span>                 ball.Move()</pre>
<pre><span>  14:</span>                 <span>If</span> ball.InPocket <span>Then</span></pre>
<pre><span>  15:</span>                     removeList.Add(ball)</pre>
<pre><span>  16:</span>                 <span>ElseIf</span> ball.IsMoving <span>Then</span></pre>
<pre><span>  17:</span>                     someBallsAreMoving = <span>True</span></pre>
<pre><span>  18:</span>                 <span>End</span> <span>If</span></pre>
<pre><span>  19:</span>             <span>Next</span> ball</pre>
<pre><span>  20:</span> &nbsp;</pre>
<pre><span>  21:</span>             <span>' store balls sunk on shot and update ui </span></pre>
<pre><span>  22:</span>             <span>For</span> <span>Each</span> ball <span>As</span> Ball <span>In</span> removeList</pre>
<pre><span>  23:</span>                 sunkBalls.Add(ball)</pre>
<pre><span>  24:</span>                 RemoveBall(ball)</pre>
<pre><span>  25:</span>             <span>Next</span> ball</pre>
<pre><span>  26:</span> &nbsp;</pre>
<pre><span>  27:</span>             <span>If</span> someBallsAreMoving <span>Then</span></pre>
<pre><span>  28:</span>                 <span>' update vectors for ball collisions</span></pre>
<pre><span>  29:</span>                 <span>For</span> i <span>As</span> <span>Integer</span> = 0 <span>To</span> m_GameBalls.Count - 1</pre>
<pre><span>  30:</span>                     <span>For</span> j <span>As</span> <span>Integer</span> = i &#43; 1 <span>To</span> m_GameBalls.Count - 1</pre>
<pre><span>  31:</span>                         m_GameBalls(i).DoCollide(m_GameBalls(j))</pre>
<pre><span>  32:</span>                     <span>Next</span> j</pre>
<pre><span>  33:</span>                 <span>Next</span> i</pre>
<pre><span>  34:</span>             <span>Else</span></pre>
<pre><span>  35:</span>                 <span>' determine shot results</span></pre>
<pre><span>  36:</span>                 <span>Dim</span> results <span>As</span> ShotResults = EvaluateShot()</pre>
<pre><span>  37:</span> &nbsp;</pre>
<pre><span>  38:</span>                 <span>' apply state and ui changes</span></pre>
<pre><span>  39:</span>                 UpdateGameState(results)</pre>
<pre><span>  40:</span>             <span>End</span> <span>If</span></pre>
<pre><span>  41:</span> &nbsp;</pre>
<pre><span>  42:</span>     <span>End</span> <span>Select</span></pre>
<pre><span>  43:</span> &nbsp;</pre>
<pre><span>  44:</span>     <span>' restart the storyboard</span></pre>
<pre><span>  45:</span>     <span>If</span> m_IsRunning <span>Then</span></pre>
<pre><span>  46:</span>         GameLoop.Begin()</pre>
<pre><span>  47:</span>     <span>End</span> <span>If</span></pre>
<pre><span>  48:</span> &nbsp;</pre>
<pre><span>  49:</span> <span>End</span> Sub</pre>
</div>
</div>
<p>The above code snippets demonstrate the full functionality of our GameLoop.&nbsp; However, the primary animation and collision logic are handled by &quot;ball.Move();&quot; and &quot;m_GameBalls[i].DoCollide(m_GameBalls[j]);&quot; lines&nbsp;(in C# example).&nbsp; The Move() function of each
 ball applies its current vector (i.e. x and y &quot;velocities&quot;) to determine its next position and updates the ball's&nbsp;UI element coordinates.&nbsp; Once the ball is advanced, the DoCollide function checks if two balls have collided.&nbsp; If so, their vectors are adjusted
 accordingly.</p>
<p><strong>C#</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>public</span> <span>bool</span> DoCollide(Ball b)</pre>
<pre><span>   2:</span> {</pre>
<pre><span>   3:</span>     <span>// calculate some vectors </span></pre>
<pre><span>   4:</span>     <span>double</span> dx = <span>this</span>._x - b._x;</pre>
<pre><span>   5:</span>     <span>double</span> dy = <span>this</span>._y - b._y;</pre>
<pre><span>   6:</span>     <span>double</span> dvx = <span>this</span>._vx - b._vx;</pre>
<pre><span>   7:</span>     <span>double</span> dvy = <span>this</span>._vy - b._vy;</pre>
<pre><span>   8:</span>     <span>double</span> distance2 = dx * dx &#43; dy * dy;</pre>
<pre><span>   9:</span>     </pre>
<pre><span>  10:</span>     <span>if</span> (Math.Abs(dx) &gt; <span>this</span>._d || Math.Abs(dy) &gt; <span>this</span>._d)</pre>
<pre><span>  11:</span>         <span>return</span> <span>false</span>;</pre>
<pre><span>  12:</span>     <span>if</span> (distance2 &gt; <span>this</span>._d2)</pre>
<pre><span>  13:</span>         <span>return</span> <span>false</span>;</pre>
<pre><span>  14:</span> &nbsp;</pre>
<pre><span>  15:</span>     <span>// make absolutely elastic collision</span></pre>
<pre><span>  16:</span>     <span>double</span> mag = dvx * dx &#43; dvy * dy;</pre>
<pre><span>  17:</span> &nbsp;</pre>
<pre><span>  18:</span>     <span>// test that balls move towards each other    </span></pre>
<pre><span>  19:</span>     <span>if</span> (mag &gt; 0)</pre>
<pre><span>  20:</span>         <span>return</span> <span>false</span>;</pre>
<pre><span>  21:</span> &nbsp;</pre>
<pre><span>  22:</span>     mag /= distance2;</pre>
<pre><span>  23:</span> &nbsp;</pre>
<pre><span>  24:</span>     <span>double</span> delta_vx = dx * mag;</pre>
<pre><span>  25:</span>     <span>double</span> delta_vy = dy * mag;</pre>
<pre><span>  26:</span> &nbsp;</pre>
<pre><span>  27:</span>     <span>this</span>._vx -= delta_vx;</pre>
<pre><span>  28:</span>     <span>this</span>._vy -= delta_vy;</pre>
<pre><span>  29:</span> &nbsp;</pre>
<pre><span>  30:</span>     b._vx &#43;= delta_vx;</pre>
<pre><span>  31:</span>     b._vy &#43;= delta_vy;</pre>
<pre><span>  32:</span> &nbsp;</pre>
<pre><span>  33:</span>     <span>return</span> <span>true</span>;</pre>
<pre><span>  34:</span> }</pre>
</div>
</div>
<p><strong>VB</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>Public</span> <span>Function</span> DoCollide(<span>ByVal</span> b <span>As</span> Ball) <span>As</span> <span>Boolean</span></pre>
<pre><span>   2:</span>     <span>' calculate some vectors </span></pre>
<pre><span>   3:</span>     <span>Dim</span> dx <span>As</span> <span>Double</span> = <span>Me</span>._x - b._x</pre>
<pre><span>   4:</span>     <span>Dim</span> dy <span>As</span> <span>Double</span> = <span>Me</span>._y - b._y</pre>
<pre><span>   5:</span>     <span>Dim</span> dvx <span>As</span> <span>Double</span> = <span>Me</span>._vx - b._vx</pre>
<pre><span>   6:</span>     <span>Dim</span> dvy <span>As</span> <span>Double</span> = <span>Me</span>._vy - b._vy</pre>
<pre><span>   7:</span>     <span>Dim</span> distance2 <span>As</span> <span>Double</span> = dx * dx &#43; dy * dy</pre>
<pre><span>   8:</span> &nbsp;</pre>
<pre><span>   9:</span>     <span>If</span> Math.Abs(dx) &gt; <span>Me</span>._d <span>OrElse</span> Math.Abs(dy) &gt; <span>Me</span>._d <span>Then</span></pre>
<pre><span>  10:</span>         <span>Return</span> <span>False</span></pre>
<pre><span>  11:</span>     <span>End</span> <span>If</span></pre>
<pre><span>  12:</span>     <span>If</span> distance2 &gt; <span>Me</span>._d2 <span>Then</span></pre>
<pre><span>  13:</span>         <span>Return</span> <span>False</span></pre>
<pre><span>  14:</span>     <span>End</span> <span>If</span></pre>
<pre><span>  15:</span> &nbsp;</pre>
<pre><span>  16:</span>     <span>' make absolutely elastic collision</span></pre>
<pre><span>  17:</span>     <span>Dim</span> mag <span>As</span> <span>Double</span> = dvx * dx &#43; dvy * dy</pre>
<pre><span>  18:</span> &nbsp;</pre>
<pre><span>  19:</span>     <span>' test that balls move towards each other    </span></pre>
<pre><span>  20:</span>     <span>If</span> mag &gt; 0 <span>Then</span></pre>
<pre><span>  21:</span>         <span>Return</span> <span>False</span></pre>
<pre><span>  22:</span>     <span>End</span> <span>If</span></pre>
<pre><span>  23:</span> &nbsp;</pre>
<pre><span>  24:</span>     mag /= distance2</pre>
<pre><span>  25:</span> &nbsp;</pre>
<pre><span>  26:</span>     <span>Dim</span> delta_vx <span>As</span> <span>Double</span> = dx * mag</pre>
<pre><span>  27:</span>     <span>Dim</span> delta_vy <span>As</span> <span>Double</span> = dy * mag</pre>
<pre><span>  28:</span> &nbsp;</pre>
<pre><span>  29:</span>     <span>Me</span>._vx -= delta_vx</pre>
<pre><span>  30:</span>     <span>Me</span>._vy -= delta_vy</pre>
<pre><span>  31:</span> &nbsp;</pre>
<pre><span>  32:</span>     b._vx &#43;= delta_vx</pre>
<pre><span>  33:</span>     b._vy &#43;= delta_vy</pre>
<pre><span>  34:</span> &nbsp;</pre>
<pre><span>  35:</span>     <span>Return</span> <span>True</span></pre>
<pre><span>  36:</span> <span>End</span> Function</pre>
</div>
</div>
<h2>User Interaction&nbsp;</h2>
<p>While the GameLoop Storyboard does a good job at managing ball movement, I didn't think it was the&nbsp;best option for handling pool stick&nbsp;and&nbsp;q-ball control.&nbsp; During times of user control (stick aiming and q-ball &quot;ball in hand&quot;), I chose to use mouse movement
 and&nbsp;click events to determine object position and angle.&nbsp; I created my own enumeration to manage switching between ball movement and user control&nbsp;states.&nbsp; The rest involves some simple statistics and Silverlight XAML transformations.
</p>
<h5><strong>Pool Stick Aiming and Ball-In-Hand</strong></h5>
<p>During a scratch, the MouseMove event allows the affect of moving the q-ball for placement.&nbsp; During aiming, it allows the user to rotate the poolstick around the q-ball.</p>
<p><strong>C#</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>void</span> Page_MouseMove(<span>object</span> sender, MouseEventArgs e)</pre>
<pre><span>   2:</span> {</pre>
<pre><span>   3:</span> &nbsp;</pre>
<pre><span>   4:</span>     m_MousePoint = e.GetPosition(<span>this</span>);</pre>
<pre><span>   5:</span> &nbsp;</pre>
<pre><span>   6:</span>     <span>switch</span> (m_ActionState)</pre>
<pre><span>   7:</span>     {</pre>
<pre><span>   8:</span>         <span>case</span> m_ActionStates.Scratch:</pre>
<pre><span>   9:</span>             m_QBall.MoveAbsolute(m_MousePoint.X, m_MousePoint.Y);</pre>
<pre><span>  10:</span>             <span>break</span>;</pre>
<pre><span>  11:</span>         <span>case</span> m_ActionStates.Aiming:</pre>
<pre><span>  12:</span>             m_PoolStick.Rotate(m_MousePoint.X, m_MousePoint.Y, m_QBall.BallCenterX, m_QBall.BallCenterY);</pre>
<pre><span>  13:</span>             <span>break</span>;</pre>
<pre><span>  14:</span>     }      </pre>
<pre><span>  15:</span>     </pre>
<pre><span>  16:</span> }</pre>
</div>
</div>
<p><strong>VB</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>Private</span> <span>Sub</span> Page_MouseMove(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> MouseEventArgs)</pre>
<pre><span>   2:</span> &nbsp;</pre>
<pre><span>   3:</span>     m_MousePoint = e.GetPosition(<span>Me</span>)</pre>
<pre><span>   4:</span> &nbsp;</pre>
<pre><span>   5:</span>     <span>Select</span> <span>Case</span> m_ActionState</pre>
<pre><span>   6:</span>         <span>Case</span> m_ActionStates.Scratch</pre>
<pre><span>   7:</span>             m_QBall.MoveAbsolute(m_MousePoint.X, m_MousePoint.Y)</pre>
<pre><span>   8:</span>         <span>Case</span> m_ActionStates.Aiming</pre>
<pre><span>   9:</span>             m_PoolStick.Rotate(m_MousePoint.X, m_MousePoint.Y, m_QBall.BallCenterX, m_QBall.BallCenterY)</pre>
<pre><span>  10:</span>     <span>End</span> <span>Select</span></pre>
<pre><span>  11:</span> &nbsp;</pre>
<pre><span>  12:</span> <span>End</span> Sub</pre>
</div>
</div>
<h5><strong></strong>&nbsp;</h5>
<h5><strong>The RotateTransform Rocks</strong></h5>
<p>The Silverlight RotateTranform is very powerful in this case.&nbsp; It allows me to simply rotate the pool stick object around a center point (the center of the q-ball) using a relative angle between the mouse point and the ball.&nbsp;
</p>
<p><strong>C#</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>public</span> <span>void</span> Rotate (<span>double</span> mouseX, <span>double</span> mouseY, <span>double</span> ballX, <span>double</span> ballY)</pre>
<pre><span>   2:</span> {</pre>
<pre><span>   3:</span>     <span>double</span> vx = ballX - mouseX;</pre>
<pre><span>   4:</span>     <span>double</span> vy = ballY - mouseY;</pre>
<pre><span>   5:</span>     </pre>
<pre><span>   6:</span>     radians = Math.Atan2(vy, vx);</pre>
<pre><span>   7:</span>     <span>double</span> angle = radians * (180/Math.PI);</pre>
<pre><span>   8:</span>     </pre>
<pre><span>   9:</span>     rootCanvas.RenderTransform = <span>new</span> RotateTransform </pre>
<pre><span>  10:</span>     { </pre>
<pre><span>  11:</span>         CenterX = Model.stickBuffer, </pre>
<pre><span>  12:</span>         CenterY = Model.stickHeight/2, </pre>
<pre><span>  13:</span>         Angle = angle </pre>
<pre><span>  14:</span>     };</pre>
<pre><span>  15:</span> &nbsp;</pre>
<pre><span>  16:</span> }</pre>
</div>
</div>
<p><strong>VB</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>Public</span> <span>Sub</span> Rotate(<span>ByVal</span> mouseX <span>As</span> <span>Double</span>, <span>ByVal</span> mouseY <span>As</span> <span>Double</span>, <span>ByVal</span> ballX <span>As</span> <span>Double</span>, <span>ByVal</span> ballY <span>As</span> <span>Double</span>)</pre>
<pre><span>   2:</span>     <span>Dim</span> vx <span>As</span> <span>Double</span> = ballX - mouseX</pre>
<pre><span>   3:</span>     <span>Dim</span> vy <span>As</span> <span>Double</span> = ballY - mouseY</pre>
<pre><span>   4:</span> &nbsp;</pre>
<pre><span>   5:</span>     radians = Math.Atan2(vy, vx)</pre>
<pre><span>   6:</span>     <span>Dim</span> angle <span>As</span> <span>Double</span> = radians * (180 / Math.PI)</pre>
<pre><span>   7:</span> &nbsp;</pre>
<pre><span>   8:</span>     <span>Dim</span> transform <span>As</span> RotateTransform = <span>New</span> RotateTransform()</pre>
<pre><span>   9:</span>     transform.CenterX = Model.stickBuffer</pre>
<pre><span>  10:</span>     transform.CenterY = Model.stickHeight / 2</pre>
<pre><span>  11:</span>     transform.Angle = angle</pre>
<pre><span>  12:</span> &nbsp;</pre>
<pre><span>  13:</span>     rootCanvas.RenderTransform = transform</pre>
<pre><span>  14:</span> &nbsp;</pre>
<pre><span>  15:</span> <span>End</span> Sub</pre>
</div>
</div>
<pre><strong></strong>&nbsp;</pre>
<h5><strong>Power Control and Q-Ball Placement</strong></h5>
<p>Based on the ActionState, the mouse up and mouse down events manage user interaction during power adjustment and q-ball placement.</p>
<p><strong>C#</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>void</span> Page_MouseLeftButtonUp(<span>object</span> sender, MouseEventArgs e)</pre>
<pre><span>   2:</span> {</pre>
<pre><span>   3:</span>     <span>if</span> (<span>this</span>.m_ActionState == m_ActionStates.AdjustingPower)</pre>
<pre><span>   4:</span>     {</pre>
<pre><span>   5:</span>         m_QBall.Strike(m_PoolStick.power, m_PoolStick.radians);</pre>
<pre><span>   6:</span> &nbsp;</pre>
<pre><span>   7:</span>         m_PoolStick.StopPowerMovement();</pre>
<pre><span>   8:</span>         <span>this</span>.Children.Remove(m_PoolStick);</pre>
<pre><span>   9:</span>         <span>this</span>.m_ActionState = m_ActionStates.BallsMoving;</pre>
<pre><span>  10:</span>     }</pre>
<pre><span>  11:</span> }</pre>
<pre><span>  12:</span> &nbsp;</pre>
<pre><span>  13:</span> <span>void</span> Page_MouseLeftButtonDown(<span>object</span> sender, MouseEventArgs e)</pre>
<pre><span>  14:</span> {</pre>
<pre><span>  15:</span>     <span>switch</span> (m_ActionState)</pre>
<pre><span>  16:</span>     {</pre>
<pre><span>  17:</span>         <span>case</span> m_ActionStates.Aiming:</pre>
<pre><span>  18:</span>             m_PoolStick.StartPowerMovement();</pre>
<pre><span>  19:</span>             <span>this</span>.m_ActionState = m_ActionStates.AdjustingPower;</pre>
<pre><span>  20:</span>             <span>break</span>;</pre>
<pre><span>  21:</span>         <span>case</span> m_ActionStates.Scratch:</pre>
<pre><span>  22:</span>             ResetPoolStick();</pre>
<pre><span>  23:</span>             m_ActionState = m_ActionStates.Aiming;</pre>
<pre><span>  24:</span>             <span>break</span>;</pre>
<pre><span>  25:</span>     }</pre>
<pre><span>  26:</span> }</pre>
</div>
</div>
<p><strong>VB</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>Private</span> <span>Sub</span> Page_MouseLeftButtonUp(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> MouseEventArgs)</pre>
<pre><span>   2:</span>     <span>If</span> <span>Me</span>.m_ActionState = m_ActionStates.AdjustingPower <span>Then</span></pre>
<pre><span>   3:</span>         m_QBall.Strike(m_PoolStick.power, m_PoolStick.radians)</pre>
<pre><span>   4:</span> &nbsp;</pre>
<pre><span>   5:</span>         m_PoolStick.StopPowerMovement()</pre>
<pre><span>   6:</span>         <span>Me</span>.Children.Remove(m_PoolStick)</pre>
<pre><span>   7:</span>         <span>Me</span>.m_ActionState = m_ActionStates.BallsMoving</pre>
<pre><span>   8:</span>     <span>End</span> <span>If</span></pre>
<pre><span>   9:</span> <span>End</span> <span>Sub</span></pre>
<pre><span>  10:</span> &nbsp;</pre>
<pre><span>  11:</span> <span>Private</span> <span>Sub</span> Page_MouseLeftButtonDown(<span>ByVal</span> sender <span>As</span> <span>Object</span>, <span>ByVal</span> e <span>As</span> MouseEventArgs)</pre>
<pre><span>  12:</span>     <span>Select</span> <span>Case</span> m_ActionState</pre>
<pre><span>  13:</span>         <span>Case</span> m_ActionStates.Aiming</pre>
<pre><span>  14:</span>             m_PoolStick.StartPowerMovement()</pre>
<pre><span>  15:</span>             <span>Me</span>.m_ActionState = m_ActionStates.AdjustingPower</pre>
<pre><span>  16:</span>         <span>Case</span> m_ActionStates.Scratch</pre>
<pre><span>  17:</span>             ResetPoolStick()</pre>
<pre><span>  18:</span>             m_ActionState = m_ActionStates.Aiming</pre>
<pre><span>  19:</span>     <span>End</span> <span>Select</span></pre>
<pre><span>  20:</span> <span>End</span> Sub</pre>
</div>
</div>
<pre>&nbsp;</pre>
<h2>Game State and Control</h2>
<p>The final component to this application is the &quot;business rules&quot; behind the game.&nbsp; A game of 8-Ball is governed by the results of each player's shot.&nbsp; Whether that shot ends the game or whose shot it is next is based on what balls are sunk.&nbsp;
</p>
<p>I created another enumeration for ShotResults which defines each potential outcome: GoAgain, NextPlayer, Scratch, ScratchOnEight, PrematureEightBall, and Win.&nbsp;
</p>
<p><strong>C#</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>private</span> <span>void</span> UpdateGameState(ShotResults results)</pre>
<pre><span>   2:</span> {</pre>
<pre><span>   3:</span>     <span>string</span> resultText = <span>&quot;&quot;</span>;</pre>
<pre><span>   4:</span>     </pre>
<pre><span>   5:</span>     <span>switch</span> (results)</pre>
<pre><span>   6:</span>     {</pre>
<pre><span>   7:</span>         <span>// update game states</span></pre>
<pre><span>   8:</span>         <span>case</span> ShotResults.PrematureEightBall:</pre>
<pre><span>   9:</span>         <span>case</span> ShotResults.ScratchOnEight:</pre>
<pre><span>  10:</span>             resultText = ProcessGameEnd(<span>false</span>, results);</pre>
<pre><span>  11:</span>             m_ActionState = m_ActionStates.GameOver;</pre>
<pre><span>  12:</span>             <span>break</span>;</pre>
<pre><span>  13:</span>         <span>case</span> ShotResults.NextPlayer:</pre>
<pre><span>  14:</span>             resultText = <span>&quot;Player looses turn&quot;</span>;</pre>
<pre><span>  15:</span>             ChangeCurrentPlayer();</pre>
<pre><span>  16:</span>             ResetPoolStick();</pre>
<pre><span>  17:</span>             m_ActionState = m_ActionStates.Aiming;</pre>
<pre><span>  18:</span>             <span>break</span>;</pre>
<pre><span>  19:</span>         <span>case</span> ShotResults.GoAgain:</pre>
<pre><span>  20:</span>             resultText = <span>&quot;Nice job. Go again.&quot;</span>;</pre>
<pre><span>  21:</span>             ResetPoolStick();</pre>
<pre><span>  22:</span>             m_ActionState = m_ActionStates.Aiming;</pre>
<pre><span>  23:</span>             <span>break</span>;</pre>
<pre><span>  24:</span>         <span>case</span> ShotResults.Scratch:</pre>
<pre><span>  25:</span>             resultText = <span>&quot;Scratch. Player looses turn.&quot;</span>;</pre>
<pre><span>  26:</span>             ChangeCurrentPlayer();</pre>
<pre><span>  27:</span>             AddBall(m_QBall);</pre>
<pre><span>  28:</span>             m_ActionState = m_ActionStates.Scratch;</pre>
<pre><span>  29:</span>             <span>break</span>;</pre>
<pre><span>  30:</span>         <span>case</span> ShotResults.Win:</pre>
<pre><span>  31:</span>             resultText = ProcessGameEnd(<span>true</span>, results);</pre>
<pre><span>  32:</span>             m_ActionState = m_ActionStates.GameOver;</pre>
<pre><span>  33:</span>             <span>break</span>;</pre>
<pre><span>  34:</span>     }</pre>
<pre><span>  35:</span> &nbsp;</pre>
<pre><span>  36:</span>     sunkBalls.Clear();</pre>
<pre><span>  37:</span> &nbsp;</pre>
<pre><span>  38:</span>     <span>this</span>.Text_Status.Text = resultText;</pre>
<pre><span>  39:</span> }</pre>
</div>
</div>
<p><strong>VB</strong></p>
<div>
<div>
<pre><span>   1:</span> <span>Private</span> <span>Sub</span> UpdateGameState(<span>ByVal</span> results <span>As</span> ShotResults)</pre>
<pre><span>   2:</span>     <span>Dim</span> resultText <span>As</span> <span>String</span> = <span>&quot;&quot;</span></pre>
<pre><span>   3:</span> &nbsp;</pre>
<pre><span>   4:</span>     <span>Select</span> <span>Case</span> results</pre>
<pre><span>   5:</span>         <span>' update game states</span></pre>
<pre><span>   6:</span>         <span>Case</span> ShotResults.PrematureEightBall, ShotResults.ScratchOnEight</pre>
<pre><span>   7:</span>             resultText = ProcessGameEnd(<span>False</span>, results)</pre>
<pre><span>   8:</span>             m_ActionState = m_ActionStates.GameOver</pre>
<pre><span>   9:</span>         <span>Case</span> ShotResults.NextPlayer</pre>
<pre><span>  10:</span>             resultText = <span>&quot;Player looses turn&quot;</span></pre>
<pre><span>  11:</span>             ChangeCurrentPlayer()</pre>
<pre><span>  12:</span>             ResetPoolStick()</pre>
<pre><span>  13:</span>             m_ActionState = m_ActionStates.Aiming</pre>
<pre><span>  14:</span>         <span>Case</span> ShotResults.GoAgain</pre>
<pre><span>  15:</span>             resultText = <span>&quot;Nice job. Go again.&quot;</span></pre>
<pre><span>  16:</span>             ResetPoolStick()</pre>
<pre><span>  17:</span>             m_ActionState = m_ActionStates.Aiming</pre>
<pre><span>  18:</span>         <span>Case</span> ShotResults.Scratch</pre>
<pre><span>  19:</span>             resultText = <span>&quot;Scratch. Player looses turn.&quot;</span></pre>
<pre><span>  20:</span>             ChangeCurrentPlayer()</pre>
<pre><span>  21:</span>             AddBall(m_QBall)</pre>
<pre><span>  22:</span>             m_ActionState = m_ActionStates.Scratch</pre>
<pre><span>  23:</span>         <span>Case</span> ShotResults.Win</pre>
<pre><span>  24:</span>             resultText = ProcessGameEnd(<span>True</span>, results)</pre>
<pre><span>  25:</span>             m_ActionState = m_ActionStates.GameOver</pre>
<pre><span>  26:</span>     <span>End</span> <span>Select</span></pre>
<pre><span>  27:</span> &nbsp;</pre>
<pre><span>  28:</span>     sunkBalls.Clear()</pre>
<pre><span>  29:</span> &nbsp;</pre>
<pre><span>  30:</span>     <span>Me</span>.Text_Status.Text = resultText</pre>
<pre><span>  31:</span> <span>End</span> Sub</pre>
</div>
</div>
<h2>Conclusion</h2>
<p>This was a fun and educational exercise for me (always a good combination).&nbsp; I learned enough about graphics design to at least fear it less, especially with the use of the Expression suite.&nbsp; It also opened my perspective of Silverlight to understand how
 it will empower us to implement more rich interactive applications.&nbsp; The most interesting part for me, however, was the change in perspective I had to take in implementing an &quot;always on&quot; game.&nbsp; As simple as a game of 8-ball is, it definitely&nbsp;required an&nbsp;adjustment
 in thinking from the event-driven model of programming I'm accustomed to using in my every day work.&nbsp;
</p>
<p>If you have any questions about this solution or have suggestions for improvement, feel free to contact me at
<a href="mailto:jpetersen@claritycon.com">jpetersen@claritycon.com</a></p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Justin-Petersen/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:f3798853672545d7ae569e7600d25106">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Silverlight-8-Ball</comments>
      <itunes:summary>




In this article, I will discuss how I have built a 2 player 8-Ball game in Silverlight (play here). I will explain how I used the Expression tools
 to design the graphics and various .NET techniques to enable user control and game animation.




Justin Petersen
Coding4Fun at Clarity

Difficulty: Intermediate
Time Required: 
6-10 hours
Cost: Free
Software: Visual Studio 2008 Beta 2,
Silverlight 1.1 Alpha Refresh,
Expression Design,

Expression Blend 2 Preview 
Hardware: 
Download: Download






 
In this article, I will discuss how I have built a 2 player 8-Ball game in Silverlight (play here). I will explain how I used the Expression tools to design the graphics and various
 .NET techniques to enable user control and game animation.&amp;nbsp;  
The following components must be implemented to complete this game:  

Graphics (pool table, pool ball, and pool stick) Vector animation and collision physics User interaction&amp;nbsp; Game state and control

 
Before I continue, I&#39;d like to point out that I did not originate all of the code and XAML for this solution. I came up with the idea of creating a Silverlight 8-Ball game after stumbling upon a 2-D “bouncing bubble” animation here:
http://www.bubblemark.com/&amp;nbsp;created by Alexey Gavrilov.&amp;nbsp;
 
The original intent for this solution was to compare the performance of the bouncing bubbles across&amp;nbsp;various platforms.&amp;nbsp; I found this very useful, but was personally interested in making something fun and interactive out of it.&amp;nbsp;
 

Getting Started
Prerequisites 
The following tools were used to implement this solution:  

Visual Studio 2008 Beta 2 Silverlight 1.1 Alpha Refresh&amp;nbsp; Expression Design Expression Blend
Learning more about game development 
If you&#39;d like to learn more about game development, I found a number Coding4Fun posts&amp;nbsp;under Gaming helpful.&amp;nbsp; In particular,&amp;nbsp;the&amp;nbsp;2D Game Primer&amp;nbsp;by &amp;quot;ZMan&amp;quot; gives a good overview
 of the basics (e.g. GameLoop, Sprites, etc.) 
Grap</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Silverlight-8-Ball</link>
      <pubDate>Wed, 19 Sep 2007 21:03:50 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Silverlight-8-Ball</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/5002772_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/5002772_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Justin Petersen</dc:creator>
      <itunes:author>Justin Petersen</itunes:author>
      <slash:comments>20</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Silverlight-8-Ball/RSS</wfw:commentRss>
      <category>Gaming</category>
      <category>Web</category>
      <category>arcade</category>
      <category>web miscellaneous</category>
    </item>    
</channel>
</rss>