<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Yet Another Coding Blog : silverlight</title><link>http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx</link><description>Tags: silverlight</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>MVVM – This might hurt a little…</title><link>http://blogs.msdn.com/avip/archive/2009/11/14/mvvm-this-might-hurt-a-little.aspx</link><pubDate>Fri, 13 Nov 2009 21:23:57 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9922221</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/avip/comments/9922221.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=9922221</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=9922221</wfw:comment><description>&lt;p&gt;This is an attempt at a collaborative post; I’ll fill in more data if/when people make suggestions; please add comments on more problems and other/better solutions – I’ll add the links.&lt;/p&gt;  &lt;p&gt;Overall, MVVM is very attractive – but all the screen casts I’ve seen avoid some confusing pitfalls that you’ll come up against in the real world. The landscape at the time of writing is a plethora of frameworks that attempt to solve similar problems; I expect the community will settle on a small number eventually, and certain patterns will emerge.&lt;/p&gt;  &lt;p&gt;Until then, I hope this will help.&lt;/p&gt;  &lt;h2&gt;Overall&lt;/h2&gt;  &lt;p&gt;Some things that you take for granted will seem impossible to do in MVVM (without breaking the rules). Sometimes this is due to Silverlight missing WPF features, other times it has nothing to do with that. Most of these holes are pluggable in some sense, which is why…:&lt;/p&gt;  &lt;h2&gt;Using a Framework&lt;/h2&gt;  &lt;p&gt;I recommend you use a framework. You can write your own, but please consider that it needs to handle quite a few things in order to solve the various problems in this article.&lt;/p&gt;  &lt;p&gt;I can’t recommend which framework to use because I have no experience with them, but I do recommend considering the problems below and finding out how each framework solves them. If the framework doesn’t have a “reference application”, stay away – you’re going to need one.&lt;/p&gt;  &lt;p&gt;Here are a few that I know of:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://compositewpf.codeplex.com/"&gt;PRISM2.0&lt;/a&gt;, which is from the MS Patters&amp;amp;Practices group.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://projects.nikhilk.net/SilverlightFX"&gt;SilverlightFX&lt;/a&gt;, by NikhilK. Does alot more than just MVVM; great samples/posts.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://mvvmlight.codeplex.com/"&gt;MVVM Light&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.codeplex.com/site/search?projectSearchText=mvvm&amp;amp;sortBy=Relevance"&gt;Lots of others&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Reacting to a click&lt;/h2&gt;  &lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: User clicks button; you want something to happen.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: You’re “not allowed” to use the codebehind and an event-handler, so it needs to be done in the ViewModel. However, the ViewModel is ignorant of the view, so it doesn’t know about the button’s existence – it can’t hook into the click event.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: You need support for “commanding”. Put very simply, this is usually a broadcast/listen mechanism where a “command” gets raised by someone, and someone else chooses to listen to it. In this case, the button would raise a command, and the ViewModel would be listening for it, and act.&lt;/p&gt;  &lt;p&gt;WPF has it built-in, Silverlight does not – but the various frameworks have tacked it on, and it’s a basic pillar of MVVM.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Opening a dialog&lt;/h2&gt;  &lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: You have a listbox, the user double-clicks on an element, and you want an edit dialog to pop up with that element’s data to be edited.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: You’re not allowed to have logic in your code-behind, so you can’t simply react to the event there. So you raise a command, and the ViewModel listens to it… But it’s not allowed to reference a UI component such as a dialog!&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Much as above, you use the broadcast/listen pattern… However, instead of having the ViewModel listen, you have some central app “router” listening, and it knows how to open a dialog. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Passing a value to a dialog&lt;/h2&gt;  &lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Same as above.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: You’ve raised the command, and it knows to open a dialog – but how does it know to pass in the currently selected item from the listbox?&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution 1:&lt;/strong&gt; Perhaps your framework allows that item to be set as the command argument as part of the XAML. If so, perfect. If not (or if you need something more complex):&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution 2&lt;/strong&gt;: Raise the command, but have the ViewModel listen to it instead of a central “router”. The ViewModel figures out what needs to be passed in (for example, a “CurrentlySelected” bound property on itself), and raises an appropriate command.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Closing a dialog&lt;/h2&gt;  &lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: You opened the dialog, the user made their edits and clicked “Save”, then the dialog’s ViewModel called the web service to save the changes. Now the dialog should be closed.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: The last bit of code that ran was on the dialog’s ViewModel; it can’t tell the dialog to close because it has no notion on the dialog’s existence…&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution 1&lt;/strong&gt;: Some frameworks have built-in support for dialogs and will handle this.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution 2&lt;/strong&gt;: Cheat; if you’re not a purist, try this: The ViewModel raises an event (“TimeToClose”) with an argument of success/failure. The View’s codebehind subscribes, and closes the view itself.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Animations&lt;/h2&gt;  &lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Your app shows a list of servers, and their status is all “good”. The ViewModel loads some new data, and one of the server’s changes to “bad”. The UI needs to react by playing an animation for that server.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Fundamentally, you don’t want your ViewModel to know anything about animations, storyboards, VisualStates, etc. It changed the data, but all we have on the view side of things is how to display the data; what we really want is the ability to trigger a storyboard, or to bind an element from the ViewModel to a VisualState on a framework element.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution 1&lt;/strong&gt;: You can try to cheat here by using the codebehind, but depending on your exact scenario it might not help at all.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Solution 2&lt;/strong&gt;: This article seems to do a good job of replicating DataTrigger for Silverlight (although I’ve yet to experiment with this):&lt;/p&gt;  &lt;p&gt;&lt;a title="http://blois.us/blog/2009/04/datatrigger-bindings-on-non.html" href="http://blois.us/blog/2009/04/datatrigger-bindings-on-non.html"&gt;http://blois.us/blog/2009/04/datatrigger-bindings-on-non.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Avi&lt;/p&gt;  &lt;p&gt;&lt;script type="text/javascript"&gt;addthis_pub  = 'avip';&lt;/script&gt;
&lt;a href="http://www.addthis.com/bookmark.php" onmouseover="return addthis_open(this, '', '[URL]', '[TITLE]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"&gt;&lt;img src="http://s7.addthis.com/button0-share.gif" width="83" height="16" border="0" alt="" /&gt;&lt;/a&gt;&lt;script type="text/javascript" src="http://s7.addthis.com/js/152/addthis_widget.js"&gt;&lt;/script&gt;
&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9922221" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category><category domain="http://blogs.msdn.com/avip/archive/tags/architecture/default.aspx">architecture</category><category domain="http://blogs.msdn.com/avip/archive/tags/mvvm/default.aspx">mvvm</category></item><item><title>Real-time list filtering with Silverlight, MVVM, and PagedCollectionView</title><link>http://blogs.msdn.com/avip/archive/2009/10/30/real-time-list-filtering-with-silverlight-mvvm-and-pagedcollectionview.aspx</link><pubDate>Fri, 30 Oct 2009 03:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9915091</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/avip/comments/9915091.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=9915091</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=9915091</wfw:comment><description>&lt;p&gt;The Model-View-ViewModel pattern is very good for forcing clean UI code. Ideally, you want to end up with zero code in your &lt;em&gt;.xaml.cs&lt;/em&gt; file – everything should be data-bound.&lt;/p&gt;  &lt;p&gt;As nice as this sounds, sometimes it can get so tempting to break this rule in order to do something that should be simple. Here’s one example:&lt;/p&gt;  &lt;p&gt;You have a &lt;em&gt;ListView&lt;/em&gt; and a &lt;em&gt;TextBox&lt;/em&gt; in the view; they are bound to an &lt;em&gt;ObservableCollection&lt;/em&gt; and a string in the ViewModel. You want them to behave such that entering text into that box causes the &lt;em&gt;ListView&lt;/em&gt; to filter its items:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/RealtimefilteringwithSilverlightMVVMandP_BE44/image_9.png" width="196" height="173" /&gt; &lt;/p&gt;  &lt;p&gt;The initial train of thought is like this: In the event handler for the &lt;em&gt;TextBox&lt;/em&gt;, address the &lt;em&gt;ListView&lt;/em&gt; and hide all the items that don’t match the filter. At least one problem with this is that you’ve broken your promise to keep logic in the ViewModel.&lt;/p&gt;  &lt;p&gt;The second train of thought is: Since the &lt;em&gt;TextBox&lt;/em&gt; is bound to a property on the ViewModel, add code to the property setter to remove all the items from the &lt;em&gt;ObservableCollection&lt;/em&gt; which don’t match the filter.&lt;/p&gt;  &lt;p&gt;This will “work”, and suck. The problem is that you’ve actually removed data, not filtered it. When the user changes the filter text, your collection no longer has the items you’ve removed – you need to reload them.&lt;/p&gt;  &lt;p&gt;This is where the &lt;em&gt;PagedCollectionView&lt;/em&gt; comes in. It’s a wrapper around another collection which serves the following purposes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You can bind UI elements to it, and it will work like any other collection. &lt;/li&gt;    &lt;li&gt;When wrapping a collection that implements &lt;em&gt;ICollectionChanged&lt;/em&gt;, it bubbles the notification changes. &lt;/li&gt;    &lt;li&gt;It has properties for setting filters (as well as sorting, paging, grouping). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So what you do is insert this object between your UI and your &lt;em&gt;ObservableCollection&lt;/em&gt;, and just modify the filters on it. The data remains untouched, but the UI reacts perfectly.&lt;/p&gt;  &lt;p&gt;Before:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/RealtimefilteringwithSilverlightMVVMandP_BE44/image_7.png" width="343" height="104" /&gt; &lt;/p&gt;  &lt;p&gt;After:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/RealtimefilteringwithSilverlightMVVMandP_BE44/image_8.png" width="411" height="86" /&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Here’s a simple example of the steps to take:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;1)&lt;/strong&gt; Create both the &lt;em&gt;ObservableCollection&lt;/em&gt; and the &lt;em&gt;PagedCollectionView&lt;/em&gt;, but only expose the latter as a property:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;// This is the actual container of items that we're storing&lt;/span&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; ObservableCollection&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; _RandomItemsBase;

