tag:blogger.com,1999:blog-75535954388460632192024-03-05T04:42:36.734+00:00Randomchaos: Graphics Adventures with XNACharles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-7553595438846063219.post-29728353804754025462013-02-21T11:04:00.001+00:002013-02-21T11:04:00.700+00:008 Week Game Competition–Voting is Open!<p>So, as I mentioned in my post at Xmas, I have entered 8 Week Game’s 3rd competition, it’s been great fun to write my entry, <a href="http://www.randomchaos.co.uk/8weekgame/roadrumble/publish.htm">Road Rumble</a>. Now all the entries are in and you, the public can play them all and decide which one you thought was the best game out of all the entries.</p> <p>You can download and play Road Rumble <a href="http://www.randomchaos.co.uk/8weekgame/roadrumble/publish.htm">here</a>, regardless of voting on the competition I would love to hear what you think of it, please post your comments here, or on the 8 Week Game blog or FaceBook page.</p> <p>So, if you want to get all the games (and I am sure you do) then head over to the 8 Week Game blog <a href="http://garfbradazweb.wordpress.com/2013/02/11/8weekgame-voting-is-open/">here</a>.</p> <p>After that, once you have played all the games, then please vote for the one you liked the most, you can do that <a href="http://www.facebook.com/questions/468399223227403/">here</a>.</p> <p>I do hope you like all the entries, and give us all constructive feed back. I am a bit late with this post, been quite busy, but hope it’s not too late for you to enjoy the games :)</p> Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com0tag:blogger.com,1999:blog-7553595438846063219.post-26120727650284098562012-12-24T10:39:00.001+00:002012-12-24T10:39:23.508+00:00Merry Xmas 2012 & a Happy New Year!<p>Just wanted to drop you all a note with some festive cheer, also so you know I have not totally dropped off the grid. I seem to go through times when I just stop posting, then Ill go mad again and put a load of stuff out, I guess it’s all down to the ebb and flow of my life. At the moment I have been evolved in the <a href="http://www.facebook.com/events/165946213543847/">3rd 8 Week Game Competition</a> and I’m having a load of fun creating my game for it called Road Rumble. I have posted a few vids of progress, you can see my first few weeks here:</p> <h1>Week 1</h1> <div style="padding-bottom: 0px; padding-left: 0px; width: 425px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:53357c8b-5919-4e32-8c25-305d27c17a37:10e3456d-1b39-49de-b391-cbd4783f9104" class="wlWriterEditableSmartContent"><embed src="http://www.youtube.com/v/fZ-1S9xDhPM" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></div> <p>This is my first weeks progress writing a game for the 8 Week Game competition. This is there 3rd competition, but my first time entering.</p> <p>I thought with the time span,a 2D game would be nice and quick to do, so that's what I have gone with. I have used Farseer for the physics & collision detection, also in their samples I have taken there 2D camera too :S</p> <h1>Week 2</h1> <div style="padding-bottom: 0px; padding-left: 0px; width: 425px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:53357c8b-5919-4e32-8c25-305d27c17a37:7e9e112a-69cf-42af-ba0f-b006f37ed75b" class="wlWriterEditableSmartContent"><embed src="http://www.youtube.com/v/5N0lKaCsi1Y" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></div> <p>This is my second weeks development update, as you can see now have a bit of a HUD, fuel and damage, some explosions and a particle system.</p> <h1>Week 3 (rushed as it’s Xmas)</h1> <div style="padding-bottom: 0px; padding-left: 0px; width: 425px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:53357c8b-5919-4e32-8c25-305d27c17a37:c0a22221-ef8f-44ee-b121-01889a128632" class="wlWriterEditableSmartContent"><embed src="http://www.youtube.com/v/WqENmyugc0o" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></div> <p>So, this is my third week update, it's a bit rushed as it's not really a full third weeks work, I put it up quick so I had something to show for the third week seeing as it was Xmas I really didn't think I would get anything done that holiday week.</p> <p>So we have a better HUD and some more explosive stuff :D Oh, and a crappy story line I knocked up in about 5 minutes, was at the time of the Mayan Apocalypse so made sense to me at the time :P</p> <p>Music sourced from here : <a href="http://rizm.ikaduchi.com">rizm.ikaduchi.com</a></p> <p>So, merry Xmas one and all, hope you have a great new year too, stay tuned, you never know I may just post some more stuff :D</p> <p>Regards,</p> <blockquote> <p>Charles.</p></blockquote> Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com0tag:blogger.com,1999:blog-7553595438846063219.post-84019724055018401202012-11-16T09:40:00.001+00:002012-11-16T09:40:03.450+00:00“Power Up” MS Windows8 Competition<p>Have you heard about the competition that MS has launched called <strong><a href="http://blogs.msdn.com/b/xna/archive/2012/11/13/win-the-opportunity-to-be-mentored-by-ian-livingstone-obe-and-any-payne-obe-along-with-a-month-s-free-pr-support-with-microsoft-s-power-up-competition.aspx">Power Up</a></strong>?</p> <p>The idea is to take your existing XNA games and using <a href="http://monogame.codeplex.com/">MonoGame</a> port them to the Windows 8 platform, now this is a pretty awesome thing to do in it’s self, but that coupled with the fantastic prizes on offer and I think you just have to have a go.</p> <p>For example, one of the prizes is to have the legendary <a href="https://twitter.com/ian_livingstone">Ian Livingstone</a> (if you don’t know who he is, then you need to hang your head in shame :P) mentor you!! </p> <p>I’m in the process of porting my <a href="http://code.google.com/p/illuminati-engine-xna/">open source</a> engine to MonoGame, and hope to have something up and running in time to enter, time as ever, will tell. </p> <p>You don’t have masses of time to get in on this, as entries close on the 14th of December, so get cracking and porting those XNA gems :D</p> Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com0tag:blogger.com,1999:blog-7553595438846063219.post-69642074342463573762012-10-20T14:00:00.001+01:002012-10-22T19:48:23.526+01:00Illuminati Engine – Open source<a href="http://lh4.ggpht.com/-xBb_7GnU5ig/UIKgJC0VSjI/AAAAAAAABcE/viXawQeTndY/s1600-h/EngineUpdate%25255B4%25255D.jpg"><img alt="EngineUpdate" border="0" height="102" src="http://lh3.ggpht.com/-AhXd4nQyCgM/UIKgJ1jtr2I/AAAAAAAABcI/_RAdPKCxDHQ/EngineUpdate_thumb%25255B1%25255D.jpg?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="EngineUpdate" width="516" /></a><br />
So, I have decided to make me engine open source, so pretty much everything I have learnt and forgot about XNA is in this engine, there are a few things in there that don’t quite work, some stuff in there I am still experimenting with, and some stuff that does work.<br />
So far I have added a few samples using the engine, from a simple template solution to skinned animation and instanced models.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJXI1r6EYoXiHnp327jGST2IGj6c2kJZV8nE3Vw_6PvOXQl0ly1w-a2oMCsgR6bZYhgGPVu2ruJgKlQX6LK76P6Sk2ZBntEO3zTKXDr-NTrKa3_yblsYg1lVto0t1J3cabzd5HrzddEjWt/s1600-h/BasicTerrain%25255B2%25255D.jpg"><img alt="BasicTerrain" border="0" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJKPbMLt_qapj0Y3zraov4ZbYRopoyS3YY4EkRQLPh1rRRu0weORdX13eRFhzK-ehmBV4qQ8MXgJbMEztyL_OeCPUBZTAnHV16TEtnMnS0e68BtrjQ4CMaawfKp-gfOo30acv9NkENjbnt/?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="BasicTerrain" width="244" /></a><a href="http://lh5.ggpht.com/-1mwayvUhbrk/UIKgM7dziwI/AAAAAAAABck/96axF_rbk4k/s1600-h/IlluminatiGameTemplate%25255B2%25255D.jpg"><img alt="IlluminatiGameTemplate" border="0" height="191" src="http://lh5.ggpht.com/-pCZGZYvOCTE/UIKgN7o_hwI/AAAAAAAABco/PJbjvY3isxI/IlluminatiGameTemplate_thumb.jpg?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="IlluminatiGameTemplate" width="244" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGmxh89JZGqFsDQ6T-WSdyban7mr5iLD_X8tJv7UPSZCaVKhdCV2JE30trDalxSdkyzqmVvkTb6KXTspsKyTcxeKfJQ1NV5Jfk1TY8QxX072zdzeqRf2KNIRWi4DoZjlX92yAPDn_67gfi/s1600-h/SkinnedMeshInstancedSample%25255B2%25255D.jpg"><img alt="SkinnedMeshInstancedSample" border="0" height="192" src="http://lh5.ggpht.com/-H4a08nCStAc/UIKgQmSU0HI/AAAAAAAABc8/AL6cCsNWhZ4/SkinnedMeshInstancedSample_thumb.jpg?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="SkinnedMeshInstancedSample" width="244" /></a><a href="http://lh6.ggpht.com/-Vcr8H_yI7f8/UIKgSJW36FI/AAAAAAAABdE/4Q3yZ5hJaQw/s1600-h/SkinnedMeshSample%25255B2%25255D.jpg"><img alt="SkinnedMeshSample" border="0" height="191" src="http://lh4.ggpht.com/-qAH-yXxDf6I/UIKgTHLtnhI/AAAAAAAABdI/IL8noJ0qD6E/SkinnedMeshSample_thumb.jpg?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="SkinnedMeshSample" width="244" /></a><a href="http://lh5.ggpht.com/-T3B5-CMfpiA/UIKgUlgwpHI/AAAAAAAABdU/lKB2gdK_Gyc/s1600-h/TerrainWithWater%25255B2%25255D.jpg"><img alt="TerrainWithWater" border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9CskQS0sggO4FqZxXagVAIK39BRCDwuyZ0lkUUoBsK9VBOqdUrw1jN0qL2RuBV4nUFLPWbZaV2VwpJb2OMRGsuBynD-0Wjpo94kIwHum0LyVR230wtndFxMtzq_6VX6hSnPyyGR8NpVFW/?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="TerrainWithWater" width="244" /></a><br />
Anyway, please feel free to use this engine how ever you like, be it to educate others, to teach your self, or even to write a game, just where ever you use it, please credit both me and Mark Neale (Mark did the physics stuff as well as other bits) in your work.<br />
Hope you find it useful.<br />
<a href="http://code.google.com/p/illuminati-engine-xna/">Illuminati Engine XNA</a>Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com3tag:blogger.com,1999:blog-7553595438846063219.post-54747210329070991592012-09-21T20:01:00.001+01:002012-09-21T20:01:03.075+01:00Killer Core–Reloaded<div style="padding-bottom: 0px; padding-left: 0px; width: 425px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:53357c8b-5919-4e32-8c25-305d27c17a37:10f996df-f0e3-4b47-ae47-692f7656535c" class="wlWriterEditableSmartContent"><embed src="http://www.youtube.com/v/uPpOkA-bu6c" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></div> <p>So, I have been quiet for a bit, and this is why, Killer Core. Way back when I was first getting into XNA I started this game, based on an old classic ZX Spectrum game called Starquake and I loved that old game.</p> <p>I have to say a big thanks to Mark Neale as he has taken on the mantle of Physic programmer on this project and without his input, I/we would be no where near this stage.</p> <p>We are still a long, long way off making this a game, but I just wanted to post what we are up to and where we are with it. I just hope this time around the game gets finished :)</p> Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com2tag:blogger.com,1999:blog-7553595438846063219.post-91105247281503221442012-07-31T01:04:00.000+01:002012-07-31T15:08:19.220+01:00A 2D Particle System<div style="padding-bottom: 0px; padding-left: 0px; width: 425px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:53357c8b-5919-4e32-8c25-305d27c17a37:a724b0ec-83c7-494a-a944-692c4ad9fbcb" class="wlWriterEditableSmartContent"><embed src="http://www.youtube.com/v/4sbIbKvQpVM" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"></embed></div> <p>So, <a href="https://twitter.com/DaveVoyles">Dave</a> was having some issue with creating a particle system for his game, so thought I could come up with a game specific particle system. I say game specific, because it is just that, the system is usable for the game I/you write it for, it’s not going to sit in an engine and be used, though you could with a few tweaks.</p> <p>In fact, there are a tone of optimizations you could do with this, but for this sample it does enough.</p> <p>My idea was, to have an emitter manager that was a registered game service, this service could then be accessed by all your game components and each component could call and place emitters as and when they want/need them. Also, you could have emitters call other emitters if you need to, in the sample, you will see I have done this for the explosions, first an explosion emitter is called and when it is halfway through it’s cycle, it calls a smoke bomb emitter.</p> <p>You may notice, this sample has a bit more than the emitter code in it, I got a bit carried away and almost wrote a game using it lol, if you like feel free to finish off :)</p> <h2>ParticleEmitterService</h2> <p>First thing we will look at is the emitter service, it is derived from the DrawableGameComponent that is intrinsic to XNA, it has two lists of IParticleEmitter, this is an interface I have created to describe a particle emitter, using this interface means you can write a totally new emitter and as long as it implements this interface, the emitter service can use it. The first list is the current list of emitters in use, I then have another list that is for emitters that are being created while we are in the Update loop, we can’t action these until we are out off the loop, so I put them in a queue to be added later.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:6c4aae9b-a666-45c7-a8e4-f3e667ccb1a3" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">    <span style="color:#0000ff">public</span> <span style="color:#0000ff">class</span> <span style="color:#2b91af">ParticleEmitterService</span> : <span style="color:#2b91af">DrawableGameComponent</span><br>     {<br>         <span style="color:#0000ff">public</span> <span style="color:#2b91af">List</span><<span style="color:#2b91af">IParticleEmitter</span>> Emitters = <span style="color:#0000ff">new</span> <span style="color:#2b91af">List</span><<span style="color:#2b91af">IParticleEmitter</span>>();<br>         <span style="color:#2b91af">List</span><<span style="color:#2b91af">IParticleEmitter</span>> emitterQue = <span style="color:#0000ff">new</span> <span style="color:#2b91af">List</span><<span style="color:#2b91af">IParticleEmitter</span>>();<br> <br>         <span style="color:#0000ff">bool</span> Updating = <span style="color:#0000ff">false</span>;</div> </div> </div> <p>We then have the constructor (ctor) for the class, and in here I get it to register it’s self as a service with the Game instance and add it’s self to the Game.Components.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:440ca339-d532-4a49-b6ca-9f9911328593" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> ParticleEmitterService(<span style="color:#2b91af">Game</span> game)<br>             : <span style="color:#0000ff">base</span>(game)<br>         {<br>             <span style="color:#008000">// Automaticaly register myself as a service</span><br>             game.Services.AddService(<span style="color:#0000ff">this</span>.GetType(),<span style="color:#0000ff">this</span>);<br> <br>             <span style="color:#008000">// Put myself in the component list</span><br>             game.Components.Add(<span style="color:#0000ff">this</span>);<br>         }</div> </div> </div> <p>I then have an add emitter method so that game entities can invoke an emitter, as you will see this method checks if we are in the update method and if we are adds the new emitter to the queue. I created an enum so you could just say what pre baked emitter you want, you could just pass the emitter instance in rather than do it this way, but for this sample this makes it a bit simpler.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:9bc83bc2-b403-45b5-bba4-ac57138b598d" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">void</span> AddEmitter(<span style="color:#2b91af">EmitterType</span> emitterType, <span style="color:#2b91af">Vector2</span> position, <span style="color:#2b91af">IGameEntity</span> entity = <span style="color:#0000ff">null</span>, <span style="color:#2b91af">Vector2</span>? entityOffset = <span style="color:#0000ff">null</span>)<br>         {<br>             <span style="color:#2b91af">IParticleEmitter</span> emitter = <span style="color:#0000ff">null</span>;<br> <br>             <span style="color:#0000ff">if</span> (entityOffset == <span style="color:#0000ff">null</span>)<br>                 entityOffset = <span style="color:#2b91af">Vector2</span>.Zero;<br> <br>             <span style="color:#0000ff">bool</span> added = <span style="color:#0000ff">false</span>;<br>             <span style="color:#0000ff">switch</span> (emitterType)<br>             {<br>                 <span style="color:#0000ff">case</span> <span style="color:#2b91af">EmitterType</span>.Explosion:<br>                     emitter = <span style="color:#0000ff">new</span> <span style="color:#2b91af">ExplosionEmitter</span>(Game) { Position = position, GameEntity = entity, EnityOffset = entityOffset.Value, Alive = <span style="color:#0000ff">true</span> };<br>                     added = <span style="color:#0000ff">true</span>;<br>                     <span style="color:#0000ff">break</span>;<br>                 <span style="color:#0000ff">case</span> <span style="color:#2b91af">EmitterType</span>.Fire:<br>                     <span style="color:#0000ff">break</span>;<br>                 <span style="color:#0000ff">case</span> <span style="color:#2b91af">EmitterType</span>.SmokeBomb:<br>                     emitter = <span style="color:#0000ff">new</span> <span style="color:#2b91af">SmokeBombEmitter</span>(Game) { Position = position, GameEntity = entity, EnityOffset = entityOffset.Value, Alive = <span style="color:#0000ff">true</span> };<br>                     added = <span style="color:#0000ff">true</span>;<br>                     <span style="color:#0000ff">break</span>;<br>                 <span style="color:#0000ff">case</span> <span style="color:#2b91af">EmitterType</span>.SmokeTail:<br>                     emitter = <span style="color:#0000ff">new</span> <span style="color:#2b91af">SmokeTrailEmitter</span>(Game) { Position = position, GameEntity = entity, EnityOffset = entityOffset.Value, Alive = <span style="color:#0000ff">true</span> };<br>                     added = <span style="color:#0000ff">true</span>;<br>                     <span style="color:#0000ff">break</span>;<br>             }<br> <br>             <span style="color:#0000ff">if</span>(added)<br>                 emitter.Initialize();<br> <br>             <span style="color:#0000ff">if</span> (Updating)<br>                 emitterQue.Add(emitter);<br>             <span style="color:#0000ff">else</span><br>                 Emitters.Add(emitter);<br>         }</div> </div> </div> <p>In our update method we check to see if we have any emitters in the queue, and if we do, we merge them with the main emitter list and clear the queue out. Then set the Updating flag to true, so if any are added while we are in here they are added to the queue. Then we go through our list, and call there Update methods, and if they are no longer alive, add them to the list to be removed from the emitter list. Then loop through and remove the emitters that are no no longer alive and call there Die method, in some emitters, you may want to do some other stuff once the emitter has completed. We the set the Updating flag to false.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:2a837742-a84a-4523-a111-6e9709d5e17b" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> Update(<span style="color:#2b91af">GameTime</span> gameTime)<br>         {<br>             <span style="color:#2b91af">List</span><<span style="color:#2b91af">IParticleEmitter</span>> removeList = <span style="color:#0000ff">new</span> <span style="color:#2b91af">List</span><<span style="color:#2b91af">IParticleEmitter</span>>();<br> <br>             <span style="color:#008000">// Update from que if need be.</span><br>             <span style="color:#0000ff">foreach</span> (<span style="color:#2b91af">IParticleEmitter</span> emitter <span style="color:#0000ff">in</span> emitterQue)<br>             {<br>                 Emitters.Add(emitter);<br>             }<br>             emitterQue.Clear();<br> <br>             Updating = <span style="color:#0000ff">true</span>;<br>             <span style="color:#0000ff">foreach</span> (<span style="color:#2b91af">IParticleEmitter</span> emitter <span style="color:#0000ff">in</span> Emitters)<br>             {<br>                 <br>                 <span style="color:#0000ff">if</span> (!emitter.Alive)<br>                     removeList.Add(emitter);<br> <br>                 <span style="color:#0000ff">if</span>(emitter.Enabled)<br>                     emitter.Update(gameTime);<br>             }<br> <br>             <span style="color:#0000ff">foreach</span> (<span style="color:#2b91af">IParticleEmitter</span> emitter <span style="color:#0000ff">in</span> removeList)<br>             {<br>                 emitter.Die();<br>                 Emitters.Remove(emitter);<br>             }<br>             Updating = <span style="color:#0000ff">false</span>;<br>         }</div> </div> </div> <p>The draw call is much simpler, just iterate through our emitters and make there draw calls.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:6885bc9c-5d6c-4467-b4a0-5deb81ee5829" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> Draw(<span style="color:#2b91af">GameTime</span> gameTime)<br>         {<br>             <span style="color:#0000ff">foreach</span> (<span style="color:#2b91af">IParticleEmitter</span> emitter <span style="color:#0000ff">in</span> Emitters)<br>             {<br>                 <span style="color:#0000ff">if</span>(emitter.Visible)<br>                     emitter.Draw(gameTime);<br>             }<br>         }</div> </div> </div> <h2> </h2> <h2>Interfaces</h2> <p>In the sample I have two interfaces, the aforementioned IParticleEmitter interface and the IGameEntity interface. I created the latter so I could bind an emitter to a screen object, so if you look at the clip, you can see the smoke trail is fixed to the ship, where ever the ship goes, the smoke trail follows.</p> <h5>IParticleEmitter</h5> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:5326d86d-31f1-4887-85f5-5b871c057bd8" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">    <span style="color:#0000ff">public</span> <span style="color:#0000ff">interface</span> <span style="color:#2b91af">IParticleEmitter</span> : <span style="color:#2b91af">IGameEntity</span><br>     {<br>         <span style="color:#2b91af">SpriteBatch</span> SpriteBatch { <span style="color:#0000ff">get</span>; }<br> <br>         <span style="color:#2b91af">ParticleEmitterService</span> ParticleEmitter { <span style="color:#0000ff">get</span>; }<br> <br>         <span style="color:#2b91af">BlendState</span> ParticleBlendState { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br> <br>         <span style="color:#2b91af">IGameEntity</span> GameEntity { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br>         <span style="color:#2b91af">Vector2</span> EnityOffset { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br> <br>         <span style="color:#2b91af">Vector2</span>[] particles { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br>         <span style="color:#0000ff">float</span>[] scaleParticle { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br>         <span style="color:#0000ff">float</span>[] rotationParticle { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br>         <span style="color:#0000ff">bool</span>[] activeParticle { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br> <br>         <span style="color:#2b91af">Color</span> Color { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br> <br>         <span style="color:#2b91af">Texture2D</span> texture { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br> <br>         <span style="color:#0000ff">int</span> ParticleCount { <span style="color:#0000ff">get</span>; }<br> <br>         <span style="color:#0000ff">bool</span> Alive { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br> <br>         <span style="color:#0000ff">void</span> Die();<br>     }</div> </div> </div> <p>As you can see, we have a few elements in there, but firstly we implement IGamEntity, here, why? Well you might want to hang an emitter off an emitter, so, a smoke trail off a fire ball for example, also, my IGameEntity also gives us other data structures, like position, scale, rotation, as well as bounds data (not implemented in here for the particle system) and a Docollision method (again, not for particles here)</p> <h5>IGameEntity</h5> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:0004f8c7-9c8a-4f30-a091-313d0d84e992" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">    <span style="color:#0000ff">public</span> <span style="color:#0000ff">interface</span> <span style="color:#2b91af">IGameEntity</span> : <span style="color:#2b91af">IGameComponent</span>, <span style="color:#2b91af">IUpdateable</span>, <span style="color:#2b91af">IDrawable</span><br>     {<br>         <span style="color:#2b91af">Vector2</span> Position { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br>         <span style="color:#2b91af">Vector2</span> Origin { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br> <br>         <span style="color:#0000ff">float</span> Scale { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br>         <span style="color:#0000ff">float</span> Rotation { <span style="color:#0000ff">get</span>; <span style="color:#0000ff">set</span>; }<br> <br>         <span style="color:#2b91af">Rectangle</span> bounds { <span style="color:#0000ff">get</span>; }<br> <br>         <span style="color:#0000ff">bool</span> DoCollision(<span style="color:#2b91af">IGameEntity</span> entity);<br>     }</div> </div> </div> <p>This interface has all the stuff we need for our game entities. </p> <p>Actually looking back over the interfaces, we could cull out a lot of these items as they are not used in the sample by implementing the interfaces, but I have kept them in here as you may need them later on (maybe).</p> <h2>Emitters</h2> <p>So, what do the emitters look like? Well to make life a bit more easier, I decided to use a base class that the emitters can then derive from, this base class implements the IParticleEmitter interface, so all you need to do to create a new emitter is to derive from this base class and away you go.</p> <h5>EmitterBase </h5> <p>As you might expect, EmitterBase implements our interfaces, the ctor sets up our default values</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:071f6425-2f91-4846-8a6a-864ab692b938" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> EmitterBase(<span style="color:#2b91af">Game</span> game, <span style="color:#0000ff">string</span> TextureAsset)<br>             : <span style="color:#0000ff">base</span>(game)<br>         {<br>             textureAsset = TextureAsset;<br> <br>             Position = <span style="color:#2b91af">Vector2</span>.Zero;<br>             Origin = <span style="color:#2b91af">Vector2</span>.Zero;<br>             Scale = 1f;<br>             Rotation = 0;<br> <br>             ParticleBlendState = <span style="color:#2b91af">BlendState</span>.Additive;<br> <br>             Color = <span style="color:#2b91af">Color</span>.White;<br>         }</div> </div> </div> <p>Initialise, well intializes the lists we need to implement the emitter</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:9b19c0f3-1556-421a-839e-411f9441ddee" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> Initialize()<br>         {<br>             particles = <span style="color:#0000ff">new</span> <span style="color:#2b91af">Vector2</span>[ParticleCount];<br>             scaleParticle = <span style="color:#0000ff">new</span> <span style="color:#0000ff">float</span>[ParticleCount];<br>             rotationParticle = <span style="color:#0000ff">new</span> <span style="color:#0000ff">float</span>[ParticleCount];<br>             activeParticle = <span style="color:#0000ff">new</span> <span style="color:#0000ff">bool</span>[ParticleCount];<br> <br>             texture = Game.Content.Load<<span style="color:#2b91af">Texture2D</span>>(textureAsset);<br>             Origin = <span style="color:#0000ff">new</span> <span style="color:#2b91af">Vector2</span>(texture.Width / 2, texture.Height / 2);<br> <br>             <span style="color:#0000ff">for</span> (<span style="color:#0000ff">int</span> p = 0; p < ParticleCount; p++)<br>             {<br>                 rotationParticle[p] = 0;<br>                 particles[p] = <span style="color:#2b91af">Vector2</span>.Zero;<br>                 scaleParticle[p] = Scale;<br>             }<br>         }</div> </div> </div> <p>Our update method is only of use if we have given the emitter an IGameEntity to bind to, and if it does, endures that we stick to that entity.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:9e09199a-280e-4493-a21e-573b7f073646" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> Update(<span style="color:#2b91af">GameTime</span> gameTime)<br>         {<br>             <span style="color:#0000ff">if</span> (GameEntity != <span style="color:#0000ff">null</span>)<br>             {<br>                 Rotation = GameEntity.Rotation;<br>                 Position = GameEntity.Position + EnityOffset;<br>             }<br>         }</div> </div> </div> <p>Our draw method again, simply draws the particles where we want them</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:f002a95b-5ee7-463b-8e3f-305296636f25" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> Draw(<span style="color:#2b91af">GameTime</span> gameTime)<br>         {<br>             SpriteBatch.Begin(<span style="color:#2b91af">SpriteSortMode</span>.Deferred, ParticleBlendState);<br> <br>             <span style="color:#0000ff">for</span> (<span style="color:#0000ff">int</span> p = 0; p < ParticleCount; p++)<br>             {<br>                 <span style="color:#0000ff">if</span> (activeParticle[p])<br>                     SpriteBatch.Draw(texture, particles[p], <span style="color:#0000ff">null</span>, Color, rotationParticle[p], Origin, scaleParticle[p], <span style="color:#2b91af">SpriteEffects</span>.None, 0);<br>             }<br> <br>             SpriteBatch.End();<br>         }</div> </div> </div> <p>Our DoCollision and Die methods are just place holders for the base class, but we make sure they are virtual so they can be overriden later.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c713772c-b9a6-4e79-9fb2-5f630834f9ef" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">virtual</span> <span style="color:#0000ff">bool</span> DoCollision(<span style="color:#2b91af">IGameEntity</span> entity)<br>         {<br>             <span style="color:#0000ff">return</span> <span style="color:#0000ff">false</span>;<br>         }<br> <br>         <span style="color:#0000ff">public</span> <span style="color:#0000ff">virtual</span> <span style="color:#0000ff">void</span> Die()<br>         {<br> <br>         }</div> </div> </div> <p>So, that’s the basic structure, but what does an example emitter look like? Lets have a look at the SmokeTrail emitter.</p> <h5>SmokeTrailEmitter</h5> <p>First off, we derive from EmitterBase, this way we have all the intrinsic goodness from that base class for our emitter, and it is then by default a IParticleEmitter and an IGameEntity.</p> <p>In the ctor, we set the texture to be used, the number of particles and the scale, in the Initialize method, we ensure our first particle is active.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:b58b61cf-43dd-4e02-8423-a85ac03956e5" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">    <span style="color:#0000ff">public</span> <span style="color:#0000ff">class</span> <span style="color:#2b91af">SmokeTrailEmitter</span> : <span style="color:#2b91af">EmitterBase</span><br>     {<br>         <span style="color:#0000ff">public</span> SmokeTrailEmitter(<span style="color:#2b91af">Game</span> game)<br>             : <span style="color:#0000ff">base</span>(game, <span style="color:#a31515">"Textures/Particles/Smoke"</span>)<br>         {<br>             particleCount = 10;<br>             Scale = .1f;<br>         }<br> <br>         <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> Initialize()<br>         {<br>             <span style="color:#0000ff">base</span>.Initialize();<br>             activeParticle[0] = <span style="color:#0000ff">true</span>;<br>         }</div> </div> </div> <p>Then all we have to do, is write the Update method, in here, we are looping through all the particles in the list, if they are active we move them down the screen, and increase there scale a little and rotate them a bit. We also measure the distance from the emitter and if greater (in this case) than 150 pixels, we deactivate it.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:0720aa78-1a44-4f01-bd95-cedad3ed3537" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> Update(<span style="color:#2b91af">GameTime</span> gameTime)<br>         {<br>             <span style="color:#008000">// set particle positions.</span><br>             <span style="color:#0000ff">for</span> (<span style="color:#0000ff">int</span> p = 0; p < ParticleCount; p++)<br>             {<br>                 <span style="color:#0000ff">if</span> (activeParticle[p])<br>                 {<br>                     rotationParticle[p] -= (p + 1) / ParticleCount;<br>                     particles[p].Y += 8f;                    <br>                     scaleParticle[p] += .015f;<br>                     <span style="color:#0000ff">float</span> dist = <span style="color:#2b91af">Vector2</span>.Distance(Position, particles[p]);<br> <br>                     <span style="color:#0000ff">if</span> (dist > 150)<br>                         activeParticle[p] = <span style="color:#0000ff">false</span>;<br>                 }</div> </div> </div> <p>If the particle is not active, we then see if we need to activate it, so we set it’s position to that of the emitter, randomly move it either left or right a bit so we get a bobbly smoke effect and set it’s scale to the starting scale value. We then compare it’s distance from the last particle and if greater that 25 make it active.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:3c8b4b0a-d24e-4ca2-a876-f9b8cb190594" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">                <span style="color:#0000ff">else</span><br>                 {<br>                     particles[p] = Position;<br>                     particles[p].X += <span style="color:#2b91af">MathHelper</span>.Lerp(-5, 5, (<span style="color:#0000ff">float</span>)rnd.NextDouble());<br> <br>                     scaleParticle[p] = Scale;<br>                     <span style="color:#0000ff">int</span> nextP = p - 1;<br> <br>                     <span style="color:#0000ff">if</span> (p == 0)<br>                     {<br>                         nextP = ParticleCount - 1;<br>                     }<br> <br>                     <span style="color:#0000ff">float</span> dist = <span style="color:#2b91af">Vector2</span>.Distance(particles[nextP], particles[p]);<br>                     <span style="color:#0000ff">if</span> (dist > 25)<br>                         activeParticle[p] = <span style="color:#0000ff">true</span>;<br>                 }<br>             }<br>             <span style="color:#0000ff">base</span>.Update(gameTime);<br>         }</div> </div> </div> <p>I know, not the most awesome particle emitter, but it’s showing you how you can create you own emitters, take a look at the ExplosionEmitter’s Update method, this gives a totally different emitter result</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:41afbec1-7f9c-43db-ba45-950336d55a6a" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> Update(<span style="color:#2b91af">GameTime</span> gameTime)<br>         {<br>             <span style="color:#0000ff">for</span> (<span style="color:#0000ff">int</span> p = 0; p < ParticleCount; p++)<br>             {<br>                 <span style="color:#008000">//particles[p] = Position;</span><br>                 rotationParticle[p] += (ParticleCount / (p+1)) * .1f;<br>                 <span style="color:#0000ff">if</span> (blowOut)<br>                     Scale += .0025f;<br>                 <span style="color:#0000ff">else</span><br>                 {<br>                     a -= .005f;<br>                     <span style="color:#0000ff">if</span> (a <= 0)<br>                         a = 0;<br>                     <br>                     Color = <span style="color:#0000ff">new</span> <span style="color:#2b91af">Color</span>(Color.R, Color.G, Color.B, (<span style="color:#0000ff">byte</span>)(a * 255));<br> <br>                     Scale -= .0025f;<br>                 }<br> <br>                 <span style="color:#0000ff">if</span> (Scale > .5f)<br>                 {<br>                     Scale = .5f;<br>                     blowOut = !blowOut;<br>                     ParticleEmitter.AddEmitter(<span style="color:#2b91af">EmitterType</span>.SmokeBomb, Position);<br>                 }<br>                 scaleParticle[p] = Scale;<br>             }<br> <br>             <span style="color:#0000ff">if</span> (Scale <= 0)<br>                 Alive = <span style="color:#0000ff">false</span>;<br>             <br>             <br>             <span style="color:#0000ff">base</span>.Update(gameTime);<br>         }</div> </div> </div> <p>And now the one for the SmokeBombEmitter, again totally different results.</p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:66e41ef8-8db3-41f9-a7b7-073120734682" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background-color: #ffffff; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap">        <span style="color:#0000ff">public</span> <span style="color:#0000ff">override</span> <span style="color:#0000ff">void</span> Update(<span style="color:#2b91af">GameTime</span> gameTime)<br>         {<br>             <span style="color:#0000ff">for</span> (<span style="color:#0000ff">int</span> p = 0; p < ParticleCount; p++)<br>             {<br>                 <span style="color:#008000">//particles[p] = Position;</span><br>                 rotationParticle[p] += (ParticleCount / (p + 1)) * .1f;<br>                 Scale += .0025f;<br>                 a -= .0025f;<br>                 <span style="color:#0000ff">if</span> (a <= 0)<br>                     a = 0;<br>                 scaleParticle[p] = Scale;<br>                 Color = <span style="color:#0000ff">new</span> <span style="color:#2b91af">Color</span>(Color.R, Color.G, Color.B, (<span style="color:#0000ff">byte</span>)(a*255));<br>             }<br> <br>             <span style="color:#0000ff">if</span> (a <= 0)<br>                 Alive = <span style="color:#0000ff">false</span>;<br> <br>             <span style="color:#0000ff">base</span>.Update(gameTime);<br>         }</div> </div> </div> <p>Hope you find this useful, you can get all the source code for this <a href="http://www.randomchaos.co.uk/tutorials/xna/Randomchaos2DParticlesSysImp.zip">here</a>. </p> <p>Also, the project uses a specific font, you can download it <a href="http://www.searchfreefonts.com/free/decrepit-brk.htm">here</a>, or swap it for one you have.</p> <p>As ever C&C welcome.</p> Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com2tag:blogger.com,1999:blog-7553595438846063219.post-42105949301832390592012-07-25T00:39:00.001+01:002012-07-25T00:39:09.132+01:00Line Intersection – y = mx + c<p>So, a twitter conversation started up with <a href="https://twitter.com/DaveVoyles">Dave Voyles</a>, he wanted to be able to find the exact point that two rectangles collided with each other, some suggestions got thrown about, but I thought one way to do it would be to use the line equation, </p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVc5r8MeepM2afLHPHHaJx0Ng_Jko1VYnK5N4COrCwAQUMTSEkP4SbE0__Pn0QBseWxFX3CyH4xVPEPmzBYP5Urc4pTm_goxO1FFyPyfR6iOBCdWWDI7EfrWNyiINgtGtorsgUyXeIQEf-/s1600-h/image%25255B3%25255D.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh3.ggpht.com/-u4XjYfUIBw8/UA8x7D9jLXI/AAAAAAAABLI/cKrq0SJIHV0/image_thumb%25255B1%25255D.png?imgmax=800" width="113" height="35"></a> <p>This equation is used to represent a line, the <em>x</em> and <em>y</em> co-ords are the possible points along this line, <em>m</em> in the gradient or slope of the line and the <em>c</em> is where the line crosses through the y axis on a graph and is known as the y intercept.</p> <p>So I thought, you could build 4 of these lines from your rectangles, then using this equation you can find exactly where the line(s) intersect.</p> <p>I am not going to cover all the math here, but what I am doing here is first finding the slope and y intercept of the two lines, we then see if both lines are vertical or horizontal, if both lines are then it’s pretty simple to solve, if not, then we have to re calculate the lope and the y intercept.</p> <p>That done we can then check to see if our two equations add up,so I solve for <em>y</em> in both cases, if they are equal, then we just need to make sure that our <em>x</em> value lies on both the lines based on the line min and max values….and, well that’s about it. </p> <p>As I have said before, I am probably sub GCSE math, so a lot of this could well be all bum, but it works, please point and laugh out loud at my crap math but please give your reasons for pointing and laughing, that way we all learn from my mistakes :)</p> <p>I wrote this class a long time ago to, and had to dig the source out from my HDD to post it here.</p> <p>Here are some pics of the code in action, we have 2 lines, first image is with no intersection</p> <p><a href="http://lh4.ggpht.com/-nPbSpn1sBB4/UA8x8Pi4zKI/AAAAAAAABLU/JQsjqhGp7Xo/s1600-h/image%25255B7%25255D.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil-EVIZv9CbpGXBgpCmS3OQkl8NWx97cxfhyphenhypheneHPIwERll3ShW8vxvYSlq4QDxjDexFSOtvOhJ4KNIaXRmRHqwr5sdKKauV6RLdHLBBxG9qg_fJfi5j-VbO0cILu0nhgpdb6shfrCIn7yFT/?imgmax=800" width="240" height="143"></a></p> <p>I can then rotate the green line round so that it intersects, here are a few images of the lines intersecting, the red dot (if you can see it) is the exact point of intersection.</p> <p><a href="http://lh4.ggpht.com/-pJ8XMpeFBaQ/UA8x9_zV0ZI/AAAAAAAABLk/Rm7VD1tEICo/s1600-h/image%25255B11%25255D.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh3.ggpht.com/-xQc2-NZ_r6s/UA8x_IZ_fbI/AAAAAAAABLo/ZWM0jFZTGhs/image_thumb%25255B5%25255D.png?imgmax=800" width="240" height="143"></a></p> <p><a href="http://lh3.ggpht.com/-1dwRob57aG0/UA8x_zsIFHI/AAAAAAAABL0/ZPkOrPB3A48/s1600-h/image%25255B15%25255D.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh5.ggpht.com/-VC8oQLvKXXk/UA8yA8GKmbI/AAAAAAAABL4/0A8LaKS5x2c/image_thumb%25255B7%25255D.png?imgmax=800" width="240" height="142"></a></p> <p><a href="http://lh4.ggpht.com/-ztVSJVzwOkE/UA8yCOdk5KI/AAAAAAAABME/8IuS9UnGrZI/s1600-h/image%25255B19%25255D.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh5.ggpht.com/-yxPFcE5KC40/UA8yC72iQYI/AAAAAAAABMM/UkPNyvcnLmA/image_thumb%25255B9%25255D.png?imgmax=800" width="240" height="143"></a></p> <p>I made a mod to my original code so if the lines are both vertical or both horizontal it gets an intersection point based on the two inner points and puts it in the middle, like this</p> <p><a href="http://lh6.ggpht.com/-cGD8mMhxYWo/UA8yDghMbII/AAAAAAAABMQ/ifPGrCyPi1U/s1600-h/image%25255B23%25255D.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh6.ggpht.com/-pKrBBtP295Q/UA8yElzMfvI/AAAAAAAABMc/AvK9JPADNFk/image_thumb%25255B11%25255D.png?imgmax=800" width="240" height="143"></a></p> <p>And this</p> <p><a href="http://lh4.ggpht.com/-o9hTepvnqNg/UA8yFj3ytxI/AAAAAAAABMg/8pjDwhNuSqI/s1600-h/image%25255B27%25255D.png"><img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3WN5ryWmeQxYHs_fxib6jTobFTbETftc-3OvA3JllUwLAWeJd0iGlyO-hNNF8p5sLo9caObuOjmDziEqS0Sp0HA0KN8_Se80ZNN5fy2QlaEjCGA683dahGuxpGbFeqD4-qIVhyphenhyphenyD8DGvI/?imgmax=800" width="240" height="144"></a></p> <p>You can download the sample code for this <a href="http://www.randomchaos.co.uk/tutorials/xna/RandomchaosLineIntersectionSample.zip">here</a>.</p> <p>You can control the green line with the arrow keys to move it about, the keys Q and Z to scale it’s length, as well as E and C to rotate it.</p> <p>For more help and better explanation of the <em><a href="http://www.teacherschoice.com.au/maths_library/functions/y_=_mx_+_c.htm">y = mx + c</a></em><em></em> equation, google it, there are loads of math resources out there.</p> Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com3tag:blogger.com,1999:blog-7553595438846063219.post-50638204240052256962012-07-11T16:56:00.001+01:002012-07-12T10:31:52.861+01:00Volumetric Clouds in XNA 4.0As mentioned in the last post and the comments before that, I got asked to port my old XNA 3.x volumetric clouds over to XNA 4.0, and that’s just what I have done, but with a few changes.<br />
The first is I am using instancing, if you don’t know what instancing is, it’s a way we can pass one set of geometry to the graphic card, but have it render lots and lots of instances of that geometry. So, in the case of our clouds, we render wisps' that are render on a quad or billboard, this billboard is just verts, so as far as the vertex buffer goes, it just holds these 4 verts, on another channel we send the graphics card a list of transforms, these transforms (or world matrix’s) represent and instance to be rendered, so, if we send ten transforms, then 10 billboards will be rendered.<br />
You can find my archived post on the original code base <a href="http://xnauk-randomchaosblogarchive.blogspot.co.uk/2012/07/volumetric-clouds-source.html">here</a>.<br />
So, that’s quite a change from the old implementation, in the earlier version I had Point Sprites (never a good idea) and billboards, and I would chain them up into a single draw call, so the vertex buffer would be the number of wisps multiplied by four, one for each vert in the quad. It gave a good result, and looked like this<br />
<div class="wlWriterEditableSmartContent" id="scid:53357c8b-5919-4e32-8c25-305d27c17a37:7095b9d0-864f-4f72-9506-8f90fc4de770" style="display: block; float: none; margin-left: auto; margin-right: auto; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 425px;">
<embed height="350" src="http://www.youtube.com/v/P-Nw4CANeBc" type="application/x-shockwave-flash" width="425" wmode="transparent"></embed></div>
You can see in the clip, it’s a bit laggy, but to be fair it was running on a very old and crappy laptop.<br />
I also changed the shader a little, as I had to anyway to get the instancing to work, but also to get a better fade as the camera got close to the cloud, before as you approached the cloud, it would fade out, but as I was doing this in the vertex shader, if it was a big billboard you would see the billboard rotate and then start to fade. I am still doing this check in the vertex shader, but I am also now doing it in the pixel shader, it now fades the cloud out much better and reduces the visibility of the twisting billboard artifact on large billboards.<br />
This is what it now looks like<br />
<div class="wlWriterEditableSmartContent" id="scid:53357c8b-5919-4e32-8c25-305d27c17a37:77342cf0-8f5f-42ee-9a83-cb71d1ef55f8" style="display: block; float: none; margin-left: auto; margin-right: auto; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 425px;">
<embed height="350" src="http://www.youtube.com/v/Mzx63UcmKBY" type="application/x-shockwave-flash" width="425" wmode="transparent"></embed></div>
So, <a href="http://www.randomchaos.co.uk/Tutorials/XNA/RandomchaosXNA4_0Clouds.zip">here</a> is the code for the clouds in XNA 4.0 <br />
Next post ill expand on instancing a bit more and show how I used it to render 1 million particles :)<br />
<strong><span style="color: red;">REMEMBER: DO NOT COMERCIALY USE THE CLOUD TEXTURE IN THE ZIP AS IT IS PROPERTY OF MS!</span></strong><br />
Just so you know and don’t get your self stung, I have put this comment in the code where ever it is referenced.<br />
<div class="wlWriterEditableSmartContent" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:48b7c8fc-9e93-4468-ad23-79cc91a0157d" style="display: inline; float: none; margin: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">
<div style="border: #000080 1px solid; color: black; font-family: 'Courier New', Courier, Monospace; font-size: 10pt;">
<div style="background-color: white; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap;">
<span style="color: green;">//////////////////////////////////////////////////////////////////</span><br />
<span style="color: green;">// REMEMBER THE CloudSpriteSheetOrg texture is property of MS //</span><br />
<span style="color: green;">// Do not comercialy use this texture! //</span><br />
<span style="color: green;">//////////////////////////////////////////////////////////////////</span></div>
</div>
</div>Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com20tag:blogger.com,1999:blog-7553595438846063219.post-81603123226175523142012-07-10T23:08:00.002+01:002012-07-10T23:09:39.859+01:00Volumetric Clouds in XNA 4.0<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/Mzx63UcmKBY?feature=player_embedded' frameborder='0'></iframe></div>
<div>
<br /></div>
<br />
<a href="http://www.blogger.com/profile/07599093117281057746">Anne-Lise Pasch</a> asked me to update the cloud sample I did way back in XNA 4.0, so this is my progress so far, hoping to write the blog post this week, if I have time :)<br />
What I love about this is each and every scene is done with a single draw call :)<br />
<br />
As ever, comments are welcome :D<br />Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com6tag:blogger.com,1999:blog-7553595438846063219.post-9795892355325285542012-06-29T09:07:00.000+01:002012-06-29T09:07:05.527+01:00What lays in store....You may have come here as you followed my blog on the XNA-UK User group, or you may have just stumbled across this by accident, either way, welcome :)<br />
<br />
In this blog I am going to post some of the things I am doing with XNA, posts will come with code samples where required, and clips showing the techniques in use.<br />
<br />
If you are new to XNA and have not seen my old blog, there is an archive of my old posts <a href="http://xnauk-randomchaosblogarchive.blogspot.co.uk/">here</a>.<br />
<br />
Welcome to my blog, and I hope what you read you find useful. Oh, and don't forget to comment if you have any suggestions or like what you have read.Charles Humphreyhttp://www.blogger.com/profile/10935746329039730399noreply@blogger.com11