<?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 : games</title><link>http://blogs.msdn.com/avip/archive/tags/games/default.aspx</link><description>Tags: games</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><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>Silverlight Game Contest: $5000 prize</title><link>http://blogs.msdn.com/avip/archive/2009/02/16/silverlight-game-contest-5000-prize.aspx</link><pubDate>Mon, 16 Feb 2009 02:51:34 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9425035</guid><dc:creator>Avi Pilosof</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/avip/comments/9425035.aspx</comments><wfw:commentRss>http://blogs.msdn.com/avip/commentrss.aspx?PostID=9425035</wfw:commentRss><wfw:comment>http://blogs.msdn.com/avip/rsscomments.aspx?PostID=9425035</wfw:comment><description>&lt;p&gt;The site is a little low on details/rules, but the prize seems pretty sweet:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.serverquestcontest.com" href="http://www.serverquestcontest.com"&gt;http://www.serverquestcontest.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&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=9425035" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/avip/archive/tags/games/default.aspx">games</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>