&lt;span class="rem"&gt;// And this is the wrapper around it which we bind to. The PagedCollectionView&lt;/span&gt;
&lt;span class="rem"&gt;// allows for easy filtering, sorting, grouping.&lt;/span&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; PagedCollectionView _RandomItems;
&lt;span class="kwrd"&gt;public&lt;/span&gt; PagedCollectionView RandomItems
{
    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _RandomItems; }
    set
    {
        _RandomItems = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
        RaisePropChange(() =&amp;gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.RandomItems);
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2)&lt;/strong&gt; In the constructor, wrap the real collection with the &lt;em&gt;PagedCollectionView&lt;/em&gt;:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;_RandomItemsBase = &lt;span class="kwrd"&gt;new&lt;/span&gt; ObservableCollection&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();
RandomItems = &lt;span class="kwrd"&gt;new&lt;/span&gt; PagedCollectionView(_RandomItemsBase);&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3)&lt;/strong&gt; When the entered text changes, call a method to filter things:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; EnteredText
{
    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _EnteredText; }
    set {
        _EnteredText = &lt;span class="kwrd"&gt;value&lt;/span&gt;;
        RaisePropChange(() =&amp;gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;.EnteredText);
        UpdateFilter(); &lt;span class="rem"&gt;// Real-time filter&lt;/span&gt;
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4)&lt;/strong&gt; And here’s the code to actually apply the filter to the view:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; UpdateFilter()
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(EnteredText))
        RandomItems.Filter = &lt;span class="kwrd"&gt;null&lt;/span&gt;;
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
        RandomItems.Filter = (o) =&amp;gt; o.ToString()
                  .Contains(EnteredText);

    &lt;span class="rem"&gt;// Make sure to force a refresh of the view&lt;/span&gt;
    RandomItems.Refresh();
}&lt;/pre&gt;
&lt;style type="text/css"&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;There is one interesting thing about the above snippet. Notice the lambda expression used to filter takes one argument (“&lt;em&gt;o&lt;/em&gt;”), and I just call &lt;em&gt;ToString()&lt;/em&gt; on it. Since the &lt;em&gt;PagedCollectionView&lt;/em&gt; isn’t templated, the filter delegate is called with an argument of type &lt;em&gt;object&lt;/em&gt;. You can then cast that object to whatever type you know the underlying colleciton uses. In this case, I have an &lt;em&gt;ObservableCollection&amp;lt;&lt;strong&gt;string&lt;/strong&gt;&amp;gt;&lt;/em&gt;, so I just call the &lt;em&gt;ToString()&lt;/em&gt; method.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;That’s it. It gets even cooler when you start applying sorting, paging and grouping to this view, then bind to it with a &lt;em&gt;DataGrid&lt;/em&gt;, or something similar.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Avi&lt;/p&gt;

&lt;p&gt;&lt;script type="text/javascript"&gt;addthis_pub  = 'avip';&lt;/script&gt;
&lt;a href="http://www.addthis.com/bookmark.php" onmouseover="return addthis_open(this, '', '[URL]', '[TITLE]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"&gt;&lt;img src="http://s7.addthis.com/button0-share.gif" width="83" height="16" border="0" alt="" /&gt;&lt;/a&gt;&lt;script type="text/javascript" src="http://s7.addthis.com/js/152/addthis_widget.js"&gt;&lt;/script&gt;
&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9915091" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category><category domain="http://blogs.msdn.com/avip/archive/tags/ui/default.aspx">ui</category></item><item><title>Silverlight RPG: Steel Saga</title><link>http://blogs.msdn.com/avip/archive/2009/03/24/silverlight-rpg-steel-saga.aspx</link><pubDate>Tue, 24 Mar 2009 07:34:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9503391</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/avip/comments/9503391.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=9503391</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=9503391</wfw:comment><description>&lt;p&gt;My friend Darren who wrote the hilarious &lt;a href="http://buddyknavery.com/"&gt;Buddy Knavery&lt;/a&gt; game has released a preview of his new project called Steel Saga.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.steelsaga.com"&gt;http://www.steelsaga.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;It’s an old-style RPG written in Silverlight, and seems quite deep. At the moment there are only two “zones” (one outdoor and one dungeon), but Darren hates having a life, and is going to spend the coming weeks writing plenty more content.&lt;/p&gt;  &lt;p&gt;Check it out; I still can’t believe one guy is doing all this work (programming, art, music).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Avi&lt;/p&gt;  &lt;p&gt;&lt;script type="text/javascript"&gt;addthis_pub  = 'avip';&lt;/script&gt;
&lt;a href="http://www.addthis.com/bookmark.php" onmouseover="return addthis_open(this, '', '[URL]', '[TITLE]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"&gt;&lt;img src="http://s7.addthis.com/button0-share.gif" width="83" height="16" border="0" alt="" /&gt;&lt;/a&gt;&lt;script type="text/javascript" src="http://s7.addthis.com/js/152/addthis_widget.js"&gt;&lt;/script&gt;
&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9503391" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/games/default.aspx">games</category><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>Live Mesh Applications – whoah.</title><link>http://blogs.msdn.com/avip/archive/2009/02/17/live-mesh-applications-whoah.aspx</link><pubDate>Tue, 17 Feb 2009 01:52:02 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9426640</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/avip/comments/9426640.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=9426640</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=9426640</wfw:comment><description>&lt;p&gt;I’ve been playing with &lt;a href="http://mesh.live.com"&gt;Live Mesh&lt;/a&gt; for a long time now, and have been loving it. During this time I’d been hearing about &lt;em&gt;applications&lt;/em&gt; for Live Mesh, and while it sounded interesting in theory I didn’t really get what the point would be.&lt;/p&gt;  &lt;p&gt;Then I watched this video:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://briangorbett.com/mesh/mesh-video-player/" href="http://briangorbett.com/mesh/mesh-video-player/"&gt;http://briangorbett.com/mesh/mesh-video-player/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The video walks you through the development process of a Live Mesh app. The “whoah” moment is when I realized that the one codebase - without any special code - created an application that ran identically on the web and on the desktop. Money shot starts at about 25:30; but it helps to watch the whole vid.&lt;/p&gt;  &lt;p&gt;This is fascinating; this is a “Web OS” (I hate that term).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Avi&lt;/p&gt;  &lt;p&gt;&lt;script type="text/javascript"&gt;addthis_pub  = 'avip';&lt;/script&gt;
&lt;a href="http://www.addthis.com/bookmark.php" onmouseover="return addthis_open(this, '', '[URL]', '[TITLE]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"&gt;&lt;img src="http://s7.addthis.com/button0-share.gif" width="83" height="16" border="0" alt="" /&gt;&lt;/a&gt;&lt;script type="text/javascript" src="http://s7.addthis.com/js/152/addthis_widget.js"&gt;&lt;/script&gt;
&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9426640" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category><category domain="http://blogs.msdn.com/avip/archive/tags/programming/default.aspx">programming</category><category domain="http://blogs.msdn.com/avip/archive/tags/mesh/default.aspx">mesh</category></item><item><title>Drawing Fractal Trees - Part 3</title><link>http://blogs.msdn.com/avip/archive/2008/07/24/drawing-fractal-trees-part-3.aspx</link><pubDate>Thu, 24 Jul 2008 03:02:12 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8768098</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/avip/comments/8768098.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8768098</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8768098</wfw:comment><description>&lt;p&gt;&lt;strong&gt;The Application Itself&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Firstly, here's what we're aiming towards:&lt;/p&gt; &lt;p&gt;Live demo: &lt;a href="http://aumdmg.bay.livefilestore.com/y1pOiXwiHJm_knxiviY2rbb8hgbM5GKyYecD4NiveEhtVituHmaD00ixlYVyO6eLopmeoCx9D0MvbM/SilverTreeTestPage.html"&gt;&lt;strong&gt;Click to view live&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Download the code:&lt;br&gt;&lt;iframe style="border-right: #dde5e9 1px solid; padding-right: 0px; border-top: #dde5e9 1px solid; padding-left: 0px; padding-bottom: 0px; margin: 3px; border-left: #dde5e9 1px solid; width: 240px; padding-top: 0px; border-bottom: #dde5e9 1px solid; height: 66px; background-color: #ffffff" marginwidth="0" marginheight="0" src="http://cid-2d6b67738cd325f9.skydrive.live.com/embedrowdetail.aspx/Public/SilverTree/SilverTree.zip" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt; &lt;p&gt;Screenshot:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/DrawingFractalTreesPart3_7CC9/SilverTree_2.jpg"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="SilverTree Screenshot" src="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/DrawingFractalTreesPart3_7CC9/SilverTree_thumb_1.jpg" width="232" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Writing The Application&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Now, when I originally wrote the bones of the app it was very simple; everything fit in the single &lt;em&gt;Page.xaml.cs&lt;/em&gt; file; there's actually very little to it. Since then I've expanded it to cater for all sorts of UI niceties and expansion opportunities, so it's a little bigger (and that's what's in the ZIP above). I'll concentrate on the basics for the purposes of the blog post; you can download the full source and inspect the complexities.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Step 1: Creating the Final Command Set&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This step involves taking the Axiom and a set of rules, and using it to generate a final set of drawing commands/operations. The method below is in a class called &lt;em&gt;LSystem&lt;/em&gt;, which is also where the axiom and rules are stored:&lt;/p&gt; &lt;div&gt; &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; FinalCommandSet(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; depth)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; res = Axiom;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 1; i &amp;lt;= depth; i++)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (LSystemRule rule &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; Rules)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;             res = res.Replace(rule.From, rule.To);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; res;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Given the "depth" of recursion, we just loop through the latest string we have and apply all the rules at each step, starting with the axiom.&lt;/p&gt;
&lt;p&gt;Now that we have this string, we need to walk through it and draw the final result.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2: The Recursive Drawing Algorithm&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; DrawSegment(Canvas uiRoot, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; commandString, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; stringPos,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;                 Point curPos, &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; curAngle, &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; curLength)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     Random rnd = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Random();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i=stringPos;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; ( i &amp;lt; commandString.Length )&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;char&lt;/span&gt; c = commandString[i];&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;switch&lt;/span&gt; (c)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #006080"&gt;'['&lt;/span&gt;:&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;                 i = DrawSegment( uiRoot, commandString, i+1, curPos,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;                                 curAngle, curLength );&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #006080"&gt;']'&lt;/span&gt;:&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; i;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #006080"&gt;'F'&lt;/span&gt;:&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;                 Point newPos = FromAngleAndMagnitude(curPos, curAngle,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;                             curLength + rnd.Next(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Randomness/3));&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;                 DrawLine( uiRoot, curPos, newPos );&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;                 curPos = newPos;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #006080"&gt;'P'&lt;/span&gt;:&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ( &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.DrawPetals &amp;amp;&amp;amp; (rnd.Next(100) &amp;lt; 90) )&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;                     DrawPetal(uiRoot, &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Petal, curPos, curAngle);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #006080"&gt;'-'&lt;/span&gt;:&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;                 curAngle -= &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Angle + rnd.Next(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Randomness);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  34:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  35:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;case&lt;/span&gt; &lt;span style="color: #006080"&gt;'+'&lt;/span&gt;:&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  36:&lt;/span&gt;                 curAngle += &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Angle + rnd.Next(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Randomness);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  37:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  38:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  39:&lt;/span&gt;         i++;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  40:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  41:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  42:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; i;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  43:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;First thing to note here is that the function is meant to be called recursively. The cases for '[' and ']' (lines 11 and 16) deal with that.&lt;/p&gt;
&lt;p&gt;Next up, notice the overall loop; it's pretty much: "Step through each character of the string, act on that character, update our current pen settings (angle/position) as you go, and then move onto the next character."&lt;/p&gt;
&lt;p&gt;Notice also that the function returns the final position in the string (&lt;em&gt;i&lt;/em&gt;)that it ended up on; this is so that when you call it recursively, it reads as far as it can, then tells the caller where to continue from (see line 12).&lt;/p&gt;
&lt;p&gt;At each call to the function, we pass in these args:&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="2" width="400" border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="102"&gt;uiRoot&lt;/td&gt;
&lt;td valign="top" width="297"&gt;The canvas to which we'll be adding any drawn lines. This is the same through all recursive calls.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="102"&gt;commandString&lt;/td&gt;
&lt;td valign="top" width="297"&gt;The original/total string of commands. Stays the same through all calls.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="102"&gt;stringPos&lt;/td&gt;
&lt;td valign="top" width="297"&gt;The current position in the command string; this changes through each recursive call.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="102"&gt;curPos&lt;/td&gt;
&lt;td valign="top" width="297"&gt;The current position of the "pen" on the canvas; starts at the tree's origin, and changes with invocation of 'F'.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="102"&gt;curAngle&lt;/td&gt;
&lt;td valign="top" width="297"&gt;The current angle/heading of the "pen" on the canvas; starts at 90 degrees, and changes with invocations of '+'/'-'.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="102"&gt;curLength&lt;/td&gt;
&lt;td valign="top" width="297"&gt;The current length of a line when drawing with 'F'. This usually remains constant, but I added it in to allow for some funkier fractals that shrink with each recursion.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Drawing a Line&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Finally, drawing a single line on the canvas is a matter of adding a &lt;em&gt;Line&lt;/em&gt; shape to the canvas's &lt;em&gt;Children &lt;/em&gt;member (slow, but simple). However, we only know the current location, the direction of the line, and the length. We need to convert this to a Start/End set of points.&lt;/p&gt;
&lt;p&gt;A little trig:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; Point FromAngleAndMagnitude(Point origin,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; angle, &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; magnitude)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; radians = DegreesToRadians(angle);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Point(&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;         (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;) (magnitude * Math.Cos(radians)) + origin.X,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;) (magnitude * -Math.Sin(radians)) + origin.Y&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     );&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;And that's pretty much it. Everything else is window dressing!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Further Reading&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Here's what happens when you take this technique just a &lt;em&gt;little&lt;/em&gt; further: &lt;a title="http://www.speedtree.com/gallery/" href="http://www.speedtree.com/gallery/"&gt;http://www.speedtree.com/gallery/&lt;/a&gt; 
&lt;li&gt;Here's more info about the topic in general: &lt;a title="http://vterrain.org/Plants/" href="http://vterrain.org/Plants/"&gt;http://vterrain.org/Plants/&lt;/a&gt; 
&lt;li&gt;Here's info about using fractals to generate whole scenes (not just plants): &lt;a title="http://vterrain.org/" href="http://vterrain.org/"&gt;http://vterrain.org/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Avi&lt;/p&gt;
&lt;p&gt;&lt;!-- AddThis Button BEGIN --&gt;
&lt;a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?wt=nw&amp;pub=avip&amp;url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title), 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no,screenX=200,screenY=100,left=200,top=100'); return false;" title="Bookmark and Share" target="_blank"&gt;&lt;img src="http://s9.addthis.com/button1-share.gif" wid&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8768098" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category><category domain="http://blogs.msdn.com/avip/archive/tags/graphics/default.aspx">graphics</category></item><item><title>Turn down the ugly...</title><link>http://blogs.msdn.com/avip/archive/2008/07/23/turn-down-the-ugly.aspx</link><pubDate>Wed, 23 Jul 2008 05:42:28 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8765688</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/avip/comments/8765688.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8765688</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8765688</wfw:comment><description>&lt;p&gt;I've always struggled with making my apps look decent. In my head I can picture how it should look, but when it comes down to it, I often end up with stuff that looks like a dog's breakfast.&lt;/p&gt; &lt;p&gt;Here's the cure:&lt;/p&gt; &lt;p&gt;&lt;a title="http://blogs.msdn.com/corrinab/archive/2008/07/22/8764478.aspx" href="http://blogs.msdn.com/corrinab/archive/2008/07/22/8764478.aspx"&gt;http://blogs.msdn.com/corrinab/archive/2008/07/22/8764478.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;That post in particular helped me understand how to use Blend to turn down the ugly; but Corrina's blog in general is good for those of you who use Silverlight.&lt;/p&gt; &lt;p&gt;Lose the borders on your ListBox and your app will already look way better :)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Avi&lt;/p&gt; &lt;p&gt;&lt;!-- AddThis Button BEGIN --&gt;
&lt;a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?wt=nw&amp;pub=avip&amp;url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title), 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no,screenX=200,screenY=100,left=200,top=100'); return false;" title="Bookmark and Share" target="_blank"&gt;&lt;img src="http://s9.addthis.com/button1-share.gif" wid&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8765688" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category><category domain="http://blogs.msdn.com/avip/archive/tags/ui/default.aspx">ui</category></item><item><title>Drawing Fractal Trees - Part 2</title><link>http://blogs.msdn.com/avip/archive/2008/07/19/drawing-fractal-trees-part-2.aspx</link><pubDate>Sat, 19 Jul 2008 06:06:55 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8753241</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/avip/comments/8753241.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8753241</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8753241</wfw:comment><description>&lt;p&gt;&lt;strong&gt;L-Systems&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;We've established that drawing the tree will use the concept of self-similarity. To put this in action, we're going to use what's called an &lt;a href="http://en.wikipedia.org/wiki/L-system"&gt;L-System&lt;/a&gt;. Here's a crash-course...&lt;/p&gt;  &lt;p&gt;Firstly, we establish that we have a &amp;quot;pen&amp;quot; that at any given time has a current position and a current heading/angle. It's always touching the paper, so when it moves forward, you get a line drawn. If you ever learned &lt;a href="http://en.wikipedia.org/wiki/Turtle_graphics"&gt;LOGO&lt;/a&gt; in school, this will be familiar.&lt;/p&gt;  &lt;p&gt;Let's define a very simple set of operations. &lt;/p&gt;  &lt;table cellspacing="2" cellpadding="2" width="460" border="0"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="87"&gt;&lt;strong&gt;Operator&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="365"&gt;&lt;strong&gt;Meaning&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="88"&gt;F&lt;/td&gt;        &lt;td valign="top" width="364"&gt;Move forward by a fixed amount.&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="89"&gt;+&lt;/td&gt;        &lt;td valign="top" width="363"&gt;Turn a little to one side.&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="90"&gt;-&lt;/td&gt;        &lt;td valign="top" width="362"&gt;Turn a little to the other side.&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="91"&gt;[&lt;/td&gt;        &lt;td valign="top" width="361"&gt;Remember your current position and heading, and store in a stack for later retrieval.&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="92"&gt;]&lt;/td&gt;        &lt;td valign="top" width="360"&gt;Retrieve the previous position/heading from the stack.&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;So if we feed something like &amp;quot;F+F+F+F&amp;quot; to our pen, we'll get a square, provided the angle that &amp;quot;+&amp;quot; uses is 90 degrees.&lt;/p&gt;  &lt;p&gt;Take something a little more complex, such as &amp;quot;F[-F][+F]&amp;quot;. This will draw a Y shape; walk it through on paper and see. The key thing to connect at this point is that the &amp;quot;[&amp;quot; and &amp;quot;]&amp;quot; characters are perfectly represented by a recursive call to the same function that's doing the drawing. Save that for later.&lt;/p&gt;  &lt;p&gt;So we have our set of operators, we need one more thing: A way to generate an interesting string of operations that will draw the tree. The way we do that is by defining two things:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;A starting point; an &amp;quot;axiom&amp;quot;.&lt;/li&gt;    &lt;li&gt;A rule (or set of rules) that transform a given set of operations into a new set of operations.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;We then keep applying these rules to the resultant set of operations (starting with the axiom) as many times as we want. For example:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Axiom: F&lt;/li&gt;    &lt;li&gt;Rule: F =&amp;gt; +FF (this reads as: &amp;quot;Every time you see an 'F', replace it with '+FF'&amp;quot;)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Execution example:&lt;/p&gt;  &lt;table cellspacing="2" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="95"&gt;&lt;strong&gt;Iteration #&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="297"&gt;&lt;strong&gt;Current Set of Operations&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="95"&gt;0&lt;/td&gt;        &lt;td valign="top" width="297"&gt;F&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="95"&gt;1&lt;/td&gt;        &lt;td valign="top" width="297"&gt;+FF&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="95"&gt;2&lt;/td&gt;        &lt;td valign="top" width="297"&gt;++FF+FF&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="95"&gt;3&lt;/td&gt;        &lt;td valign="top" width="297"&gt;+++FF+FF++FF+FF&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;Feed the final string above into our &amp;quot;pen&amp;quot;, and it will draw stuff. Not a tree though; not with &lt;em&gt;that&lt;/em&gt; rule. If you want a tree, go with a rule like this:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;F =&amp;gt; FF-[-F+F+F]+[+F-F-F] &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Wait, what?! Doesn't look anything like a tree, does it? But it turns out that when you apply that rule a few times to the axiom &amp;quot;F&amp;quot;, it generates a set of operations that draws something very similar to a tree (depending on what angle you rotate with each +/-).&lt;/p&gt;  &lt;p&gt;Check it out:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/DrawingFractalTreesPart2_BC4E/tree_2.gif"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="256" alt="tree" src="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/DrawingFractalTreesPart2_BC4E/tree_thumb.gif" width="341" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;There is no randomness in this image; it's a direct drawing of the above rule (with 3-4 iterations of the rule), using a fixed distance for F and a fixed angle for +/-. Altering the distance that the pen moves with each F will make a larger/smaller tree; altering the angle can make a profound difference to the shape.&lt;/p&gt;  &lt;p&gt;There are different rules that will produce different looking plants. For more examples, see &lt;a href="http://spanky.fractint.org/www/fractint/lsys/plants.html"&gt;this page&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;To me, this is mind-blowing. That such a simple system with such basic rules and operations can generate something that looks so eerily &amp;quot;natural&amp;quot; is a little spooky. And reminds me that I had the same effect with the &lt;a title="Two lines of code make for natural parabolic flight..." href="http://blogs.msdn.com/avip/archive/2008/06/23/trivial-physics-simulations-in-silverlight-part-1.aspx"&gt;physics tutorial&lt;/a&gt;: Simple rules can make complex behaviour. I think there's some deep philosophical insight buried there.&lt;/p&gt;  &lt;p&gt;What's left to do now is take this knowledge and apply it to a Silverlight program that can allow the user to alter the parameters in real-time, introduce some randomness, and maybe a little more life to the image.&lt;/p&gt;  &lt;p&gt;Stay tuned...&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Avi&lt;/p&gt;  &lt;p&gt;&lt;!-- AddThis Button BEGIN --&gt;
&lt;a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?wt=nw&amp;pub=avip&amp;url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title), 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no,screenX=200,screenY=100,left=200,top=100'); return false;" title="Bookmark and Share" target="_blank"&gt;&lt;img src="http://s9.addthis.com/button1-share.gif" wid&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8753241" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category><category domain="http://blogs.msdn.com/avip/archive/tags/graphics/default.aspx">graphics</category></item><item><title>Drawing Fractal Trees - Part 1</title><link>http://blogs.msdn.com/avip/archive/2008/07/19/drawing-fractal-trees-part-1.aspx</link><pubDate>Sat, 19 Jul 2008 04:02:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8752564</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/avip/comments/8752564.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8752564</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8752564</wfw:comment><description>&lt;p&gt;&lt;strong&gt;Table Of Contents&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Part 1: &lt;a href="http://blogs.msdn.com/avip/archive/2008/07/24/drawing-fractal-trees-part-1.aspx"&gt;Basic fractal theory&lt;/a&gt; (this page)&lt;/li&gt; &lt;li&gt;Part 2: &lt;a href="http://blogs.msdn.com/avip/archive/2008/07/19/drawing-fractal-trees-part-2.aspx"&gt;L-Systems - drawing trees&lt;/a&gt;.&lt;/li&gt; &lt;li&gt;Part 3: &lt;a href="http://blogs.msdn.com/avip/archive/2008/07/24/drawing-fractal-trees-part-3.aspx"&gt;Implementation in Silverlight, live demo, code download&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;A Brief Explanation of Fractals&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;In plain English, a fractal is a shape whose constituent parts are really just copies (scaled down) of the whole.&amp;nbsp; Here's a simple example, the &lt;a href="http://en.wikipedia.org/wiki/Koch_curve"&gt;Koch Curve&lt;/a&gt;:&lt;/p&gt; &lt;p&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="204" alt="Koch Curve" src="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/DrawingFractalTrees_89F6/koch_thumb.gif" width="164" border="0"&gt; &lt;/p&gt; &lt;p&gt;Take a look at the first part made up of 4 line segments. Make a copy of that whole part in your head, shrink it down, and rotate it so that it fits on top of one of the line segments. Notice how that looks like the beginnings of the second part? Keep going (forever), and that's your fractal: Any little bit of it is just a scaled down copy of the rest of it. You can zoom in &lt;em&gt;infinitely&lt;/em&gt; and keep seeing the same pattern.&lt;/p&gt; &lt;p&gt;It's a very powerful concept that can generate &lt;a href="http://www.darkroastedblend.com/2008/04/most-beautiful-fractals.html"&gt;stunning images&lt;/a&gt; when taken further.&lt;/p&gt; &lt;p&gt;But what really strikes me about fractals is that they're &lt;em&gt;real&lt;/em&gt;; they're everywhere in the physical world. From &lt;a href="http://fisica.ciencias.uchile.cl/alejo/fractal_antenna/node7.html"&gt;lightning&lt;/a&gt; to &lt;a href="http://www.amazon.com/Fractal-River-Basins-Chance-Self-Organization/dp/0521004055"&gt;river networks&lt;/a&gt; to &lt;a href="http://en.wikipedia.org/wiki/Image:Fractal_Broccoli.jpg"&gt;broccoli&lt;/a&gt; to the layout of &lt;a href="http://blog.fractalspin.com/neat-stuff/fractals-are-everywhere-in-africa"&gt;African villages&lt;/a&gt;! And also, to trees, which is where we come in.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Fractals in Trees&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;If you look at the "Y" shape created by a stylised tree branch, it's identical in concept to the branch that it spawned off, which is identical to its parent branch, etc, etc, until you reach the trunk - which forms the "axiom" of this fractal.&lt;/p&gt; &lt;p&gt;This series of posts will describe a Silverlight program based on this observation that allows users to generate random fractal plants by defining an axiom, a rule to iterate over, and a set of preferences that they can tweak.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Avi&lt;/p&gt; &lt;p&gt;&lt;!-- AddThis Button BEGIN --&gt;
&lt;a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?wt=nw&amp;pub=avip&amp;url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title), 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no,screenX=200,screenY=100,left=200,top=100'); return false;" title="Bookmark and Share" target="_blank"&gt;&lt;img src="http://s9.addthis.com/button1-share.gif" wid&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8752564" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category><category domain="http://blogs.msdn.com/avip/archive/tags/graphics/default.aspx">graphics</category></item><item><title>[The Global] War On Terrier</title><link>http://blogs.msdn.com/avip/archive/2008/07/17/the-global-war-on-terrier.aspx</link><pubDate>Thu, 17 Jul 2008 04:46:09 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8741528</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/avip/comments/8741528.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8741528</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8741528</wfw:comment><description>&lt;p&gt;I mentioned in the last series of posts that I'd written a small Silverlight game for an internal competition. Well, I'm finally able to put it online, here it is:&lt;/p&gt; &lt;p&gt;&lt;a title="http://silverlight.net/samples/2b2/waronterrier/waronterriertestpage.html" href="http://silverlight.net/samples/2b2/waronterrier/waronterriertestpage.html"&gt;http://silverlight.net/samples/2b2/waronterrier/waronterriertestpage.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;It's very similar to the old Worms games (which I love!), but much simpler. The reason I used puppies? Because my colleague suggested "War On Terrier" as a name, and while "Wombat Combat" was better, it's really tough to draw a cute cartoon wombat.&lt;/p&gt; &lt;p&gt;I think that programmers in general find it difficult to share their code with others because they rarely feel it's good enough, and we're a judgmental lot. I am no exception :) But here's the code anyway:&lt;/p&gt; &lt;p&gt;&lt;a href="http://download.microsoft.com/download/d/8/4/d843c2da-ff18-4ac9-b560-98d5429a3395/WarOnTerrier.zip"&gt;Download the code&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I know it's not great code, so here come the excuses: Zero up front planning went into it; it was written in 2-3 hour bursts over the course of a few weeks; it was my first Silverlight program.&lt;/p&gt; &lt;p&gt;Now that those are out of the way, let me point out what I found difficult in writing this game:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;XAML! My god, the amount of time I spent trying to figure out why my polyline didn't fit in the grid and how to scale it to fit and scale many polylines together and why the boundaries of the canvas were so big and why the transform origin was wonky and why things move when they shouldn't and why this won't wrap, and, and... Suffice to say, my XAML-fu is very weak.  &lt;li&gt;The game is turn based, but within a given turn it will also switch to being physics based and also Silverlight animation based. This forced me to write a big state machine for the game which complicated the code alot. Basically, I had to do things like this in many places: "If we're waiting for an animation to complete, then do nothing this frame."  &lt;li&gt;Learning how to use Silverlight user controls as my game objects, and how to structure the project around that. Do I load the XAML at runtime from a resource? Do I create actual user controls for each "image" in the game?  &lt;li&gt;XAML - did I mention that?&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;That having been said, it was alot of fun getting it to work. Here's what really needs to be added to the game:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Network play. This would be way more fun if playing against other humans.  &lt;li&gt;Allowing the characters to be moved along the screen.  &lt;li&gt;More crazy weapons, different types.  &lt;li&gt;Bonuses, hazards, etc.  &lt;li&gt;Music.  &lt;li&gt;Different scenes.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I hope the code is useful to someone, and that it doesn't lead you too far astray. Feel free to do whatever you want with it; if you have any doubts or questions as to why I did something, post a comment. I'll likely answer: "Because I wasn't thinking straight at the time" :)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Avi&lt;/p&gt; &lt;p&gt;&lt;!-- AddThis Button BEGIN --&gt;
&lt;a href="http://www.addthis.com/bookmark.php" onclick="window.open('http://www.addthis.com/bookmark.php?wt=nw&amp;pub=avip&amp;url='+encodeURIComponent(location.href)+'&amp;title='+encodeURIComponent(document.title), 'addthis', 'scrollbars=yes,menubar=no,width=620,height=520,resizable=yes,toolbar=no,location=no,status=no,screenX=200,screenY=100,left=200,top=100'); return false;" title="Bookmark and Share" target="_blank"&gt;&lt;img src="http://s9.addthis.com/button1-share.gif" wid&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8741528" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/games/default.aspx">games</category><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>Trivial Physics Simulations (...in Silverlight) - Part 5</title><link>http://blogs.msdn.com/avip/archive/2008/06/24/trivial-physics-simulations-in-silverlight-part-5.aspx</link><pubDate>Tue, 24 Jun 2008 02:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8641532</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/avip/comments/8641532.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8641532</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8641532</wfw:comment><description>&lt;p&gt;&lt;strong&gt;The finished product:&lt;/strong&gt;&lt;/p&gt; &lt;p mce_keep="true"&gt;I'm having trouble finding a way to embed the SL app inside this page, so let's see if this works (c'mon, skydrive!):&lt;/p&gt; &lt;p&gt;&lt;a href="http://nzlsdw.bay.livefilestore.com/y1pKuDVf6WkkscIs3Q3snLqCmUT7Fk2zPpzVcwS1cVehaTb23YZUshQAqYV9Gmuq5PNr1Mq8xBprxznh12uOlCE5Eh9Ht3CDF_D/SkyDriveTestPage.html" target="_blank" mce_href="http://nzlsdw.bay.livefilestore.com/y1pKuDVf6WkkscIs3Q3snLqCmUT7Fk2zPpzVcwS1cVehaTb23YZUshQAqYV9Gmuq5PNr1Mq8xBprxznh12uOlCE5Eh9Ht3CDF_D/SkyDriveTestPage.html"&gt;CLICK HERE TO SEE THE APP IN ACTION.&lt;/a&gt; &lt;/p&gt; &lt;p&gt;And download the solution from here:&lt;/p&gt; &lt;p&gt;&lt;iframe style="border-right: #dde5e9 1px solid; padding-right: 0px; border-top: #dde5e9 1px solid; padding-left: 0px; padding-bottom: 0px; margin: 3px; border-left: #dde5e9 1px solid; width: 240px; padding-top: 0px; border-bottom: #dde5e9 1px solid; height: 66px; background-color: #ffffff" marginwidth="0" marginheight="0" src="http://cid-2d6b67738cd325f9.skydrive.live.com/embedrowdetail.aspx/Public/SLPhysicsDemo/SLPhysicsDemo.zip" frameborder="0" scrolling="no" mce_src="http://cid-2d6b67738cd325f9.skydrive.live.com/embedrowdetail.aspx/Public/SLPhysicsDemo/SLPhysicsDemo.zip"&gt;&lt;/iframe&gt;&lt;/p&gt; &lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Taking it Further&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Particle systems are the basis for lots of very high tech graphics effects such as fire, smoke, water, and explosions. Perhaps that's no longer the state of the art - but it used to be :) Anyway, with extra work, you can simulate the above to some degree of realism.&lt;/p&gt; &lt;p&gt;Aside from that, the physics we've created here aren't just for particles - you can use them in games for any simple physics-based motion (space ships, cars, projectiles). I say "simple" because things start to change if you want realistic physics that take into account the shape of the object and how it reacts to its environment.&lt;/p&gt; &lt;p&gt;Here are some ideas:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Direction&lt;/strong&gt;: Currently, our particles are drawn as simple circles. Let's say we wanted to upgrade them to space ships. In that case, we'd get a terrible effect where the spaceship changes direction without actually rotating - nowhere in our code do we rotate the visual based on the direction (which is a function of its velocity). This could be fixed by adding a &lt;em&gt;RenderTransform&lt;/em&gt; at the &lt;em&gt;FireworksRenderingHelper&lt;/em&gt; level.&lt;/p&gt; &lt;p&gt;If you do that, you'll be 80% of the way there, but you'll notice that as the direction of the ship changes, the rotation can "flip" suddenly, which is unnatural. The reason for this is because the code we've written simulates a body being acted upon by simple outside forces; but a spaceship actually introduces its own forces (thrust). See more below...&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Forces&lt;/strong&gt;: We haven't talked about the concept of "force", but it's at the heart of real physics. We've hard-coded the acceleration to &lt;em&gt;simulate&lt;/em&gt; gravity; but in reality, gravity applies a force, which &lt;em&gt;causes &lt;/em&gt;acceleration. If you wanted to simulate a spaceship, you'd be better off altering the acceleration based on the force created by its thrusters, rather than having a fixed acceleration.&lt;/p&gt; &lt;p&gt;Introducing forces to the animation can make the realism really jump to the next level, because you start "feeling" inertia. But keep in mind that there's no force without mass, so bust out this equation:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;F = ma&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Or for our purposes:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;a = F/m&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Where "a" is the acceleration, "F" is the force being applied, and "m" is the mass of the object being pushed. The heavier the object, the slower the acceleration.&lt;/p&gt; &lt;p&gt;Obviously, this would add to the inner loop for the particle - but the basics are the same: modify the acceleration based on the force, the velocity based on the acceleration, and the position based on the velocity.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Friction&lt;/strong&gt;: The current simulation has no mention of friction. The most obvious one is air resistance, but depending on what you're simulating, there could be others. I won't go into detail here because friction can be complex depending on the scenario; but it's essentially another force acting on the object. It can be a matter of reducing the acceleration, it could be tied to velocity, it could be tied to mass, materials, etc.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Angular Momentum&lt;/strong&gt;: Getting fancier, you might want to give particles an angular velocity (or acceleration) - rotation. Let's say you smack a cube on the corner; it's going to both move and rotate. If your particles are being rendered as anything but tiny dots, it makes sense to add a component for that. In 2D, it would probably be of type &lt;em&gt;double&lt;/em&gt;, units "degrees per second", or something like that.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Visuals&lt;/strong&gt;: This is where you can really go nuts. In my youth (on my beloved Amiga, RIP) I wrote a program which rendered animations of explosions, smoke and lightning. All used a particle system like this, but altered the way that individual particles were rendered. All used a particle whose transparency fell off near the edges - you can probably do this in SL with a &lt;em&gt;RadialGradientBrush&lt;/em&gt; - and whose colour changed over age. For example, an explosion particle went from bright orange to gray (as it turned into smoke). It actually turned out very beautiful and quite realistic (well, the 2nd version, anyway).&lt;/p&gt; &lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;As you can see, there's lots of room for improvement and creativity. If you want to get into a more detailed physics simulation, I recommend this book:&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.amazon.com/Physics-Game-Developers-David-Bourg/dp/0596000065" href="http://www.amazon.com/Physics-Game-Developers-David-Bourg/dp/0596000065" mce_href="http://www.amazon.com/Physics-Game-Developers-David-Bourg/dp/0596000065"&gt;http://www.amazon.com/Physics-Game-Developers-David-Bourg/dp/0596000065&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Once you get into collisions between oddly shaped bodies and working out how they come to rest; that's when things start getting really complex.&lt;/p&gt; &lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Avi&lt;/p&gt; &lt;p&gt;&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;script type="text/javascript"&gt;
digg_skin = 'compact';
&lt;/script&gt;
&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8641532" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/games/default.aspx">games</category><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>Trivial Physics Simulations (...in Silverlight) - Part 4</title><link>http://blogs.msdn.com/avip/archive/2008/06/24/trivial-physics-simulations-in-silverlight-part-4.aspx</link><pubDate>Tue, 24 Jun 2008 01:52:33 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8644118</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/avip/comments/8644118.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8644118</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8644118</wfw:comment><description>&lt;p&gt;Tying it all together has zip to do with the physics simulation, but there are a couple of interesting bits which I'll paste into here. The rest you can grab from the solution that I'll post up; feel free to ask questions.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;The Game Loop&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The heart of the app is a method call which renders one frame only. The trick is calling that method for each frame, and having that method do a very simple fixed set of operations that updates the particles for that frame only.&lt;/p&gt; &lt;p&gt;For the "call-each-frame" part, I use a very nice method stolen from Bill Reiss:&lt;/p&gt; &lt;p&gt;&lt;a title="http://silverlightrocks.com/community/blogs/silverlight_games_101/archive/2008/03/28/the-start-of-a-game-helper-class-library.aspx" href="http://silverlightrocks.com/community/blogs/silverlight_games_101/archive/2008/03/28/the-start-of-a-game-helper-class-library.aspx"&gt;http://silverlightrocks.com/community/blogs/silverlight_games_101/archive/2008/03/28/the-start-of-a-game-helper-class-library.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Each frame, that loop calls my method:&lt;/p&gt; &lt;div&gt; &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; _GameLoop_Update(TimeSpan elapsed)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     AddNewParticles();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     UpdatePhysics(elapsed);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     _Renderer.Render();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     RemoveDeadParticles();&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This method does the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Checks to see if we've got as many particles as the user wants us to have, and if not, adds a few more. I only add a small [random] number each frame, to avoid creating large spurts. 
&lt;li&gt;Updates the physics for all particles by calling each particle's &lt;em&gt;RunFrame&lt;/em&gt; method. Because this uses the elapsed time since the last frame, the particles maintain a correct speed on-screen, even if the frame rate drops/increases. 
&lt;li&gt;Renders the particles to the canvas. More on that soon. 
&lt;li&gt;Removes any particles that have died, to prevent the particle list from growing indefinitely.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generating Particles&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The AddNewParticles method is where you need some creativity, and is the method you would alter if you wanted to change the nature of the fireworks (say, to create an explosion effect instead of a fountain). This method relies on simple heuristics to generate initial velocities. Here's the relevant bit:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// Generate some random starting conditions for this particle&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; Vector2D vel = Vector2D.FromSpeedAndAngle(200 + &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.MaxSpeed,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     ((180 - &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.SpreadAngle) / 2) + rnd.Next(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.SpreadAngle));&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; milliseconds = 200 + rnd.Next(3000);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; radius = 2 + rnd.Next(10);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; Color color = FireworksColours[ rnd.Next(FireworksColours.Length) ];&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;It's really all in lines 2 &amp;amp; 3: The initial velocity of the particle. We use the user's UI selections as limiters to random values. The more randomness, the more "natural" things look.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rendering Particles&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In making some effort to separate the logic of the physics from the UI rendering part, I created a &lt;em&gt;FireworksRenderingHelper&lt;/em&gt; class that is given a list of &lt;em&gt;FireworksParticle&lt;/em&gt; and a &lt;em&gt;Canvas&lt;/em&gt;, and knows how to render one to the other.&lt;/p&gt;
&lt;p&gt;Pre-Silverlight, I'd reset each frame, clear the background, render all particles, and show the frame. But with Silverlight, it already has internal methods for drawing objects to the screen, buffering, etc. So what I do is add my shapes as the &lt;em&gt;Canvas&lt;/em&gt;'s children and let it draw.&lt;/p&gt;
&lt;p&gt;The catch is that I don't want to remove/add all the children each frame - it seems wasteful. This is why I added the &lt;em&gt;Custom&lt;/em&gt; field within &lt;em&gt;FireworksParticle&lt;/em&gt; - I use it to track a reference to the child of the canvas. At render time, if the field is null, I create a new Ellipse as a child and add it to the canvas. If it's not null, then I retrieve it and modify its position. Here are the loop internals ("p" is the current particle):&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; UIElement canvasChild;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (p.Custom != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     canvasChild = (UIElement)p.Custom;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     canvasChild = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Ellipse()&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;         Width = p.Radius,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;         Height = p.Radius,&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;         Fill = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; SolidColorBrush(p.GlowColor)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     };&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     p.Custom = canvasChild;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     _Canvas.Children.Add(canvasChild);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt; canvasChild.Opacity = 1-p.Opacity;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt; canvasChild.SetValue(Canvas.LeftProperty, p.Position.X);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt; canvasChild.SetValue(Canvas.TopProperty, p.Position.Y);&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Removing Dead Particles&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The one non-trivial thing about this is that you can't use a simple &lt;em&gt;foreach &lt;/em&gt;loop and remove any particles where &lt;em&gt;Alive==false&lt;/em&gt;. Doing so would be modifying the collection while enumerating it, and you'd get slapped by the runtime. Normally, you'd get around this by separating things into two steps (get the list of dead particles, then remove them individually).&lt;/p&gt;
&lt;p&gt;It seems that LINQ allows you to do this in one line, and I think it's due to the ToList() in there:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RemoveDeadParticles()&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     _Particles.Where(p =&amp;gt; !p.Alive).ToList().ForEach(p =&amp;gt; _Particles.Remove(p));&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/avip/archive/2008/06/23/trivial-physics-simulations-in-silverlight-part-5.aspx"&gt;In the final installment&lt;/a&gt;, I'll post the zipped up solution (and if I can work out how, the actual Silverlight app), and I'll explain how you can take this further.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Avi&lt;/p&gt;
&lt;p&gt;&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;script type="text/javascript"&gt;
digg_skin = 'compact';
&lt;/script&gt;
&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8644118" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/games/default.aspx">games</category><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>Trivial Physics Simulations (...in Silverlight) - Part 3</title><link>http://blogs.msdn.com/avip/archive/2008/06/24/trivial-physics-simulations-in-silverlight-part-3.aspx</link><pubDate>Mon, 23 Jun 2008 23:55:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8643733</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/avip/comments/8643733.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8643733</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8643733</wfw:comment><description>&lt;p&gt;So now that we have vectors, we need to do something with them. We're going to use the concept of a &lt;em&gt;Particle&lt;/em&gt;. This is supposed to represent a tiny object in our world that is affected by physics. For this reason, it has a position, velocity, acceleration, etc.&lt;/p&gt; &lt;p&gt;For starters, let's define the basic particle:&lt;/p&gt; &lt;div&gt; &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Particle&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; TimeSpan _Age;  &lt;span style="color: #008000"&gt;// How old is the particle right now?&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Vector2D Position { get; set; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Vector2D Velocity { get; set; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Vector2D Acceleration { get; set; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; TimeSpan MaxAge { get; set; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; Alive { get { &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; (_Age &amp;lt; MaxAge); } }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; Radius { get; set; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Particle(Vector2D pos, Vector2D vel, Vector2D acc, TimeSpan maxage, &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; radius)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;         Position = pos;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;         Velocity = vel;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;         Acceleration = acc;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         MaxAge = maxage;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         Radius = radius;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;         _Age = TimeSpan.FromMilliseconds(0);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// Iterate one frame of animation for this particle.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// &amp;lt;param name="timeSinceLastFrame"&amp;gt;How much time has passed since the last frame?&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RunFrame( TimeSpan timeSinceLastFrame )&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  28:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; secondsPassed = (timeSinceLastFrame.TotalMilliseconds / 1000.0);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  29:&lt;/span&gt;         Velocity += Acceleration * secondsPassed;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  30:&lt;/span&gt;         Position += Velocity * secondsPassed;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  31:&lt;/span&gt;         _Age += timeSinceLastFrame;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  32:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  33:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;A few things to note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It's an abstract class. Depending on your use of it, it doesn't have to be. This is actually a ready-to-go particle; it just doesn't have anything in terms of visuals attached to it. 
&lt;li&gt;Note the concept of "Age" in there (lines 3, 8 and 9). A particle lives for a while, then dies. It doesn't have to - but for most particle based simulations, you do want that. 
&lt;li&gt;The "Radius" property is supposed to indicate the size of the particle. It could be argued that this belongs in a subclass.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The only real point of interest is the &lt;em&gt;RunFrame&lt;/em&gt; method on line 26. This is the key to the whole physics simulation. Remember I said that it's down to two lines of code? Those are 29 &amp;amp; 30 - the rest is fluff. We call this method every frame, telling it how long since the last call, and it will move the given particle in the right direction by the right amount.&lt;/p&gt;
&lt;p&gt;So now that we have this abstract particle, let's use it to make something a little more specific to our fireworks demo:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; FireworksParticle : Particle&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; Custom { get; set; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Color GlowColor { get; set; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; FireworksParticle(Vector2D pos, Vector2D vel, Vector2D acc, TimeSpan maxage, &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; radius, Color color)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;         : &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;(pos, vel, acc, maxage, radius)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         GlowColor = color;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// Fade the opacity of a particle as it gets older&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; Opacity&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         get&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;         {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; pctOfLifetime = ((&lt;span style="color: #0000ff"&gt;double&lt;/span&gt;)_Age.TotalMilliseconds) / ((&lt;span style="color: #0000ff"&gt;double&lt;/span&gt;)MaxAge.TotalMilliseconds);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;             &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pctOfLifetime &amp;gt; 1)  pctOfLifetime = 1;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (pctOfLifetime &amp;lt; 0)  pctOfLifetime = 0;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  24:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; pctOfLifetime;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  25:&lt;/span&gt;         }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  26:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  27:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You'll see we're only adding two things, both tangential to the core of this topic, but we need a little bling: The particle's color and opacity - the latter being a function of its age; it dims as it grows older.&lt;/p&gt;
&lt;p&gt;Oh, and the &lt;em&gt;Custom&lt;/em&gt; property. I'll get to that later; it's totally an implementation detail and not necessarily a pretty one.&lt;/p&gt;
&lt;p&gt;So, what are we missing at this point?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We need a page to put all this on, with some UI controls for playing with variables. 
&lt;li&gt;We need some way of rendering the particles to the page (there's no drawing code above - I prefer not to put it in these classes). 
&lt;li&gt;We need to actually create particles with positions and velocities that will suggest some kind of fireworks. 
&lt;li&gt;We need code to tie it all together; the rendering, the UI, the particle generation.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Here's a screenshot of what the end result will look like:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/TrivialPhysicsSimulat.inSilverlightPart3_DCF7/Capture.gif"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="487" alt="Capture" src="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/TrivialPhysicsSimulat.inSilverlightPart3_DCF7/Capture_thumb.gif" width="496" border="0"&gt;&lt;/a&gt;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;(Yeah, no beauty contest winner - but it's effective :))&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/avip/archive/2008/06/24/trivial-physics-simulations-in-silverlight-part-4.aspx"&gt;Next up: Putting it all together&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Avi&lt;/p&gt;
&lt;p&gt;&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;script type="text/javascript"&gt;
digg_skin = 'compact';
&lt;/script&gt;
&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8643733" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/games/default.aspx">games</category><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>Trivial Physics Simulations (...in Silverlight) - Part 2</title><link>http://blogs.msdn.com/avip/archive/2008/06/23/trivial-physics-simulations-in-silverlight-part-2.aspx</link><pubDate>Mon, 23 Jun 2008 04:26:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8640712</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/avip/comments/8640712.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8640712</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8640712</wfw:comment><description>&lt;p&gt;If you know how vectors work, this isn't going to be interesting. If you've never seen one before, I'll try to keep it simple. Keep in mind that throughout this post I'm talking in 2 dimensions. The same stuff applies for 3D work; you'd just add another variable (the Z component) to the vectors.&lt;/p&gt; &lt;p&gt;A 2D vector stores two numbers which can be used to describe the position of an object (X, Y), or the velocity (X = the speed along the X axis, Y = the speed along the Y axis).&lt;/p&gt; &lt;p&gt;So take for example an object that's traveling at a speed of 10 pixels per second directly northeast:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/TrivialPhysicsSimulationsPart2_8F91/velocity.gif"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="196" alt="velocity" src="http://blogs.msdn.com/blogfiles/avip/WindowsLiveWriter/TrivialPhysicsSimulationsPart2_8F91/velocity_thumb.gif" width="244" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The red line (marked "v") is the actual velocity (10 pixels per second), while the dotted blue lines indicate the speed along the x-axis (vx) and the y-axis (vy). Essentially, we've "decomposed" the one diagonal line into one horizontal and one vertical. For now, we're going to leave the details at that.&lt;/p&gt; &lt;p&gt;At the very least, here's what a &lt;em&gt;Vector2D&lt;/em&gt; needs to know how to do:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Store the X/Y components  &lt;li&gt;Add two Vectors to each other (eg; add acceleration to velocity)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So here's the code:&lt;/p&gt; &lt;div&gt; &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Vector2D&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; X { get; set; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; Y { get; set; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Vector2D(&lt;span style="color: #0000ff"&gt;double&lt;/span&gt; x, &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; y)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;         X = x;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;         Y = y;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// Add two vectors and return the resultant vector&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;     &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Vector2D &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt; +(Vector2D v1, Vector2D v2)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Vector2D(v1.X + v2.X, v1.Y + v2.Y);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;At this point, we can do stuff like this:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; Vector2D acceleration = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Vector2D(0, 10);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; Vector2D velocity = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Vector2D(50, -50);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; velocity += acceleration;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;That's probably sufficient to write the engine, but there are a few other features we'll want which will make the eventual code cleaner. Specifically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scale the vector by a fixed amount. 
&lt;li&gt;Generate a vector given an angle and a speed.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Why do we want that second one? Well, let's say you want to write code to generate the vector in the hand-drawn scribble above. What values do you give for &lt;em&gt;vx&lt;/em&gt; and &lt;em&gt;vy&lt;/em&gt; in order to generate the speed of 10 pixels per second in the northeast direction? You'd actually need to calculate them using some trigonometry, and that's some ugly code to have to read at a high level; so we bury it in the Vector class.&lt;/p&gt;
&lt;p&gt;Eventually, we want to be able to do this:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// Init from a speed (10 pixels per second) and an angle (45 degrees)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; Vector2D velocity = Vector2D.FromSpeedAndAngle( 10, 45 );&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And here are the methods we want to add to the above class:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// Scale the vector by the given amount (ie; multiply by a scalar)&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Vector2D &lt;span style="color: #0000ff"&gt;operator&lt;/span&gt; *(Vector2D v1, &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; scale)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Vector2D(v1.X * scale, v1.Y * scale);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// Convert the given angle (in degrees) to a vector with origin&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// (0,0) and length == speed, breaking down into the X/Y components.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt; &lt;span style="color: #008000"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; Vector2D FromSpeedAndAngle(&lt;span style="color: #0000ff"&gt;double&lt;/span&gt; speed, &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; degrees)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; radians = Vector2D.DegreesToRadians(degrees);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Vector2D(Math.Cos(radians), -Math.Sin(radians)) * speed;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt; }&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; DegreesToRadians(&lt;span style="color: #0000ff"&gt;double&lt;/span&gt; angle)&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; angle * (Math.PI / 180);&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;For now, we're done with the &lt;em&gt;Vector2D&lt;/em&gt; class. As I promised, it's quite trivial. We might add a couple of helpers here and there if we need them, but they will be obvious.&lt;/p&gt;
&lt;p&gt;The key thing to remember about &lt;em&gt;Vector2D&lt;/em&gt; is that it inherently stores &lt;em&gt;both the magnitude and direction&lt;/em&gt; of the motion. So not only will it tell us the direction something is going in, but how fast it's doing it. This allows us to use it interchangeably for velocity/acceleration/position, and have everything "Just Work".&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/avip/archive/2008/06/24/trivial-physics-simulations-in-silverlight-part-3.aspx"&gt;Next up: The Particle class&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Avi&lt;/p&gt;
&lt;p&gt;&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;script type="text/javascript"&gt;
digg_skin = 'compact';
&lt;/script&gt;
&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8640712" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/games/default.aspx">games</category><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>Trivial Physics Simulations (...in Silverlight) - Part 1</title><link>http://blogs.msdn.com/avip/archive/2008/06/23/trivial-physics-simulations-in-silverlight-part-1.aspx</link><pubDate>Mon, 23 Jun 2008 03:34:39 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8640555</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/avip/comments/8640555.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8640555</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8640555</wfw:comment><description>&lt;p&gt;&lt;strong&gt;Table of Contents:&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://blogs.msdn.com/avip/archive/2008/06/23/trivial-physics-simulations-in-silverlight-part-1.aspx"&gt;Part 1: Introduction to simple physics and vectors.&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/avip/archive/2008/06/23/trivial-physics-simulations-in-silverlight-part-2.aspx"&gt;Part 2: Details of the Vector2D class.&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/avip/archive/2008/06/24/trivial-physics-simulations-in-silverlight-part-3.aspx"&gt;Part 3: The Particle class and basic physics-based motion.&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/avip/archive/2008/06/24/trivial-physics-simulations-in-silverlight-part-4.aspx"&gt;Part 4: Tying it all together.&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blogs.msdn.com/avip/archive/2008/06/23/trivial-physics-simulations-in-silverlight-part-5.aspx" target="_blank"&gt;Part 5: The finished product, and "what next...?"&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;I recently wrote a small Silverlight game for an internal competition and a friend asked me how I did the projectile trajectories. Turns out that something which looks cool in practice is one of the simplest algorithms of all time (two lines of code!), and which I guarantee you learned in highschool science class; although they didn't call it an "algorithm", they called it a "formula". The cool thing is that it can be used to generate fairly complex visuals, by adding just a little extra spice.&lt;/p&gt; &lt;p&gt;I'm going to write up a short series demonstrating how to simulate fireworks in Silverlight using a very basic physics engine. At the end, we should have a nice interactive simulation to play with.&lt;/p&gt; &lt;p&gt;To start off, let me get back to the basic &lt;a title="The equations of linear motion" href="http://en.wikipedia.org/wiki/Equations_of_motion"&gt;physics equation&lt;/a&gt; which underlies this whole thing:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;v = u + at&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;To paraphrase this: "The velocity (v) a after some time (t) will equal the initial velocity (u), plus the acceleration (a) multiplied by the time (t)." Alternatively, to really get to the heart of the matter:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;"Acceleration makes things go faster [or slower!] over time."&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now let's look at the units of measurement:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Time: seconds  &lt;li&gt;Acceleration: pixels per second per second  &lt;li&gt;Velocity: pixels per second  &lt;li&gt;Distance: pixels&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I think Newton may have been using the outmoded "meters" rather than pixels when he came up with this stuff; but it won't matter as long as the unit is consistent throughout.&lt;/p&gt; &lt;p&gt;Now, when you think about those units of measurement above, you notice that acceleration is just a measure of how velocity changes, and velocity is just a measure of how distance changes. So the whole physics simulation, at its core, is this set of two lines: &lt;/p&gt; &lt;div&gt; &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; ( &lt;span style="color: #0000ff"&gt;true&lt;/span&gt; )&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;     position += velocity;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     velocity += acceleration;&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; }&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In other words:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"Every frame, the position of the object changes based on its velocity, and the velocity changes based on the acceleration."&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Run the contents of that loop for each frame, and you have yourself a simple physics simulation.&lt;/p&gt;
&lt;p&gt;One big thing that seems to be missing above is the direction of motion. It actually isn't missing - It's hidden in the type of those variables:&lt;/p&gt;
&lt;div&gt;
&lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; Vector2D acceleration = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Vector2D( 0, 10 );&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; Vector2D velocity = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Vector2D( 50, -50 );&lt;/pre&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; Vector2D position = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Vector2D( 0, 0 );&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;What's a &lt;em&gt;Vector2D&lt;/em&gt;? It's a custom class that stores both a X component [of motion] and a Y component, and knows how to add/subtract them. Turns out that the WPF &lt;em&gt;Vector&lt;/em&gt; class was taken out of Silverlight, so we need to write our own. Also turns out that this is trivial.&lt;/p&gt;
&lt;p&gt;With this simple algorithm, by merely changing the initial velocity, you can simulate lots of simple phenomena:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A ballistic trajectory, by giving a high initial velocity in the direction the gun is pointed. 
&lt;li&gt;An explosion, by creating lots of fragments that have large initial velocities radiating in a rough circle from an origin. 
&lt;li&gt;A fountain, by continuously creating particles that radiate roughly upwards from a single point.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Stay tuned... &lt;a href="http://blogs.msdn.com/avip/archive/2008/06/23/trivial-physics-simulations-in-silverlight-part-2.aspx"&gt;Next up; the Vector2D class&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Avi&lt;/p&gt;
&lt;p&gt;&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;script type="text/javascript" src="http://www.reddit.com/button.js?t=1"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;script type="text/javascript"&gt;
digg_skin = 'compact';
&lt;/script&gt;
&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8640555" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/games/default.aspx">games</category><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>Buddy Knavery - The Killer Riffs</title><link>http://blogs.msdn.com/avip/archive/2008/06/13/buddy-knavery-the-killer-riffs.aspx</link><pubDate>Fri, 13 Jun 2008 00:21:03 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8593674</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/avip/comments/8593674.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=8593674</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=8593674</wfw:comment><description>&lt;p&gt;Some Silverlight goodness. My friend Darren wrote this amazing game that has strong ties to those 90's adventure games that I miss; Kings|Space|Police Quest, Leisure Suit Larry, etc. Writing a game engine is one thing, but doing all the artwork &amp;amp; scripting while holding down a full time job (at MS, no less) is quite impressive.&lt;/p&gt; &lt;p&gt;Check it out:&lt;/p&gt; &lt;p&gt;&lt;a title="Buddy Knavery" href="http://www.buddyknavery.com/"&gt;http://www.buddyknavery.com/&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8593674" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/games/default.aspx">games</category><category domain="http://blogs.msdn.com/avip/archive/tags/silverlight/default.aspx">silverlight</category></item></channel></rss>