tag:blogger.com,1999:blog-89673211149655389032024-03-14T09:09:52.443+00:00Lane DefenceFireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-8967321114965538903.post-36502509450709902642014-06-18T18:00:00.000+01:002014-06-18T18:00:13.004+01:00XNA 5? Why Not Sunburn?!<div abp="711">
As most of you probably know, <a abp="713" href="http://www.gamasutra.com/view/news/185894/Its_official_XNA_is_dead.php" target="_blank">XNA in its current form is dead</a>. Although several alternatives exist such as Monogame and Unity, people seem to either not know about or consistently fail to mention SunBurns relatively new <strong abp="965"><u abp="966"><em abp="967"><span abp="968" style="color: red;">and completely free</span></em></u></strong> <a abp="970" href="http://www.synapsegaming.com/products/sunburn/framework/" target="_blank">Platform framework</a>.</div>
<div abp="715">
<br /></div>
<div abp="729">
It offers an API very similar to XNA's and has a lot of the same features, with the added support for many, many more platforms including:</div>
<div abp="729">
</div>
<ul abp="1025">
<li abp="1026"><div abp="1027">
Windows Desktop</div>
</li>
<li abp="1028"><div abp="1029">
Windows Store</div>
</li>
<li abp="1030"><div abp="1031">
Windows Phone</div>
</li>
<li abp="1032"><div abp="1033">
Android</div>
</li>
<li abp="1034"><div abp="1035">
Linux</div>
</li>
<li abp="1036"><div abp="1037">
Mac OS</div>
</li>
</ul>
<div abp="729">
With more still coming! What's even better is, you can share <strong abp="1038">most</strong> of your code across all platforms without any changes; no more #if statements!</div>
<div abp="729">
</div>
<div abp="729">
SunBurn allows you to do this by separating your game into three types of project: the Content Project (same as XNA), the Game Library and the Platform specific project: </div>
<div abp="729">
</div>
<div abp="729">
<a abp="1039" href="http://www.synapsegaming.com/wikis/using_sunburn/sunburn-platform-layer-overview.aspx">http://www.synapsegaming.com/wikis/using_sunburn/sunburn-platform-layer-overview.aspx</a></div>
<div abp="729">
<a href="http://www.synapsegaming.com/wikis/using_sunburn/project-layout.aspx">http://www.synapsegaming.com/wikis/using_sunburn/project-layout.aspx</a></div>
<div abp="729">
<a href="http://www.synapsegaming.com/wikis/sunburn_1_0_docs/portable-development-working-outside-the-sandbox.aspx">http://www.synapsegaming.com/wikis/sunburn_1_0_docs/portable-development-working-outside-the-sandbox.aspx</a></div>
<div abp="729">
</div>
<div abp="729">
If all this wasn't enough, the team behind SunBurn are constantly answering the communities questions <a abp="1041" href="http://www.synapsegaming.com/community/" target="_blank">on the forums</a>, as well as responding and fixing any bugs which have been found. They truly offer the best support in the business!</div>
<div abp="729">
</div>
<div abp="729">
If you want to find out more, the SunBurn website has a lot more information:</div>
<div abp="729">
</div>
<div abp="729">
<a href="http://www.synapsegaming.com/products/sunburn/framework/">http://www.synapsegaming.com/products/sunburn/framework/</a></div>
<div abp="729">
</div>
<div abp="729">
I hope to update all of my old tutorials to use the new SunBurn Platform, so stay tuned!</div>
FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com1tag:blogger.com,1999:blog-8967321114965538903.post-80796078389398691472013-09-18T13:25:00.000+01:002013-09-21T11:16:23.948+01:00Lane DefenceAre you bored of all the cloned tower defence games out there? Introducing, Lane Defence!<br />
<br />
A unique tower defence game in the style of the old Warcraft 3 Line Tower Wars map; you work to build a maze of towers which will stop the 40 waves of enemies from reaching the bottom of the lane!<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQAHnhn1L3NniP1doDm1nxG83nKy7jjNqo3jU2YyvD5va8boD7yahm0KfbxTYsxyWom3hZxiV4vD504Kzqa4XIhZoNhOvvPdG4ab4UdzM5rB0_rOktN0meu9hOV09rlCUc31vikSxWTqiv/s1600/2013-09-19_11-50-31.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQAHnhn1L3NniP1doDm1nxG83nKy7jjNqo3jU2YyvD5va8boD7yahm0KfbxTYsxyWom3hZxiV4vD504Kzqa4XIhZoNhOvvPdG4ab4UdzM5rB0_rOktN0meu9hOV09rlCUc31vikSxWTqiv/s320/2013-09-19_11-50-31.jpg" width="192" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-bzq-as_8J7ylMs_njKOtCsZahoqEiqjnKsq-o6j4kA7R5etGNkgTHp_NwjicpTAUNqqCKaJqCpcbaDOi-U2SIG8rNweJ5eDoJ2XYyveOQG3HBdlY7oJTCKCL_qT_1l2trzJAV9lN2AIQ/s1600/2013-09-06_12-50-32.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-bzq-as_8J7ylMs_njKOtCsZahoqEiqjnKsq-o6j4kA7R5etGNkgTHp_NwjicpTAUNqqCKaJqCpcbaDOi-U2SIG8rNweJ5eDoJ2XYyveOQG3HBdlY7oJTCKCL_qT_1l2trzJAV9lN2AIQ/s320/2013-09-06_12-50-32.jpg" width="192" /></a></div>
<br />
This is how a tower defence is meant to play; No longer will enemies walk through each other like ghosts or conform to a set path, you are in control.<br />
<br />
Create choke points to take full advantage of your splash towers, or encircle the high damage towers to get optimum attack time; the smarter your maze is, the easier the game will become.<br />
<br />
You will be defending your lane against 5 types of enemy:<br />
<br />
Normal - Nothing special.<br />
Fast - Moves much faster than his friends.<br />
Immune - Will not be slowed by any tower.<br />
Air - Laughs at your mazes as he soars over them.<br />
Boss - Lonesome, but very tough to kill.<br />
<br />
To aid you, you will choose two unique 'speciality' towers from:<br />
<br />
Ice - Slow's enemies.<br />
Fire - Fast with average damage.<br />
Tech - Very slow, but awesome against bosses.<br />
Earth - Slow with a large splash damage.<br />
Lightning - The bane of air enemies<br />
<br />
Each have their strengths, but which combination will work best for you? Can you achieve the ultimate goal and beat the game using all of the combos? You can track your progress with the built in medal system!<br />
<br />
Perfection must be achieved!<br />
<br />
Download the demo (free) from:<br />
<br />
Google Play: <a href="http://play.google.com/store/apps/details?id=englishguygames.lanedefence.demo">http://play.google.com/store/apps/details?id=englishguygames.lanedefence.demo</a><br />
Amazon Market: <a href="http://amazon.com/gp/mas/dl/android?p=englishguygames.lanedefence.demo">amazon.com/gp/mas/dl/android?p=englishguygames.lanedefence.demo</a><br />
<br />
Download the full version ($0.99):<br />
<br />
Google Play: <a href="http://play.google.com/store/apps/details?id=englishguygames.lanedefence">http://play.google.com/store/apps/details?id=englishguygames.lanedefence</a><br />
Amazon Market: <a href="http://amazon.com/gp/mas/dl/android?p=englishguygames.lanedefence">amazon.com/gp/mas/dl/android?p=englishguygames.lanedefence</a>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com7tag:blogger.com,1999:blog-8967321114965538903.post-34351134392269105982013-09-09T21:56:00.000+01:002013-09-09T21:57:36.516+01:00Lane Defence: Coming Soon<div style="text-align: center;">
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Enjoyed the tutorials...? Ever wondered what would happen if you carried on developing...?</span></b></div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5r5KtaEp0IhPgQ8XsF1LfH-fHCGYcLcZYFZqHVOXrtTqQfF-aV_3BKLsuCVUE2f6QuSpWICYw70rnPdkfDxF6i3v39zru3yNzFsGhUFs5QE-M7jQ1i_jagY4IgoHow2SLSt1t7jFQBSfN/s1600/Web.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5r5KtaEp0IhPgQ8XsF1LfH-fHCGYcLcZYFZqHVOXrtTqQfF-aV_3BKLsuCVUE2f6QuSpWICYw70rnPdkfDxF6i3v39zru3yNzFsGhUFs5QE-M7jQ1i_jagY4IgoHow2SLSt1t7jFQBSfN/s1600/Web.png" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">COMING SOON TO GOOGLE PLAY STORE!</span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">(TESTERS WANTED)</span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span></b></div>
FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com1tag:blogger.com,1999:blog-8967321114965538903.post-13433999115150520782012-08-12T10:49:00.000+01:002012-08-12T10:49:05.313+01:00Platformer Starter Kit: Ramp ExampleIf anyone is interested I have modified the platformer starter kit so that it can handle ramps by using SAT:<br />
<br />
<a href="http://www.mediafire.com/file/9ekhfpf0gt7zehg/PlatformerWithRamps.zip">http://www.mediafire.com/file/9ekhfpf0gt7zehg/PlatformerWithRamps.zip</a>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com4tag:blogger.com,1999:blog-8967321114965538903.post-81080808722420813872012-05-11T21:01:00.000+01:002012-05-11T21:01:46.701+01:003D Level Editor<a href="https://sceneeditor.codeplex.com/" target="_blank">Have you ever wanted to build your own game levels but don't have the time to create you own editor?</a>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com1tag:blogger.com,1999:blog-8967321114965538903.post-46209418448388489902012-05-04T17:02:00.001+01:002012-05-05T09:52:57.838+01:002D Collision Series : SAT Part 1In this series, I will be giving a very brief insight into the world of 2D collision detection and response. Normally during collision detection there are two phases, Broad phase and Narrow phase. <br />
<br />
This series will focus on the Narrow phase.<br />
<br />
<a name='more'></a>The Broad phase is where you quickly look over all of the objects in your world and do a very rough collision test (e.g Rectangle to Rectangle or Sphere to Sphere) to find pairs of objects that might be colliding. This step is performed first to help cut down on the number of more accurate, more expensive tests we will perform in the Narrow phase. The Broad phase is normally speeded up using spatial partitioning methods such as Quadtrees, however I will not be discussing such things in this series.<br />
<br />
The Narrow phase is where we will look at each pair of possibly colliding objects found in the Broad Phase and do a more accurate check to test if the objects are actually colliding. In a lot of situations rectangles and spheres are not good enough to represent the shape of an object, what if we want to check if a rectangle<br />
and a triangle are colliding for instance?. This will be the focus of this tutorial series.<br />
<br />
In particular the method we will be using for our Narrow phase tests is called the Separating Axis Theorem (or SAT for short). Do not let the name put you off, the method itself is actually very simple to understand and only uses very little vector math!<br />
<br />
Quite simply, SAT states that if we can draw a straight line between two <a href="http://en.wikipedia.org/wiki/Convex" target="_blank"><strong>convex</strong></a> shapes, the two shapes are not colliding. We refer to this line as the <strong>Separation Axis</strong>. Simple enough right?<br />
<br />
<a href="http://lh3.ggpht.com/-AoCqws6N_pI/T6P9nRZivaI/AAAAAAAAAGo/KJr5v5EUTxQ/s1600-h/image%25255B8%25255D.png"><img alt="image" border="0" height="150" src="http://lh5.ggpht.com/-BPqaRY3bCf0/T6P9nvzTLsI/AAAAAAAAAGw/RXsNagFxcYc/image_thumb%25255B4%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="418" /></a><br />
<br />
So which set of axes should we test and how do we actually test if an axis actually separates two shapes?<br />
<br />
It would be naive to just keep picking lines at random and hope that one of them separates the two shapes; It turns out the only axes that we need to test are the ones that are parallel to the shapes edges, take the above rectangles for example:<br />
<br />
<a href="http://lh5.ggpht.com/-aK58C-1VgoI/T6P9n5Py2pI/AAAAAAAAAG4/tyofVq17PD0/s1600-h/image%25255B3%25255D.png"><img alt="image" border="0" height="124" src="http://lh4.ggpht.com/-wqWCr9rv8p8/T6P9oV2nQII/AAAAAAAAAHA/YGvgPHiew1E/image_thumb%25255B1%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="230" /></a><br />
<br />
We would only need to test a total of 4 different axes to see if they separate the two shapes.<br />
<br />
This answers the question of which axes do we look at, but now we need a way to test if an axis actually separates the two shapes.<br />
<br />
To do this we ‘project’ each shape onto the axis which is perpendicular to the axis we are testing. <br />
So what does this mean exactly? We first rotate our separation axis by 90° so we get an axis which is perpendicular to the original axis, we will call this rotated axis the <strong>Projection Axis</strong>. <br />
<em><br /></em><br />
<em>Doing this with vectors is very simple, we simply multiply the axis Y component by –1 and then just swap the X and Y components:</em><br />
<br />
We then project the shapes onto the projection axis; We can imagine this as us drawing a line from each vertex in each shape to the projection axis like in the following diagram:<br />
<br />
<a href="http://lh4.ggpht.com/-PF-XAIkhHs8/T6P9ot0ibJI/AAAAAAAAAHI/fg9MWJ55OXI/s1600-h/image%25255B18%25255D.png"><img alt="image" border="0" height="219" src="http://lh3.ggpht.com/-dyjQA1VTkdU/T6P9pFk_iOI/AAAAAAAAAHQ/HCNPa-_yE3E/image_thumb%25255B15%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="290" /></a><br />
<span style="color: #797979;"><br /></span><br />
<span style="color: #797979;">When we project a vertex onto the projection axis, we end up with a number which tells us how far along the axis the line we drew crosses. This number is called the <strong>dot (<em>or sometimes the scalar</em>) product</strong> of the vertex and the projection axis. </span><br />
<span style="color: #797979;"><br /></span><br />
<span style="color: #797979;">As you can see from the diagram above, the biggest and smallest numbers will give us an interval on the projection axis which will represent the projected shape (e.g. <strong><span style="color: black;">r<sub>min</sub></span></strong> and <span style="color: black;"><strong>r<sub>max</sub></strong></span> define the interval of the rectangle).</span><br />
<span style="color: #797979;"><br /></span><br />
By using these intervals we turn a daunting 2D problem into a nice and simple 1D problem:<br />
<br />
<a href="http://lh3.ggpht.com/-3f9C49sQZzE/T6P9pUxOc8I/AAAAAAAAAHY/YE7d4Qqh82k/s1600-h/image%25255B33%25255D.png"><img alt="image" border="0" height="65" src="http://lh3.ggpht.com/-VdpTx4R8ecM/T6P9pqgpsUI/AAAAAAAAAHg/bKgjUFODRYs/image_thumb%25255B24%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="438" /></a><br />
<br />
To check if the axis we are testing separates the two shapes, we simply need to check whether their intervals on the projection axis overlap! In pseudo code the checks would look something like this:<br />
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">if</span> (tmin > rmax || rmin > tmax)
{
No collision!
}
<span style="color: blue;">else</span>
{
Collision occured!
}</pre>
<br /></div>
And that’s all there is to SAT!<br />
<br />
One of the big bonuses of using SAT is that it makes resolving a collision very easy for us! We already know how much the two shapes intersect each other by, so to make them stop intersecting we simply push each shape either forwards or backwards along the projection axis a distance equal to the amount of overlap / 2. (I will speak more on this in the next tutorial).<br />
<br />
And that concludes part 1, in part two we will be turning the method explained above into actual useable code! I hope you have enjoyed this tutorial and have found it useful! If anything wasn’t clear or was explained badly please let me know and I'll try to elaborate.FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com4tag:blogger.com,1999:blog-8967321114965538903.post-48994669741459711582012-03-24T13:08:00.001+00:002012-03-24T13:08:52.068+00:00Coming Soon...<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxPTH7ugRGTVM5qMebMCkL8dzyzStSf9LpKLfpLBryAvoBbRgENdwyWxG6k0O-fgL6xBOEMjApJO_qUgKD2nA' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com8tag:blogger.com,1999:blog-8967321114965538903.post-50897176586876978952012-03-07T16:51:00.003+00:002012-03-07T16:51:39.814+00:00WANTED : More Tutorials?Hi guys,<br />
<br />
It has been a while since I wrote any tutorials, mainly due to lack of time, but partly due to lack of inspiration... hopefully you can help me out here!<br />
<br />
What tutorials would you like to see written? (just to get it clear now, I am NOT writing a series on how to make an FPS, an RTS, an RPG etc... a whole book would most likely be too small for this... ;) )<br />
<br />
<br />FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com25tag:blogger.com,1999:blog-8967321114965538903.post-89518112860298525632012-02-02T12:29:00.001+00:002012-03-07T16:46:15.315+00:00Bug Fix : Tutorial 4 - WaypointsAs has been pointed out in the comments, in the fourth tutorial we added some code to check if the enemy has gotten close enough to the way point to move onto the next. This works well if the enemy is moving with a speed <= 1, however not so great if it moves with a speed of 2 for example.<br />
<br />
To fix this we simply change :<br />
<br />
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;"><span style="color: blue;">if</span> (DistanceToDestination < 1.0f)</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;">{</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;"> position = waypoints.Peek();</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;"> waypoints.Dequeue();</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;">}</pre>
<br />
to :<br />
<br />
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;"><span style="color: blue;">if</span> (DistanceToDestination < speed)</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;">{</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;"> position = waypoints.Peek();</pre>
<pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;"> waypoints.Dequeue();</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;">}</pre>
<pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 651px;"></pre>
<br />
Thanks for pointing this out Ryan! This was what I had intended to write but for some reason left the speed hard coded...FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com4tag:blogger.com,1999:blog-8967321114965538903.post-87302550056197297962011-12-25T11:11:00.001+00:002012-03-17T12:12:57.372+00:00Merry Christmas!As a very big thank you to all of those that have read this blog and helped improve it by pointing out my mistakes, I have decided to release an older version of my personal tower defence!<br />
<br />
It includes two different types of pathfinding, one that helps the enemies get to the end of the level, and one that detects if the player is “blocking”.<br />
<br />
The algorithm used to get the enemies to the end of the level is a variant of the breadth first algorithm. The algorithm generates a direction for each tile which points to a neighbouring tile. The neighbouring tile also contains a direction to a neighbouring tile; eventually if you just keep following the directions you follow a path to the goal!<br />
<br />
It also includes a basic level editor, however you will only be able to save levels using the shortcut <strong>Ctrl + S</strong>, though the code to load the levels is included!<br />
<br />
Just be warned the game isn’t at all balanced! <img alt="Winking smile" class="wlEmoticon wlEmoticon-winkingsmile" src="http://lh3.ggpht.com/-bJom6Fg_TAk/TvcE0JYvxlI/AAAAAAAAAGg/yXSGiHbAjCU/wlEmoticon-winkingsmile%25255B2%25255D.png?imgmax=800" style="border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none;" /><br />
<br />
<a href="http://www.mediafire.com/?mgegznzjcym" target="_blank">So here it is, Merry Christmas!</a>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com20tag:blogger.com,1999:blog-8967321114965538903.post-60155801963217875602011-12-10T19:31:00.000+00:002011-12-15T08:35:00.349+00:00A* Pathfinding Tutorial : Part 3Welcome to the final part of the A* pathfinding tutorial! In this tutorial we will be implementing the algorithm I described in part 2 in code!
<br />
<br />
At the start of this tutorial we will be adding some useful properties and methods to the SearchNode and Pathfinder classes that will make writing the FindPath method more simple.
<br />
<br />
Then to finish off I will post the full code for FindPath method indicating which piece of code relates to which step of the algorithm posted in the last tutorial!
<br />
<br />
<b><i>Edited on the 10/12/2011 at 8:00pm</i></b><br />
<a name='more'></a><br />
To start with we are going to add some of the properties that I described in the last tutorial to the <strong>SearchNode</strong> class :<br />
<br />
<style type="text/css">
.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br />
</style> <br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">/// <summary></span>
<span style="color: green;">/// A reference to the node that transfered this node to</span>
<span style="color: green;">/// the open list. This will be used to trace our path back</span>
<span style="color: green;">/// from the goal node to the start node.</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">public</span> SearchNode Parent;
<span style="color: green;">/// <summary></span>
<span style="color: green;">/// Provides an easy way to check if this node</span>
<span style="color: green;">/// is in the open list.</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> InOpenList;
<span style="color: green;">/// <summary></span>
<span style="color: green;">/// Provides an easy way to check if this node</span>
<span style="color: green;">/// is in the closed list.</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">public</span> <span style="color: blue;">bool</span> InClosedList;
<span style="color: green;">/// <summary></span>
<span style="color: green;">/// The approximate distance from the start node to the</span>
<span style="color: green;">/// goal node if the path goes through this node. (F)</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">public</span> <span style="color: blue;">float</span> DistanceToGoal;
<span style="color: green;">/// <summary></span>
<span style="color: green;">/// Distance traveled from the spawn point. (G)</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">public</span> <span style="color: blue;">float</span> DistanceTraveled;</pre>
<br /></div>
All of these properties are described in the last tutorial in detail so if you do not understand the role of one of the fields, I would suggest that you start by having a read of that!<br />
<br />
Next we are going to add the open and closed lists to the <b>Pathfinder </b>class as well as the <b>Heuristic </b>function :<br />
<br />
<div>
<span class="Apple-style-span" style="background-color: #f4f4f4; color: green; font-family: 'Courier New', courier, monospace; font-size: 11px; line-height: 16px; white-space: pre;">// Holds search nodes that are avaliable to search.</span></div>
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> List<SearchNode> openList = new List<SearchNode>();</pre>
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><searchnode style="color: black;"><span style="color: green;">// Holds the nodes that have already been searched.</span>
<span style="color: blue;">private</span> List<SearchNode> closedList = new List</searchnode><SearchNode>();</pre>
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><searchnode style="color: black;"><searchnode>
<span style="color: green;">/// <summary></span>
<span style="color: green;">/// Returns an estimate of the distance between two points. (H)</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">private</span> <span style="color: blue;">float</span> Heuristic(Point point1, Point point2)
{
<span style="color: blue;">return</span> Math.Abs(point1.X - point2.X) +
Math.Abs(point1.Y - point2.Y);
}</searchnode></searchnode></pre>
<br />
As mentioned in the last tutorial, the heuristic is a function that will give an estimate of the distance between two points, for this tutorial I am using what is called the Manhattan Distance which I beleive gives the best trade off between speed and accuracy. However there are many different heuristic functions out there that will give you a more accurate “shortest path” but will be a slower function! </div>
</div>
<br />
<div>
<div>
The next method we are going to add is the <b>ResetSearchNodes </b>method, this method will be responsible for “resetting” the pathfinder so that we can start a new search :</div>
</div>
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">/// <summary></span>
<span style="color: green;">/// Resets the state of the search nodes.</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">private</span> <span style="color: blue;">void</span> ResetSearchNodes()
{
openList.Clear();
closedList.Clear();
<span style="color: blue;">for</span> (<span style="color: blue;">int</span> x = 0; x < levelWidth; x++)
{
<span style="color: blue;">for</span> (<span style="color: blue;">int</span> y = 0; y < levelHeight; y++)
{
SearchNode node = searchNodes[x, y];
<span style="color: blue;">if</span> (node == <span style="color: blue;">null</span>)
{
<span style="color: blue;">continue</span>;
}
node.InOpenList = <span style="color: blue;">false</span>;
node.InClosedList = <span style="color: blue;">false</span>;
node.DistanceTraveled = <span style="color: blue;">float</span>.MaxValue;
node.DistanceToGoal = <span style="color: blue;">float</span>.MaxValue;
}
}
}</pre>
<br /></div>
This method resets the key properties used in the algorithm so that we can use this method again and again and still get valid paths. <br />
<br />
Another key method that we are going to add is the <b>FindBestNode </b>method. This method will search through the open list and finds the one with the smallest “Distance to Goal” :<br />
<br />
<div>
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 100%;"><span style="color: green;">/// <summary></span>
<span style="color: green;">/// Returns the node with the smallest distance to goal.</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">private</span> SearchNode FindBestNode()
{
SearchNode currentTile = openList[0];
<span style="color: blue;">float</span> smallestDistanceToGoal = <span style="color: blue;">float</span>.MaxValue;
<span style="color: green;">// Find the closest node to the goal.</span>
<span style="color: blue;">for</span> (<span style="color: blue;">int</span> i = 0; i < openList.Count; i++)
{
<span style="color: blue;">if</span> (openList[i].DistanceToGoal < smallestDistanceToGoal)
{
currentTile = openList[i];
smallestDistanceToGoal = currentTile.DistanceToGoal;
}
}
<span style="color: blue;">return</span> currentTile;
}</pre>
</div>
<br />
The first thing this method does create a new field called smallestDistanceToGoal and set it to be some massive number. We will use this field to keep a track of the smallest distance to the goal that we have found when looping over all the nodes. <br />
<br />
The next thing we do is loop through all of the nodes and compare each nodes DistanceToGoal to the smallestDistanceToGoal, and if the nodes DistanceToGoal is smaller, than this node becomes the best node we have found so far. This type of method is very common in programming.<br />
<br />
The last helper method that we are going to add is one that will find the final path; we use the parent pointer of the goal node to trace a path back to the start node:<br />
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; width: 100%;"><span style="color: green;">/// <summary></span>
<span style="color: green;">/// Use the parent field of the search nodes to trace</span>
<span style="color: green;">/// a path from the end node to the start node.</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">private</span> List<Vector2> FindFinalPath(SearchNode startNode, SearchNode endNode)
{
closedList.Add(endNode);
SearchNode parentTile = endNode.Parent;
<span style="color: green;">// Trace back through the nodes using the parent fields</span>
<span style="color: green;">// to find the best path.</span>
<span style="color: blue;">while</span> (parentTile != startNode)
{
closedList.Add(parentTile);
parentTile = parentTile.Parent;
}
List<Vector2> finalPath = <span style="color: blue;">new</span> List<Vector2>();
<span style="color: green;">// Reverse the path and transform into world space.</span>
<span style="color: blue;">for</span> (<span style="color: blue;">int</span> i = closedList.Count - 1; i >= 0; i--)
{
finalPath.Add(<span style="color: blue;">new</span> Vector2(closedList[i].Position.X * 32,
closedList[i].Position.Y * 32));
}
<span style="color: blue;">return</span> finalPath;
}</pre>
<br /></div>
And now to add the method that you no doubt have been waiting for! The <b>FindPath </b>method follows the exact same logic as the algorithm posted in the last tutorial:<br />
<br />
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper">
<div>
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">/// <summary></span>
<span style="color: green;">/// Finds the optimal path from one point to another.</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">public</span> List<Vector2> FindPath(Point startPoint, Point endPoint)
{
<span style="color: green;">// Only try to find a path if the start and end points are different.</span>
<span style="color: blue;">if</span> (startPoint == endPoint)
{
<span style="color: blue;">return</span> <span style="color: blue;">new</span> List<Vector2>();
}
<span style="color: green;">/////////////////////////////////////////////////////////////////////</span>
<span style="color: green;">// Step 1 : Clear the Open and Closed Lists and reset each node’s F </span>
<span style="color: green;">// and G values in case they are still set from the last </span>
<span style="color: green;">// time we tried to find a path. </span>
<span style="color: green;">/////////////////////////////////////////////////////////////////////</span>
ResetSearchNodes();
<span style="color: green;">// Store references to the start and end nodes for convenience.</span>
SearchNode startNode = searchNodes[startPoint.X, startPoint.Y];
SearchNode endNode = searchNodes[endPoint.X, endPoint.Y];
<span style="color: green;">/////////////////////////////////////////////////////////////////////</span>
<span style="color: green;">// Step 2 : Set the start node’s G value to 0 and its F value to the </span>
<span style="color: green;">// estimated distance between the start node and goal node </span>
<span style="color: green;">// (this is where our H function comes in) and add it to the </span>
<span style="color: green;">// Open List. </span>
<span style="color: green;">/////////////////////////////////////////////////////////////////////</span>
startNode.InOpenList = <span style="color: blue;">true</span>;
startNode.DistanceToGoal = Heuristic(startPoint, endPoint);
startNode.DistanceTraveled = 0;
openList.Add(startNode);
<span style="color: green;">/////////////////////////////////////////////////////////////////////</span>
<span style="color: green;">// Setp 3 : While there are still nodes to look at in the Open list : </span>
<span style="color: green;">/////////////////////////////////////////////////////////////////////</span>
<span style="color: blue;">while</span> (openList.Count > 0)
{
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
<span style="color: green;">// a) : Loop through the Open List and find the node that </span>
<span style="color: green;">// has the smallest F value.</span>
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
SearchNode currentNode = FindBestNode();
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
<span style="color: green;">// b) : If the Open List empty or no node can be found, </span>
<span style="color: green;">// no path can be found so the algorithm terminates.</span>
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
<span style="color: blue;">if</span> (currentNode == <span style="color: blue;">null</span>)
{
<span style="color: blue;">break</span>;
}
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
<span style="color: green;">// c) : If the Active Node is the goal node, we will </span>
<span style="color: green;">// find and return the final path.</span>
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
<span style="color: blue;">if</span> (currentNode == endNode)
{
<span style="color: green;">// Trace our path back to the start.</span>
<span style="color: blue;">return</span> FindFinalPath(startNode, endNode);
}
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
<span style="color: green;">// d) : Else, for each of the Active Node’s neighbours :</span>
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
<span style="color: blue;">for</span> (<span style="color: blue;">int</span> i = 0; i < currentNode.Neighbors.Length; i++)
{
SearchNode neighbor = currentNode.Neighbors[i];
<span style="color: green;">//////////////////////////////////////////////////</span>
<span style="color: green;">// i) : Make sure that the neighbouring node can </span>
<span style="color: green;">// be walked across. </span>
<span style="color: green;">//////////////////////////////////////////////////</span>
<span style="color: blue;">if</span> (neighbor == <span style="color: blue;">null</span> || neighbor.Walkable == <span style="color: blue;">false</span>)
{
<span style="color: blue;">continue</span>;
}
<span style="color: green;">//////////////////////////////////////////////////</span>
<span style="color: green;">// ii) Calculate a new G value for the neighbouring node.</span>
<span style="color: green;">//////////////////////////////////////////////////</span>
<span style="color: blue;">float</span> distanceTraveled = currentNode.DistanceTraveled + 1;
<span style="color: green;">// An estimate of the distance from this node to the end node.</span>
<span style="color: blue;">float</span> heuristic = Heuristic(neighbor.Position, endPoint);
<span style="color: green;">//////////////////////////////////////////////////</span>
<span style="color: green;">// iii) If the neighbouring node is not in either the Open </span>
<span style="color: green;">// List or the Closed List : </span>
<span style="color: green;">//////////////////////////////////////////////////</span>
<span style="color: blue;">if</span> (neighbor.InOpenList == <span style="color: blue;">false</span> && neighbor.InClosedList == <span style="color: blue;">false</span>)
{
<span style="color: green;">// (1) Set the neighbouring node’s G value to the G value </span>
<span style="color: green;">// we just calculated.</span>
neighbor.DistanceTraveled = distanceTraveled;
<span style="color: green;">// (2) Set the neighbouring node’s F value to the new G value + </span>
<span style="color: green;">// the estimated distance between the neighbouring node and</span>
<span style="color: green;">// goal node.</span>
neighbor.DistanceToGoal = distanceTraveled + heuristic;
<span style="color: green;">// (3) Set the neighbouring node’s Parent property to point at the Active </span>
<span style="color: green;">// Node.</span>
neighbor.Parent = currentNode;
<span style="color: green;">// (4) Add the neighbouring node to the Open List.</span>
neighbor.InOpenList = <span style="color: blue;">true</span>;
openList.Add(neighbor);
}
<span style="color: green;">//////////////////////////////////////////////////</span>
<span style="color: green;">// iv) Else if the neighbouring node is in either the Open </span>
<span style="color: green;">// List or the Closed List :</span>
<span style="color: green;">//////////////////////////////////////////////////</span>
<span style="color: blue;">else</span> <span style="color: blue;">if</span> (neighbor.InOpenList || neighbor.InClosedList)
{
<span style="color: green;">// (1) If our new G value is less than the neighbouring </span>
<span style="color: green;">// node’s G value, we basically do exactly the same </span>
<span style="color: green;">// steps as if the nodes are not in the Open and </span>
<span style="color: green;">// Closed Lists except we do not need to add this node </span>
<span style="color: green;">// the Open List again.</span>
<span style="color: blue;">if</span> (neighbor.DistanceTraveled > distanceTraveled)
{
neighbor.DistanceTraveled = distanceTraveled;
neighbor.DistanceToGoal = distanceTraveled + heuristic;
neighbor.Parent = currentNode;
}
}
}
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
<span style="color: green;">// e) Remove the Active Node from the Open List and add it to the </span>
<span style="color: green;">// Closed List</span>
<span style="color: green;">/////////////////////////////////////////////////////////////////</span>
openList.Remove(currentNode);
currentNode.InClosedList = <span style="color: blue;">true</span>;
}
<span style="color: green;">// No path could be found.</span>
<span style="color: blue;">return</span> <span style="color: blue;">new</span> List<Vector2>();
}</pre>
</div>
<br />
And that is all there is to A-Star! The last thing we are going to do in this tutorial is a quick example of how to use the FindPath method!<br />
<br />
The first thing you need to do is go to <b>Game1.cs</b> and at the top of the class add a field for the pathfinder :<br />
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">Pathfinder pathfinder;</pre>
<br /></div>
Next, we go to the <b>Initialize </b>method and add the following:<br />
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">pathfinder = <span style="color: blue;">new</span> Pathfinder(map);
List<Vector2> path = pathfinder.FindPath(<span style="color: blue;">new</span> Point(0, 0), <span style="color: blue;">new</span> Point(9, 9));
<span style="color: blue;">foreach</span> (Vector2 point <span style="color: blue;">in</span> path)
{
System.Diagnostics.Debug.WriteLine(point);
}</pre>
<br /></div>
After we initialize the pathfinder, we use it for the first time! We find a path from the top left corner to the bottom right corner and we output the points that make up the path to the output window!<br />
<br />
And there you have, you now have the means to make your enemies that little bit smatter!<br />
<br />
Thank you for reading and I hope you have enjoyed this tutorial series!<br />
<br />
<div>
<a href="http://www.mediafire.com/file/69f9ax9j7bjog2w/AStarPathfinding.zip">Here if the code for this tutorial.</a></div>
</div>
</div>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com22tag:blogger.com,1999:blog-8967321114965538903.post-3729839897913554452011-08-04T20:37:00.003+01:002011-08-27T09:02:10.132+01:00A* Pathfinding Tutorial : Part 2<p><span>Welcome to part two in my series on pathfinding. In this tutorial we will be looking at the actual A* algorithm before we actually start implementing it in code in the next tutorial. </span></p> <p><span>This tutorial will be mostly theory based with very little coding so please stick with it as it is really important to understand the actual algorithm before trying to translate it into code!</span></p> <a name='more'></a> <p><span>Before we can start looking at how the A* algorithm actually works, we will need to define a few key terms that will make describing the algorithm a lot easer :</span></p> <ul> <li><span>The <strong><span>G</span></strong> Value – Each node will have an associated <strong>G</strong> value, this is how far we would have to travel to get from the starting node to this node. </span> </li><li><span>The <strong>H</strong> Function (<span>The Heuristic Function)</span> – This is a method that will help us to estimate how far we would have to move to get from one node to another node “as the crow flies”. The method will not take into account any obstacles which is why it will only be an estimate.</span> </li><li><span>The <strong><span>F</span></strong> Value – Each node will also have an associated <strong>F</strong> value. This is a rough estimate of how far we would have to travel to get from the starting node to the end node if the path crosses this node. To work out an <strong><span>F</span></strong> value we can do the following : <strong>F</strong> = <strong>G</strong> + <strong>H – </strong>it is basically how far we will have already had to travel to get to this node add a rough estimate of how much further we need to travel.</span> </li><li>The <strong>Open List</strong> – This is basically a big list of all the nodes that are being considered to be included in the final path. </li><li>The <strong>Closed List</strong> – This is a list of all of the nodes that have already have been looked at, we will use this to make sure we don’t consider each node more than once. </li><li>The <strong>Parent</strong> Reference – Each node will have a reference to the node that added this node to the <strong>Open List</strong>. When the algorithm has finished, we will use the reference to the node’s <strong>Parent </strong>to trace the final path from the end node to the start node ( I will cover this in more detail later ).</li></ul> <p>So now that we have all of the definitions out of the way we can look at the actual algorithm, if at first it seems to make no sense, don’t worry about it, just try and keep reading it through and then when we come to actually implement it in code it should make a lot more sense. It will normally take a couple of implementations to fully understand the algorithm. </p> <p>So basically the algorithm works like this :</p> <p style="line-height: 13pt; text-indent: -17.85pt; margin: 0cm 0cm 6pt 17.85pt; mso-list: l0 level1 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">1)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Clear the </span></span><span style="font-size: 10pt"><b><span style="color: ; mso-themecolor: accent6"><span>Open</span></span></b><span> and </span><b><span style="color: ; mso-themecolor: accent6"><span>Closed</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>Lists</span></span></b><span> and reset each node’s </span><b><span style="color: ; mso-themecolor: accent6"><span>F</span></span></b><span> and </span><b><span style="color: ; mso-themecolor: accent6"><span>G</span></span></b><span> values in case they are still set from the last time we tried to find a path. </span></span></span></p> <p style="line-height: 13pt; text-indent: -18pt; margin: 0cm 0cm 6pt 18pt; mso-list: l0 level1 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">2)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Set the start node’s </span></span><span style="font-size: 10pt"><b><span style="color: ; mso-themecolor: accent6"><span>G</span></span></b><span> value to 0 and its </span><b><span style="color: ; mso-themecolor: accent6"><span>F</span></span></b><span> value to the estimated distance between the start node and goal node (this is where our </span><b><span style="color: ; mso-themecolor: accent6"><span>H</span></span></b><span> function comes in) and add it to the </span><b><span style="color: ; mso-themecolor: accent6"><span>Open</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>List</span></span></b><span>. </span></span></span></p> <p style="line-height: 13pt; text-indent: -18pt; margin: 0cm 0cm 6pt 18pt; mso-list: l0 level1 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">3)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">While there are still nodes to look at in the </span></span><span style="font-size: 10pt"><b><span style="color: ; mso-themecolor: accent6"><span>Open</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>list</span></span><span> :</span></b><span> </span></span></span></p> <p style="line-height: 13pt; text-indent: -17.85pt; margin: 0cm 0cm 6pt 36pt; mso-list: l0 level2 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">a)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Loop through the </span></span><span style="font-size: 10pt"><b><span style="color: ; mso-themecolor: accent6"><span>Open</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>List</span></span></b><span> and find the node that has the smallest </span><b><span style="color: ; mso-themecolor: accent6"><span>F</span></span></b><span> value (We will refer to this node as the <b style="mso-bidi-font-weight: normal">Active Node</b>).</span></span></span></p> <p style="line-height: 13pt; text-indent: -17.85pt; margin: 0cm 0cm 6pt 36pt; mso-list: l0 level2 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">b)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">If the </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>Open List</span></span></b><span> empty or no node can be found, no path can be found so the algorithm terminates.</span></span></span></p> <p style="line-height: 13pt; text-indent: -17.85pt; margin: 0cm 0cm 6pt 36pt; mso-list: l0 level2 lfo1" class="MsoListParagraph"><span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span style="font-size: 10pt">c)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span style="font-size: 10pt">If the <b style="mso-bidi-font-weight: normal">Active Node</b> is the goal node, we will find and return the final path.</span></span></span></p> <p style="line-height: 13pt; text-indent: -17.85pt; margin: 0cm 0cm 6pt 36pt; mso-list: l0 level2 lfo1" class="MsoListParagraph"><span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span style="font-size: 10pt">d)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span style="font-size: 10pt">Else, for each of the <b style="mso-bidi-font-weight: normal">Active Node’s</b> neighbours :</span></span></span></p> <p style="line-height: 13pt; text-indent: -17.85pt; margin: 0cm 0cm 6pt 54pt; mso-list: l0 level3 lfo1" class="MsoListParagraph"><span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span style="font-size: 10pt">i)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span style="font-size: 10pt">Make sure that the neighbouring node can be walked across. </span></span></span></p> <p style="line-height: 13pt; text-indent: -17.85pt; margin: 0cm 0cm 6pt 54pt; mso-list: l0 level3 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">ii)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Calculate a new </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>G</span></span></b><span> value for the neighbouring node ( This will be the </span><b style="mso-bidi-font-weight: normal"><span>Active Node’s </span><span style="color: ; mso-themecolor: accent6"><span>G</span></span></b><span> value + the cost of moving to the neighbour node – I will discuss this later)</span></span></span></p> <p style="line-height: 13pt; text-indent: -17.85pt; margin: 0cm 0cm 6pt 54pt; mso-list: l0 level3 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">iii)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">If the neighbouring node is not in either the </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>Open</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>List</span></span><span> </span></b><span>or<b style="mso-bidi-font-weight: normal"> </b>the</span><b style="mso-bidi-font-weight: normal"><span> </span><span style="color: ; mso-themecolor: accent6"><span>Closed</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>List</span></span></b><span> : </span></span></span></p> <p style="line-height: 13pt; text-indent: -18pt; margin: 0cm 0cm 6pt 72pt; mso-list: l0 level4 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">(1)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Set the neighbouring node’s </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>G</span></span></b><span> value to the </span><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>G</span></span></b><span> value we just calculated.</span></span></span></p> <p style="line-height: 13pt; text-indent: -18pt; margin: 0cm 0cm 6pt 72pt; mso-list: l0 level4 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">(2)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Set the neighbouring node’s </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>F</span></span></b><span> value to the new </span><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>G</span></span></b><span> value + the estimated distance between the neighbouring node and goal node.</span></span></span></p> <p style="line-height: 13pt; text-indent: -18pt; margin: 0cm 0cm 6pt 72pt; mso-list: l0 level4 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">(3)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Set the neighbouring node’s </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>Parent</span></span></b><span> property to point at the <b style="mso-bidi-font-weight: normal">Active Node</b>.</span></span></span></p> <p style="line-height: 13pt; text-indent: -18pt; margin: 0cm 0cm 6pt 72pt; mso-list: l0 level4 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">(4)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Add the neighbouring node to the </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>Open</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>List</span></span></b><span>.</span></span></span></p> <p style="line-height: 13pt; text-indent: -18pt; margin: 0cm 0cm 6pt 54pt; mso-list: l0 level3 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">iv)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Else if the neighbouring node is in either the </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>Open</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>List</span></span><span> </span></b><span>or<b style="mso-bidi-font-weight: normal"> </b>the</span></span><b style="mso-bidi-font-weight: normal"><span style="font-size: 10pt"><span> </span><span style="color: ; mso-themecolor: accent6"><span>Closed</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>List</span></span><span> :</span></span></b></span></p> <p style="line-height: 13pt; text-indent: -18pt; margin: 0cm 0cm 6pt 72pt; mso-list: l0 level4 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">(1)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">If our new </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>G</span></span></b><span> value is less than the neighbouring node’s </span><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>G</span></span></b><span> value, we basically do exactly the same steps as if the nodes are not in the </span><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>Open</span></span></b><span> and </span><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>Closed</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>Lists</span></span></b><span> except we do not need to add this node the </span><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>Open</span></span><span> </span><span style="color: ; mso-themecolor: accent6"><span>List</span></span></b><span> again.</span></span></span></p> <p style="line-height: 13pt; text-indent: -18pt; margin: 0cm 0cm 6pt 36pt; mso-list: l0 level2 lfo1" class="MsoListParagraph"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb; mso-fareast-font-family: arial"><span style="mso-list: ignore"><span><span style="font-size: 10pt">e)</span><span style="line-height: normal; font-family: "><span><span style="font-size: 7pt"> </span></span></span></span></span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span><span style="font-size: 10pt">Remove the <b style="mso-bidi-font-weight: normal">Active Node</b> from the </span></span><span style="font-size: 10pt"><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>Open</span></span></b><span> </span><b style="mso-bidi-font-weight: normal"><span style="color: ; mso-themecolor: accent6"><span>List</span></span></b><span> and add it to the </span></span><b style="mso-bidi-font-weight: normal"><span style="font-size: 10pt"><span style="color: ; mso-themecolor: accent6"><span>Closed</span></span><span> </span></span><span style="color: ; mso-themecolor: accent6"><span style="font-size: 10pt">List</span></span></b></span></p> <p style="line-height: 13pt; margin: 0cm 0cm 6pt" class="MsoNormal"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span style="font-size: 10pt"> </span></span></p> <p style="line-height: 13pt; margin: 0cm 0cm 6pt" class="MsoNormal"><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span>And that’s all that this algorithm does, it basically just takes the node that is ‘closest’ to the goal node and keeps hoping across the neighbouring nodes until it reaches the goal node. </span></span></p> <p>In <span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span>the next tutorial, we will be going through this algorithm step by step and implementing it in code, but in the mean time I would highly recommend that you try and code this by yourself first! </span></span><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span>I know it may look pretty complicated but if you break follow it through step by step it is actually pretty simple. </span></span></p> <p><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span>The first thing you will need to do is add the new fields to the SearchNode class, a couple of floats for the <strong>F </strong>and <strong>G</strong> values and a SearchNode property for the <strong>Parent</strong> field. Then our Pathfinder class is going to need two new lists to represent the <strong>Open </strong>and <strong>Closed</strong> <strong>Lists.</strong></span></span></p> <p><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span>The only thing that won’t be easy to code is the code that will return the final path, but you can always just miss that step… ;)</span></span></p> <p><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span>I hope you have found this tutorial useful and please let me know if anything in it was poorly explained or not explained in enough detailed or even is something was missed out completely and I will do my best to fix it.</span></span></p> <p><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><span>Thank you for reading!</span></span></p> <p><span style="line-height: 12pt; font-family: ; mso-fareast-language: en-gb"><em>I would just like to mention a few of the sources that helped me when I was learning about A* :</em></span></p> <ul> <li><em>“</em><a href="http://www.policyalmanac.org/games/aStarTutorial.htm"><em>http://www.policyalmanac.org/games/aStarTutorial.htm</em></a><em>” (Patrick Lester)</em></li> <li><em>“</em><a href="http://en.wikipedia.org/wiki/A*_search_algorithm"><em>http://en.wikipedia.org/wiki/A*_search_algorithm</em></a><em>”</em></li> <li><em>“Programming and RTS Game with Direct3D” (Carl Granberg)</em></li></ul> FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com16tag:blogger.com,1999:blog-8967321114965538903.post-62672045355305250272011-06-26T13:56:00.004+01:002011-08-27T09:02:23.698+01:00A* Pathfinding Tutorial : Part 1<p>Welcome to part one of my two part series on path finding!</p> <p>In this first part we will be looking at the amazing <strong>A*</strong> (A-Star) pathfinding algorithm which is probably one of the most precise and performance friendly pathfinding algorithm out there at the moment.</p> <p>In part two I am going to show you that although <strong>A*</strong> is great, that it isn’t always the best algorithm for the job. I will be showing you how we can add pathfinding to the tower defence game made in the previous series using a Breadth First algorithm.</p> <a name='more'></a> <p>The first thing we are going to do talk about before we get onto the algorithm itself is the world in which the pathfinding will take place. </p> <p>Imagine we have a very simple level like this and we want to get from the red flag to the yellow flag. </p> <p><a href="http://lh5.ggpht.com/-8ufSePhTnkM/TgcsWROIgBI/AAAAAAAAAGA/0UKtR1lE0Qo/s1600-h/example2%25255B6%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="example2" border="0" alt="example2" src="http://lh4.ggpht.com/-ab1TbbSXK4U/TgcsW5Y5--I/AAAAAAAAAGE/nJzUMPHz0CE/example2_thumb%25255B2%25255D.png?imgmax=800" width="164" height="100" /></a></p> <p>The first thing that we will need to do to find a path is split the level up into a <strong>grid</strong>. </p> <p><a href="http://lh4.ggpht.com/-c5SiOMP6lqA/TgcsXoViOnI/AAAAAAAAAGI/csQpxW5U2dU/s1600-h/example3%25255B2%25255D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="example3" border="0" alt="example3" src="http://lh3.ggpht.com/-1f94uodrHTM/TgcsYEHbUvI/AAAAAAAAAGM/Ft_uD7e5ARg/example3_thumb.png?imgmax=800" width="164" height="100" /></a></p> <p>This allows us to simplify the level down to a series of squares, some that can be walked across, and some that are blocked. Each of these squares (or nodes) represent a tile that our path might pass over. We call the squares around a node the nodes neighbours. </p> <p>So, lets implement what we have just talked about in code. I have made a project that I will be using as the starting code for this tutorial; all it does is create a level and draw it to the screen. </p> <p><a href="http://www.mediafire.com/file/q954jqws1v45s5l/AStarPathfinding%20Start.zip">It can be downloaded here.</a></p> <p>Once you have opened up the project you will need to find and open <strong>Pathfinder.cs</strong> and you should see two empty classes ready for us to get started with! The <strong>SearchNode</strong> class will represent one of our pathfinding nodes.</p> <p>So lets start by padding it out with some useful fields :</p> <div id="codeSnippetWrapper"> <div><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// <summary></span>
<br /><span style="color: #008000">/// Reresents one node in the search space</span>
<br /><span style="color: #008000">/// </summary></span>
<br /><span style="color: #0000ff">private</span> <span style="color: #0000ff">class</span> SearchNode
<br />{
<br /><span style="color: #008000">/// <summary></span>
<br /><span style="color: #008000">/// Location on the map</span>
<br /><span style="color: #008000">/// </summary></span>
<br /><span style="color: #0000ff">public</span> Point Position;
<br /><span style="color: #008000">/// <summary></span>
<br /><span style="color: #008000">/// If true, this tile can be walked on.</span>
<br /><span style="color: #008000">/// </summary></span>
<br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> Walkable;
<br />
<br /><span style="color: #008000">/// <summary></span>
<br /><span style="color: #008000">/// This contains references to the for nodes surrounding </span>
<br /><span style="color: #008000">/// this tile (Up, Down, Left, Right).</span>
<br /><span style="color: #008000">/// </summary></span>
<br /><span style="color: #0000ff">public</span> SearchNode[] Neighbors;
<br />}</pre></div>
<br /><div>There is nothing too scary there, the first field is to keep track of where the node is on our map. The second field defines if the node can be walked on or not! The last field will keep track of the other nodes that surround this node.</div><div>
<br /></div><div>Now that we have our node defined we will concentrate on the <strong>Pathfinder</strong> class! This is where all of the magic will happen. Add the following fields and the constructor to the top of the <strong>Pathfinder</strong> class :</div></div><div id="codeSnippetWrapper">
<br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Stores an array of the walkable search nodes.</span>
<br /><span style="color: #0000ff">private</span> SearchNode[,] searchNodes;
<br />
<br /><span style="color: #008000">// The width of the map.</span>
<br /><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> levelWidth;
<br /><span style="color: #008000">// The height of the map.</span>
<br /><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> levelHeight;
<br />
<br /><span style="color: #008000">/// <summary></span>
<br /><span style="color: #008000">/// Constructor.</span>
<br /><span style="color: #008000">/// </summary></span>
<br /><span style="color: #0000ff">public</span> Pathfinder(Map map)
<br />{
<br />levelWidth = map.Width;
<br />levelHeight = map.Height;
<br />}</pre></div></div><p>The first node is a 2D array that will keep track of our search nodes, it is in the same format as the layout array in our map class. This is because one tile from our map class will be represented by one of our search nodes!</p><p>The other two fields just help us keep track of how big the level is. Next we are going to add a new method to the class, this will be the method responsible for splitting our level up into a grid. Add this method just underneath the constructor :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// <summary></span>
<br /><span style="color: #008000">/// Splits our level up into a grid of nodes.</span>
<br /><span style="color: #008000">/// </summary></span>
<br /><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> InitializeSearchNodes(Map map)
<br />{
<br />
<br />}</pre></div><p>Before we start padding out this method, we need to make sure that it is called in the <strong>Pathfinder’s</strong> constructor, so add this line at the bottom of the <strong>Constructor</strong> :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">InitializeSearchNodes(map);</pre></div><p>Ok we are now ready to start padding at the <strong>InitializeSearchNodes</strong> method. Let’s start by adding the following code to the <strong>InitializeSearchNodes</strong> method :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">searchNodes = <span style="color: #0000ff">new</span> SearchNode[levelWidth, levelHeight];
<br />
<br /><span style="color: #008000">//For each of the tiles in our map, we</span>
<br /><span style="color: #008000">// will create a search node for it.</span>
<br /><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> x = 0; x < levelWidth; x++)
<br />{
<br /><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> y = 0; y < levelHeight; y++)
<br />{
<br /> <span style="color: #008000">//Create a search node to represent this tile.</span>
<br /> SearchNode node = <span style="color: #0000ff">new</span> SearchNode();
<br />
<br /> node.Position = <span style="color: #0000ff">new</span> Point(x, y);
<br />
<br /> <span style="color: #008000">// Our enemies can only walk on grass tiles.</span>
<br /> node.Walkable = map.GetIndex(x, y) == 0;
<br />
<br /> <span style="color: #008000">// We only want to store nodes</span>
<br /> <span style="color: #008000">// that can be walked on.</span>
<br /> <span style="color: #0000ff">if</span> (node.Walkable == <span style="color: #0000ff">true</span>)
<br /> {
<br /> node.Neighbors = <span style="color: #0000ff">new</span> SearchNode[4];
<br /> searchNodes[x, y] = node;
<br /> }
<br />}
<br />}</pre></div><p>We start off by initializing the grid of nodes that we defined earlier. Next, for every tile on the map, we create a new search node to represent it. Note that we don’t set up the references to the neighbour nodes just yet, first we need to create all of the nodes before we can start referencing them!</p><p>Next just below that code add the following :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Now for each of the search nodes, we will</span>
<br /><span style="color: #008000">// connect it to each of its neighbours.</span>
<br /><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> x = 0; x < levelWidth; x++)
<br />{
<br /><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> y = 0; y < levelHeight; y++)
<br />{
<br /> SearchNode node = searchNodes[x, y];
<br />
<br /> <span style="color: #008000">// We only want to look at the nodes that </span>
<br /> <span style="color: #008000">// our enemies can walk on.</span>
<br /> <span style="color: #0000ff">if</span> (node == <span style="color: #0000ff">null</span> || node.Walkable == <span style="color: #0000ff">false</span>)
<br /> {
<br /> <span style="color: #0000ff">continue</span>;
<br /> }
<br />
<br /> <span style="color: #008000">// An array of all of the possible neighbors this </span>
<br /> <span style="color: #008000">// node could have. (We will ignore diagonals for now.)</span>
<br /> Point[] neighbors = <span style="color: #0000ff">new</span> Point[]
<br /> {
<br /> <span style="color: #0000ff">new</span> Point (x, y - 1), <span style="color: #008000">// The node above the current node</span>
<br /> <span style="color: #0000ff">new</span> Point (x, y + 1), <span style="color: #008000">// The node below the current node.</span>
<br /> <span style="color: #0000ff">new</span> Point (x - 1, y), <span style="color: #008000">// The node left of the current node.</span>
<br /> <span style="color: #0000ff">new</span> Point (x + 1, y), <span style="color: #008000">// The node right of the current node</span>
<br /> };
<br />
<br /> <span style="color: #008000">// We loop through each of the possible neighbors</span>
<br /> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i < neighbors.Length; i++)
<br /> {
<br /> Point position = neighbors[i];
<br />
<br /> <span style="color: #008000">// We need to make sure this neighbour is part of the level.</span>
<br /> <span style="color: #0000ff">if</span> (position.X < 0 || position.X > levelWidth - 1 ||
<br /> position.Y < 0 || position.Y > levelHeight - 1)
<br /> {
<br /> <span style="color: #0000ff">continue</span>;
<br /> }
<br />
<br /> SearchNode neighbor = searchNodes[position.X, position.Y];
<br />
<br /> <span style="color: #008000">// We will only bother keeping a reference </span>
<br /> <span style="color: #008000">// to the nodes that can be walked on.</span>
<br /> <span style="color: #0000ff">if</span> (neighbor == <span style="color: #0000ff">null</span> || neighbor.Walkable == <span style="color: #0000ff">false</span>)
<br /> {
<br /> <span style="color: #0000ff">continue</span>;
<br /> }
<br />
<br /> <span style="color: #008000">// Store a reference to the neighbor.</span>
<br /> node.Neighbors[i] = neighbor;
<br /> }
<br />}
<br />}</pre>
<br /></div>I know the length of this snippet may be quite daunting, but the code code is actually pretty simple! We loop through all of our search nodes, and if the node can be walked on, we look at all of the possible neighbours for that node. If the neighbour is part of the level and can be walked on, we keep a reference to it. It’s as simple as that!
<br /><p>And that is all we will be doing on the pathfinder in this tutorial. The last thing we are going to do is create an instance of the pathfinder in the game class, so go to <strong>Game1.cs</strong> and at the top add the following field :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">Pathfinder pathfinder;</pre></div><p>Next go to the <strong>Initialize</strong> method and add the following :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">pathfinder = <span style="color: #0000ff">new</span> Pathfinder(map);</pre></div><p>And we are finished for this part of the tutorial, I know it doesn’t seem like we have done much, but we have just laid down the foundations for our pathfinder! </p><p>Next time we will actually look at the algorithm in more depth before we get to work implementing it in code.</p>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com31tag:blogger.com,1999:blog-8967321114965538903.post-36126255527100989342011-04-08T16:48:00.005+01:002013-01-31T19:38:48.312+00:00Tutorial 15 : Adding Health Bars – ExtendedUp until now, we use the enemies colour to represent his health, and while this works quite nicely for our little black blob, it doesn’t work so well with more complex sprites.<br />
In this tutorial we are going to add little health bars that will float above our enemies heads. A lot of the code in this tutorial has been inspired from <a href="http://www.xnadevelopment.com/tutorials/notsohealthy/NotSoHealthy.shtml">George Clingerman’s amazing tutorial on health bars</a>. So if you are struggling with this tutorial, I would recommend reading his first as he explains it in more depth than I will.<br />
<a name='more'></a>The first thing that we’re going to do is stop the enemies colour from changing when the enemy loses health. <em>If you still want this to happen just skip over this next bit.</em><br />
To do that we need to go to <strong>Enemy.cs</strong> and find the <strong>Draw</strong> method. Then you need to replace these lines :<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">float</span> healthPercentage = (<span style="color: blue;">float</span>)currentHealth / (<span style="color: blue;">float</span>)startHealth;
Color color = <span style="color: blue;">new</span> Color(<span style="color: blue;">new</span> Vector3(1 - healthPercentage,
1 - healthPercentage, 1 - healthPercentage));
<span style="color: blue;">base</span>.Draw(spriteBatch, color);</pre>
</div>
<br />
<div>
With this :</div>
<div id="codeSnippetWrapper">
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">base</span>.Draw(spriteBatch, Color.Black);</pre>
</div>
<br />
<div>
Now instead of tinting our sprite a different colour based on it’s health percentage, we just draw it black.</div>
</div>
<br />
<div>
While we are still in <strong>Enemy.cs</strong> we are going to add a new property to keep track of how much health an enemy has left :</div>
<div>
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper">
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">/// <summary></span>
<span style="color: green;">/// The % of health that an enemy has left</span>
<span style="color: green;">/// </summary></span>
<span style="color: blue;">public</span> <span style="color: blue;">float</span> HealthPercentage
{
get { <span style="color: blue;">return</span> currentHealth / startHealth; }
}</pre>
<br /></div>
With that done, we can move onto drawing the health bars! The first thing we need to do is add a new texture to the content project :</div>
<div>
<a href="http://lh4.ggpht.com/_q2VraDVN7Lg/TZ8uVoGKgMI/AAAAAAAAAFs/9bsZCkom0CM/s1600-h/health-bar6.png"><span style="color: black;"><img alt="health bar" src="http://lh4.ggpht.com/_q2VraDVN7Lg/TZ8uWO8gx5I/AAAAAAAAAFw/kseAuOdTTFM/health-bar_thumb4.png?imgmax=800" style="display: block; float: none; margin-left: auto; margin-right: auto;" title="health bar" /></span></a></div>
</div>
</div>
</div>
<i><br /></i>
<i>Note : This texture should be called "health bar.png" however it's name get messed up when I uploaded it!</i><br />
<br />
<div>
This is the texture we are going to use for the health bar. The reason that it is just white at the moment is so that we can easily tint it different colours when we draw it.<br />
<br /></div>
<div>
We are going to draw our health bars in the Wave class, so go to <strong>Wave.cs</strong> and at the top of the class, add the following field :<br />
<br />
<div>
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> Texture2D healthTexture; // A texture <span style="color: blue;">for</span> the health bar.</pre>
</div>
<br />
<div>
We will use this field to store the texture we just added.</div>
<div>
<br /></div>
<div>
Next we are going to change a couple of constructors so we can pass our texture to this class. Seeing as we are already looking at the wave class, we will start by changing the Wave constructor. Find the <strong>Wave</strong> constructor and change it so it looks like this :</div>
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> Wave(<span style="color: blue;">int</span> waveNumber, <span style="color: blue;">int</span> numOfEnemies, Player player,
Level level, Texture2D enemyTexture, Texture2D healthTexture)
{
<span style="color: blue;">this</span>.waveNumber = waveNumber;
<span style="color: blue;">this</span>.numOfEnemies = numOfEnemies;
<span style="color: blue;">this</span>.player = player;
<span style="color: blue;">this</span>.level = level;
<span style="color: blue;">this</span>.enemyTexture = enemyTexture;
<span style="color: green;">// Initialze our new texture field</span>
<span style="color: blue;">this</span>.healthTexture = healthTexture;
}</pre>
</div>
<br />
<div>
We have added in an extra parameter so that we can pass in a texture to use for the health bars. Next go to <strong>WaveManager.cs</strong> and find the <strong>WaveManager</strong> constructor and change it to look like this :</div>
<div>
<br /></div>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> WaveManager(Player player, Level level, <span style="color: blue;">int</span> numberOfWaves,
Texture2D enemyTexture, Texture2D healthTexture)
{
<span style="color: blue;">this</span>.numberOfWaves = numberOfWaves;
<span style="color: blue;">this</span>.enemyTexture = enemyTexture;
<span style="color: blue;">this</span>.level = level;
<span style="color: blue;">for</span> (<span style="color: blue;">int</span> i = 0; i < numberOfWaves; i++)
{
<span style="color: blue;">int</span> initialNumerOfEnemies = 6;
<span style="color: blue;">int</span> numberModifier = (i / 6) + 1;
<span style="color: green;">// Pass the wave class our health texture.</span>
Wave wave = <span style="color: blue;">new</span> Wave(i, initialNumerOfEnemies * numberModifier,
player, level, enemyTexture, healthTexture);
waves.Enqueue(wave);
}
StartNextWave();
}</pre>
<br /></div>
<div>
Again we have added a new parameter to the constructor, and then passed this parameter straight to the Wave class.</div>
<br />
<div>
The last thing we need to do is go to <strong>Game1.cs</strong> and load our texture and pass it to our WaveManager. So in <strong>Game1.cs</strong> find the <strong>LoadContent</strong> method and more specifically this line :</div>
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">waveManager = <span style="color: blue;">new</span> WaveManager(player, level, 24, enemyTexture);</pre>
<br /></div>
<div>
And replace it with this :</div>
<div>
<br /></div>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">Texture2D healthTexture = Content.Load<Texture2D>(<span style="color: #006080;">"health bar"</span>);
waveManager = <span style="color: blue;">new</span> WaveManager(player, level, 24, enemyTexture,
healthTexture);</pre>
</div>
<div>
<br /></div>
<div>
The only difference is that we load in our healthbar texture and pass it to the WaveManager. Now that we have finished the tedious process of changing constructors and passing textures, we can move onto actually drawing our health bars!</div>
<div>
<br /></div>
<div>
The health bars will be drawn as two layers, we will first draw a gray ‘base’ layer that will indicate how much health the enemy started with. On top of that we will draw a gold layer that will indicate how much health the enemy has left.</div>
<div>
<br /></div>
<div>
So go to <strong>Wave.cs</strong> and find the <strong>Draw</strong> method, it should look something like this at the moment :</div>
<div>
<br /></div>
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">foreach</span> (Enemy enemy <span style="color: blue;">in</span> enemies)
{
enemy.Draw(spriteBatch);
}</pre>
</div>
<div>
<br /></div>
<div>
Add the following code just underneath where we draw the enemy, but before the last curly bracket :</div>
<div>
<br /></div>
<div id="codeSnippetWrapper">
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">// Draw the health bar normally.</span>
Rectangle healthRectangle = <span style="color: blue;">new</span> Rectangle((<span style="color: blue;">int</span>)enemy.Position.X,
(<span style="color: blue;">int</span>)enemy.Position.Y,
healthTexture.Width,
healthTexture.Height);
spriteBatch.Draw(healthTexture, healthRectangle, Color.Gray);</pre>
<br />
The first thing this code does is initialize a Rectangle that has the same dimensions as our health bar texture, and is located directly above our enemies head. Then we actually draw our health bar texture in this rectangle and tint it gray – this code basically draws our ‘base’ layer.</div>
<div>
<br /></div>
<div>
Underneath the last bit of code but before the curly bracket, add the following :</div>
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">float</span> healthPercentage = enemy.HealthPercentage;
<span style="color: blue;">float</span> visibleWidth = (<span style="color: blue;">float</span>)healthTexture.Width * healthPercentage;
healthRectangle = <span style="color: blue;">new</span> Rectangle((<span style="color: blue;">int</span>)enemy.Position.X,
(<span style="color: blue;">int</span>)enemy.Position.Y,
(<span style="color: blue;">int</span>)(visibleWidth),
healthTexture.Height);
spriteBatch.Draw(healthTexture, healthRectangle, Color.Gold);</pre>
<br /></div>
The first two lines determine how wide our gold layer should be based off of how much health the enemy has left. We then modify our health rectangle to use this new width and draw our gold texture in the new rectangle!</div>
<div>
<br /></div>
<div>
And that’s all there is to it! If you hit F5 and run you game now you should see something like this :</div>
<div>
<br /></div>
<div>
<a href="http://lh4.ggpht.com/_q2VraDVN7Lg/TZ8uWka-q6I/AAAAAAAAAF0/uBtVVWQfw9Q/s1600-h/image%5B2%5D.png"><img alt="image" border="0" height="244" src="http://lh5.ggpht.com/_q2VraDVN7Lg/TZ8uXGHB6yI/AAAAAAAAAF4/tuaH5V0ewKc/image_thumb.png?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="217" /></a></div>
<br />
<em>I know that the health bars don’t look very pretty at the moment, but it’s your job to make the game look nice, I'm just here to help with the nuts and bolts of it</em> <img alt="Winking smile" class="wlEmoticon wlEmoticon-winkingsmile" src="http://lh6.ggpht.com/_q2VraDVN7Lg/TZ8uXmekTII/AAAAAAAAAF8/XOTAngMCo5s/wlEmoticon-winkingsmile%5B2%5D.png?imgmax=800" style="border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none;" /><br />
<br />
<div>
I hope that this is useful to some of you!</div>
<div>
<br /></div>
<div>
<strong>Extra Reading :</strong></div>
<br />
<div>
One of the commenters on this tutorial was kind enough to provide some code to make the healthbars look a bit more pretty.</div>
<br />
<div>
The code tints the colour of the health bar based on how much health is left, so when the enemy has full health his health bar will be tinted green and when the enemy has very little health the healthbar will be tinted red. </div>
<br />
<div>
To do this find this line in <strong>Wave.cs</strong> in the <strong>Draw()</strong> method :</div>
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">spriteBatch.Draw(healthTexture, healthRectangle, Color.Gold);</pre>
</div>
And replace it with this :<br />
<br />
<div id="codeSnippetWrapper">
<pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">float</span> red = (healthPercentage < 0.5 ? 1 : 1 - (2 * healthPercentage - 1));
<span style="color: blue;">float</span> green = (healthPercentage > 0.5 ? 1 : (2 * healthPercentage));
Color healthColor = <span style="color: blue;">new</span> Color(red, green, 0);
spriteBatch.Draw(healthTexture, healthRectangle, healthColor);</pre>
<br /></div>
For more information see the below comment by <a href="http://www.blogger.com/profile/16433841466422162613">BlueRaja</a><br />
<a href="http://www.mediafire.com/file/a0rwdlc3ak353o0/TowerDefenseTutorial_15.zip">Here is the source code for this tutorial.</a></div>
FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com27tag:blogger.com,1999:blog-8967321114965538903.post-86631861955075226852011-02-25T10:48:00.004+00:002011-02-25T11:28:25.509+00:00Tutorial 14.5 : Drag and Drop TowersAs has been requested I have written another tutorial about the ability to “Drag and Drop” tower onto the level, at the end of the tutorial I will also discuss zooming and tower upgrades.<br />
<br />
<br />
<a name='more'></a><br />
<br />
The first thing we will need to do is add a new event to the Button class; one which will fire when the player presses the button but doesn’t release the mouse. So go to <strong>Button.cs</strong> and just under the click event add the following event :<br />
<br />
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">// Gets fired when the button is pressed.</span>
<span style="color: blue;">public</span> <span style="color: blue;">event</span> EventHandler Clicked;
<span style="color: green;">// Gets fired when the button is held down.</span>
<span style="color: blue;">public</span> <span style="color: blue;">event</span> EventHandler OnPress;</pre><br />
</div><div>Next go to the Update method and find the code that checks if the player is holding down the left mouse button, it will look something like this : </div><br />
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">// Check if the player holds down the button.</span>
<span style="color: blue;">if</span> (mouseState.LeftButton == ButtonState.Pressed &&
previousState.LeftButton == ButtonState.Released)
{
<span style="color: blue;"> if</span> (isMouseOver == <span style="color: blue;">true</span>)
{
<span style="color: green;"> // Update the button state.</span>
state = ButtonStatus.Pressed;
}
}</pre><br />
</div><div>Then just under where we set the state of the button add the following :</div><br />
<div><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">if</span> (OnPress != <span style="color: blue;">null</span>)
{
<span style="color: green;"> // Fire the OnPress event.</span>
OnPress(<span style="color: blue;">this</span>, EventArgs.Empty);
}</pre></div><br />
<div>And that’s it for the button class, it really is that simple to add a new event to the class!<br />
<br />
</div><div>Now before we go to <strong>Game1.cs</strong> and subscribe to the new event, we must make a few additions to the player class, so go to <strong>Player.cs</strong> and add the following field and property :</div><br />
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">// The index of the new towers texture.</span>
<span style="color: blue;">private</span> <span style="color: blue;">int</span> newTowerIndex;
<span style="color: blue;">public</span> <span style="color: blue;">int</span> NewTowerIndex
{
set { newTowerIndex = <span style="color: blue;">value</span>; }
}</pre><br />
</div>This new field will make it easier to choose which tower texture to draw when we are drawing a “preview” of the new tower.<br />
<br />
<div>Now we are going to add a new method that will draw a preview of the tower that the player wants to add :</div><br />
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">void</span> DrawPreview(SpriteBatch spriteBatch)
{
<span style="color: green;"><span class="Apple-style-span" style="color: black;"> </span>// Draw the tower preview.</span>
<span style="color: blue;"><span class="Apple-style-span" style="color: black;"> </span>if</span> (<span style="color: blue;">string</span>.IsNullOrEmpty(newTowerType) == <span style="color: blue;">false</span>)
{
<span style="color: blue;"><span class="Apple-style-span" style="color: black;"> </span></span> <span style="color: blue;">int</span> cellX = (<span style="color: blue;">int</span>)(mouseState.X / 32); <span style="color: green;">// Convert the position of the mouse</span></pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> </span> <span style="color: blue;">int</span> cellY = (<span style="color: blue;">int</span>)(mouseState.Y / 32); <span style="color: green;">// from array space to level space</span></pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">
</span></pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> </span> <span style="color: blue;">int</span> tileX = cellX * 32; <span style="color: green;">// Convert from array space to level space</span></pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> </span> <span style="color: blue;">int</span> tileY = cellY * 32; <span style="color: green;">// Convert from array space to level space</span></pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">
</span></pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> Texture2D previewTexture = towerTextures[newTowerIndex];</pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> spriteBatch.Draw(previewTexture, <span style="color: blue;">new</span> Rectangle(tileX, tileY,</pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> previewTexture.Width, previewTexture.Height), Color.White);</pre><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-bottom: 0em; margin-left: 0em; margin-right: 0em; margin-top: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}
}</pre><br />
</div><div>First this method checks if the player is trying to create a new tower, and if they are, we draw a preview of tower in the cell that the mouse if hovering over.<br />
<br />
</div><div>Now there is just one more addition to be made to the player class, go to the AddTower method and just after the if statement that checks if there is a space for the tower and if the player can afford it, add the following :</div><br />
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">else</span>
{
newTowerType = <span style="color: blue;">string</span>.Empty;
}</pre><br />
</div>What this will do is when the player tries to create a tower, but he can’t afford it or there isn’t space for it, the tower preview will disappear and the player will have to press the button again to make a new tower.<br />
<br />
<div>And that’s all that needs to be changed in the player class! So, let’s finally go back to <strong>Game1.cs</strong> and hook up our new to events!</div><br />
<div>Go to the LoadContent method and just after where we subscribed to the all of our buttons Clicked event, add the following :</div><br />
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">arrowButton.OnPress += <span style="color: blue;">new</span> EventHandler(arrowButton_OnPress);
spikeButton.OnPress += <span style="color: blue;">new</span> EventHandler(spikeButton_OnPress);
slowButton.OnPress += <span style="color: blue;">new</span> EventHandler(slowButton_OnPress);</pre><br />
</div>Then find the following methods :<br />
<br />
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">void</span> arrowButton_Clicked(<span style="color: blue;">object</span> sender, EventArgs e)
{
player.NewTowerType = <span style="color: #006080;">"Arrow Tower"</span>;
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> spikeButton_Clicked(<span style="color: blue;">object</span> sender, EventArgs e)
{
player.NewTowerType = <span style="color: #006080;">"Spike Tower"</span>;
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> slowButton_Clicked(<span style="color: blue;">object</span> sender, EventArgs e)
{
player.NewTowerType = <span style="color: #006080;">"Slow Tower"</span>
}</pre><br />
</div>And replace them with these :<br />
<br />
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">void</span> arrowButton_Clicked(<span style="color: blue;">object</span> sender, EventArgs e)
{
player.NewTowerType = <span style="color: #006080;">"Arrow Tower"</span>;
player.NewTowerIndex = 0;
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> spikeButton_Clicked(<span style="color: blue;">object</span> sender, EventArgs e)
{
player.NewTowerType = <span style="color: #006080;">"Spike Tower"</span>;
player.NewTowerIndex = 1;
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> slowButton_Clicked(<span style="color: blue;">object</span> sender, EventArgs e)
{
player.NewTowerType = <span style="color: #006080;">"Slow Tower"</span>;
player.NewTowerIndex = 2;
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> arrowButton_OnPress(<span style="color: blue;">object</span> sender, EventArgs e)
{
player.NewTowerType = <span style="color: #006080;">"Arrow Tower"</span>;
player.NewTowerIndex = 0;
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> spikeButton_OnPress(<span style="color: blue;">object</span> sender, EventArgs e)
{
player.NewTowerType = <span style="color: #006080;">"Spike Tower"</span>;
player.NewTowerIndex = 1;
}
<span style="color: blue;">private</span> <span style="color: blue;">void</span> slowButton_OnPress(<span style="color: blue;">object</span> sender, EventArgs e)
{
player.NewTowerType = <span style="color: #006080;">"Slow Tower"</span>;
player.NewTowerIndex = 2;
}</pre><br />
</div>All that is left now is to draw the tower preview! So go to the draw method and just before we call spriteBatch.End() add the following :<br />
<br />
<div id="codeSnippetWrapper"><pre id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">player.DrawPreview(spriteBatch);</pre><br />
</div>And that’s all there is to it! We now have the means to both “Drag and Drop” towers or just click and place them. If you only want to be able to Drag and Drop tower you will need to comment out the lines where we subscribe to our buttons Clicked event, and if you don’t want the player to Drag and Drop towers comment out where we subscribe to our buttons OnPress events.<br />
<br />
Hopefully all of that made sense and was helpful to you all!<br />
<br />
I have also been asked to write a tutorial about upgrading towers, however I think this is pretty simple and it would be good if you could do it on your own! But if you get stuck this is how I would do it:<br />
<ol><li>In the Tower class I would add a tier field that describes how upgraded the tower is.</li>
<li>Then in each of the different tower classes I would add an Upgrade method that increases the tier of the tower and also increases the damage etc.</li>
<li>In the Game1 class I would add a field for a new button and also another field that describes if it is hidden or visible.</li>
<li>When a tower is selected I would make the button visible, and when no tower is selected I would make the button hidden.</li>
<li>When the button is clicked I would call the selected towers Upgrade method if the player could afford the upgrade.</li>
</ol>Also someone asked about zooming the camera in and out, for this I would look at one of the SpriteBatch.Begin() overloads that takes a matrix as a parameter. You could pass a scaling matrix (Matrix.CreateScale) to the Begin method to create a scaling effect, although this may cause some images to look stretched!<br />
<br />
I hope this tutorial was useful to you all, thanks for reading!<br />
<br />
<a href="http://www.mediafire.com/file/811iwyi2ec66gdw/TowerDefenseTutorial_14.zip">Here is the source code for this tutorial.</a>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com27tag:blogger.com,1999:blog-8967321114965538903.post-14063894974814283762011-01-31T15:08:00.002+00:002011-03-31T16:14:59.368+01:00Tutorial 14 : Polishing the Game<p>In this, the last tutorial in the series, I will show you how to add a bit of polish to the game by adding a few key features to our game :</p> <ol> <li>Giving the player money when he kills an enemy.</li> <li>Removing a life when one of the enemies reaches the end of the path.</li></ol> <p>Both of these things will be implemented in the wave class, however before we make any changes to that we must first make some of the player’s properties settable! </p> <a name='more'></a> <p>So go to the <strong>Player </strong>class and find the Money and Lives properties and a set statement to both of them :</p> <div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Money<br />{<br /> get { <span style="color: #0000ff">return</span> money; }<br /> set { money = <span style="color: #0000ff">value</span>; }<br />}<br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Lives<br />{<br /> get { <span style="color: #0000ff">return</span> lives; }<br /> set { lives = <span style="color: #0000ff">value</span>; }<br />}</pre></div><p>This will allow us to make changes to these properties outside of the player class. We are now ready to add our two key features! Go to the <strong>Wave</strong> class and somewhere with the fields add a Player field :</p><div id="codeSnippetWrapper"><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> Player player; // A reference to the player.</pre></div></div><p>Now we need to pass a reference to the player via the constructor, so change the <strong>Wave</strong> constructor to accept a player reference :</p><div><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> Wave(<span style="color: #0000ff">int</span> waveNumber, <span style="color: #0000ff">int</span> numOfEnemies,<br /> Player player, Level level, Texture2D enemyTexture)<br />{<br /><span style="color: #0000ff"><span class="Apple-style-span" style="color: rgb(0, 0, 0); "> </span>this</span>.waveNumber = waveNumber;<br /><span style="color: #0000ff"><span class="Apple-style-span" style="color: rgb(0, 0, 0); "> </span>this</span>.numOfEnemies = numOfEnemies;<br /><br /><span style="color: #0000ff"><span class="Apple-style-span" style="color: rgb(0, 0, 0); "> </span>this</span>.player = player; <span style="color: #008000">// Reference the player.</span><br /><span style="color: #0000ff"><span class="Apple-style-span" style="color: rgb(0, 0, 0); "> </span>this</span>.level = level;<br /><br /> <span style="color: #0000ff">this</span>.enemyTexture = enemyTexture;<br />}</pre></div><div><br /></div><div>Now that we have a stored reference to the player, find the Update method and in particular the if statement that check’s if an enemy is dead but still has health (ergo the enemy is at the end), and in this if statement add the code to remove a life from the player :</div><br /><div><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">if</span> (enemy.IsDead)<br />{<br /> <span style="color: #0000ff">if</span> (enemy.CurrentHealth > 0) <span style="color: #008000">// Enemy is at the end</span><br /> {<br /> enemyAtEnd = <span style="color: #0000ff">true</span>;<br /> player.Lives -= 1;<br /> }</pre></div><br /><div>Then just under that we are going to add an else statement which will be triggered if the enemy has been killed and has no health (ergo the player has killed the enemy) :</div><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">else</span><br />{<br /> player.Money += enemy.BountyGiven;<br />}</pre></div><p>Simple huh? I can’t beleive I left it until the end to add these features in that actually make our game playable! With those changes made, that if statement should look like this :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">if</span> (enemy.IsDead)<br />{<br /> <span style="color: #0000ff">if</span> (enemy.CurrentHealth > 0) <span style="color: #008000">// Enemy is at the end</span><br /> {<br /> enemyAtEnd = <span style="color: #0000ff">true</span>;<br /> player.Lives -= 1;<br /> }<br /><br /> <span style="color: #0000ff">else</span><br /> {<br /> player.Money += enemy.BountyGiven;<br /> }<br /><br /> enemies.Remove(enemy);<br /> i--;<br />}</pre><br /></div><p>All that is left now is to pass the player reference to the Wave class. So go to the <strong>WaveManager</strong> class and modify the constructor so that it takes in a reference to the Player class and then passes it to the Wave class :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> WaveManager(Player player, Level level, <span style="color: #0000ff">int</span> numberOfWaves, Texture2D enemyTexture)<br />{<br /> <span style="color: #0000ff">this</span>.numberOfWaves = numberOfWaves;<br /> <span style="color: #0000ff">this</span>.enemyTexture = enemyTexture;<br /><br /> <span style="color: #0000ff">this</span>.level = level;<br /><br /> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i < numberOfWaves; i++)<br /> {<br /> <span style="color: #0000ff">int</span> initialNumerOfEnemies = 6;<br /> <span style="color: #0000ff">int</span> numberModifier = (i / 6) + 1;<br /><br /> <span style="color: #008000">// Pass the reference to the player, to the wave class.</span><br /> Wave wave = <span style="color: #0000ff">new</span> Wave(i, initialNumerOfEnemies *<br /> numberModifier, player, level, enemyTexture);<br /><br /> waves.Enqueue(wave);<br /> }<br /><br /> StartNextWave();<br />}</pre></div><p>Now go back to <strong>Game1</strong> and find the LoadContent method, and in it find where we initialize the WaveManager.We need to move this initialization code to underneath where we initialize the Player and then pass in the Player to the WaveManager, like so :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">Texture2D bulletTexture = Content.Load<Texture2D>(<span style="color: #006080">"bullet"</span>);<br /><br />Texture2D[] towerTextures = <span style="color: #0000ff">new</span> Texture2D[]<br />{<br /> Content.Load<Texture2D>(<span style="color: #006080">"arrow tower"</span>),<br /> Content.Load<Texture2D>(<span style="color: #006080">"spike tower"</span>),<br /> Content.Load<Texture2D>(<span style="color: #006080">"slow tower"</span>),<br />};<br /><br />player = <span style="color: #0000ff">new</span> Player(level, towerTextures, bulletTexture);<br /><br />Texture2D enemyTexture = Content.Load<Texture2D>(<span style="color: #006080">"enemy"</span>);<br />waveManager = <span style="color: #0000ff">new</span> WaveManager(player, level, 24, enemyTexture);</pre><br /></div><div>And we’re done!! That is the end of this series (unless people are in need of another tutorial??). So now you have a pretty solid base to work off of if you want to create your own tower defence! But don’t be tempted to think this is finished game, there is still a lot more that could be done!!</div><ul><li>The art is only placeholder, be creative and make your own!</li><br /><li>Currently there is only 1 type of enemy, how dull is that? Be creative and add new types, it is basically the same process as adding a new tower!</li><br /><li>Wouldn’t it be nice if enemies didn’t have to just follow a path? Let A-Star guide you...</li><br /><li>Add a timer that appears in between levels to let the player know how long he has before the next wave.</li><br /><li>Add in bonus rounds for extra gold.</li><br /><li>The current UI is so dull, wouldn’t it be nice if you could see some more information about each tower?</li></ul><p>Well that’s it for me, thank you so much for the kind words, reporting bugs, and for just reading this blog!</p><p>Happy Coding!</p>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com46tag:blogger.com,1999:blog-8967321114965538903.post-17330578824389684092011-01-21T16:58:00.003+00:002011-01-21T17:00:41.406+00:00Tutorial 13 : Adding the Slow Tower<p>As a few of you have requested, I will write another tutorial on creating a custom tower type. In this tutorial I will show you how to create a tower the makes the enemies move slower when they are hit with a bullet, and hopefully by the end of this tutorial you will see how easy it is to extend the tower class to make all sorts of different towers!</p> <p>For simplicities sake, I am only going to show you the changes needed to create the new tower class and not include any details about adding a new button or changing the player AddTower method (If you need help on this see Tutorial 12). However I will provide some placeholder textures that you can use for the slow tower :</p> <p><a href="http://lh3.ggpht.com/_q2VraDVN7Lg/TTm7GMLVskI/AAAAAAAAAEU/aVbFcdAe4vs/s1600-h/slow%20tower%5B11%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 50px 0px 200px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="slow tower" border="0" alt="slow tower" src="http://lh3.ggpht.com/_q2VraDVN7Lg/TTm7GhI7OBI/AAAAAAAAAEY/iP7PisjWLXY/slow%20tower_thumb%5B5%5D.png?imgmax=800" width="32" height="32" /></a><a href="http://lh3.ggpht.com/_q2VraDVN7Lg/TTm7HD31x_I/AAAAAAAAAEc/on1BCjqrJO4/s1600-h/slow%20button%5B3%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 50px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="slow button" border="0" alt="slow button" src="http://lh4.ggpht.com/_q2VraDVN7Lg/TTm7HjXMlWI/AAAAAAAAAEg/k6it0l-da88/slow%20button_thumb%5B1%5D.png?imgmax=800" width="32" height="32" /></a><a href="http://lh5.ggpht.com/_q2VraDVN7Lg/TTm7IPI_i2I/AAAAAAAAAEk/zeSBVKvV0rQ/s1600-h/slow%20hover%5B3%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="slow hover" border="0" alt="slow hover" src="http://lh3.ggpht.com/_q2VraDVN7Lg/TTm7IXvoKQI/AAAAAAAAAEo/ZsbPDQIHZAc/slow%20hover_thumb%5B1%5D.png?imgmax=800" width="32" height="32" /></a><a href="http://lh4.ggpht.com/_q2VraDVN7Lg/TTm7Iyr3M5I/AAAAAAAAAEs/q5m1952lfYc/s1600-h/slow%20pressed%5B3%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 50px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="slow pressed" border="0" alt="slow pressed" src="http://lh6.ggpht.com/_q2VraDVN7Lg/TTm7JZQz4kI/AAAAAAAAAEw/bEqY07hwjU4/slow%20pressed_thumb%5B1%5D.png?imgmax=800" width="32" height="32" /></a></p> <a name='more'></a> <p>So let’s begin, the first thing we are going to do is add a few new fields and properties to the Enemy class :</p> <div><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">float</span> speedModifier;<br /><br /><span style="color: #0000ff">private</span> <span style="color: #0000ff">float</span> modifierDuration;<br /><span style="color: #0000ff">private</span> <span style="color: #0000ff">float</span> modiferCurrentTime;<br /><br /><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Alters the speed of the enemy.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">float</span> SpeedModifier<br />{<br /> get { <span style="color: #0000ff">return</span> speedModifier; }<br /> set { speedModifier = <span style="color: #0000ff">value</span>; }<br />}<br /><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Defines how long the speed modification will last.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">float</span> ModifierDuration<br />{<br /> get { <span style="color: #0000ff">return</span> modifierDuration; }<br /> set<br /> {<br /> modifierDuration = <span style="color: #0000ff">value</span>;<br /> modiferCurrentTime = 0;<br /> }<br />}</pre></div><br /><div>We will use these fields to alter the movement of the enemies. We will use these fields to alter the velocity of the enemy. So go to the Enemy Update method and find where we multiply the enemies velocity by it’s speed, and replace it with this :</div><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">Vector2 direction = waypoints.Peek() - position;<br />direction.Normalize();<br /><br /><span style="color: #008000">// Store the original speed.</span><br /><span style="color: #0000ff">float</span> temporarySpeed = speed;<br /><br /><span style="color: #008000">// If the modifier has finished,</span><br /><span style="color: #0000ff">if</span> (modiferCurrentTime > modifierDuration)<br />{<br /> <span style="color: #008000">// reset the modifier.</span><br /> speedModifier = 0;<br /> modiferCurrentTime = 0;<br />}<br /><br /><span style="color: #0000ff">if</span> (speedModifier != 0 && modiferCurrentTime <= modifierDuration)<br />{<br /> <span style="color: #008000">// Modify the speed of the enemy.</span><br /> temporarySpeed *= speedModifier;<br /> <span style="color: #008000">// Update the modifier timer.</span><br /> modiferCurrentTime += (<span style="color: #0000ff">float</span>)gameTime.ElapsedGameTime.TotalSeconds;<br />}<br /><br />velocity = Vector2.Multiply(direction, temporarySpeed);<br /><br />position += velocity;</pre><br /></div><div>Most of what we are doing here is the same as before, however now we are checking if the enemy has any speed modifier applied to it, and if it has, we alter it’s velocity. Also this code keeps track of how long the speed modifier has lasted and removes this modifier when it wears off.<br /></div><br /><div>Right, now that is out of the way, let’s create our new tower! The great thing about the slow tower is that it is basically just an Arrow Tower, only it applies a speed modifier to the enemy it is shooting. </div><div><br /></div><div>So we can cheat a little bit here by finding “ArrowTower.cs” in the solution explorer and cloning it. You will need to rename the copy something like “SlowTower.cs”, and also you will need to go into the new file and replace wherever it says ArrowTower with SlowTower.</div><div><br /></div><div>So now most of the work is done for us, all that is left to do is to add a few fields to keep track of the speed modifications, and to update the bullet intersection code, so let’s start by adding the follow fields to SlowTower :</div><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Defines how fast an enemy will move when hit.</span><br /><span style="color: #0000ff">private</span> <span style="color: #0000ff">float</span> speedModifier;<br /><span style="color: #008000">// Defines how long this effect will last.</span><br /><span style="color: #0000ff">private</span> <span style="color: #0000ff">float</span> modifierDuration;</pre></div><p>We also need to initialize these fields in the SlowTower constructor :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">this</span>.speedModifier = 0.6f;<br /><span style="color: #0000ff">this</span>.modifierDuration = 2.0f;</pre></div><p>Next go down to the SlowTower’s Update method and find where we check if a bullet has hit the target :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">if</span> (target != <span style="color: #0000ff">null</span> && Vector2.Distance(bullet.Center, target.Center) < 12)</pre></div><p>And just under what is inside the if statement, add this :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Apply our speed modifier if it is better than</span><br /><span style="color: #008000">// the one currently affecting the target :</span><br /><span style="color: #0000ff">if</span> (target.SpeedModifier <= speedModifier)<br />{<br /> target.SpeedModifier = speedModifier;<br /> target.ModifierDuration = modifierDuration;<br />}</pre></div><p>We will only allow an enemy to have one speed modifier acting on it – the modifier will only be applied to the enemy if it is better than the current one.</p><p>And voilà, we have a new type of tower, it really is that simple! There is a lot more that you could change / add to this tower :</p><ul><li>This tower costs exactly the same as the arrow tower and does the same damage.</li><br /><li>Maybe you think the enemy should move even slower when hit by this tower or maybe it should move slow for longer?</li><br /><li>What if when an enemy is hit by this tower it is tinted a different colour to show that it has been slowed?</li><br /><li>Maybe this tower should only target enemies that are moving at normal speed for maximum efficiency?</li><br /><li>Or perhaps it could target more than one enemy at a time, or have a kind of “Splash” effect!</li></ul><p>Maybe you could see how many of the above you could add to the tower to test your skills? If you have some trouble creating a button for this class, I will upload working source that shows you how to do this.</p><p><a href="http://www.mediafire.com/file/jekrhizzw63rbjg/TowerDefenseTutorial_13.zip">Here is the source code for this tutorial.</a></p>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com8tag:blogger.com,1999:blog-8967321114965538903.post-66431096053415428502011-01-18T20:21:00.005+00:002011-01-19T16:01:04.399+00:00Tutorial 12 : Adding a New Tower Type<p>Sorry for the delay, I have had a very busy at the month! In this tutorial I will show you how to add in two type of cannon, the Spike tower. This tower will be able to shoot 8 bullets in eight different directions at a time.</p> <p><a href="http://lh3.ggpht.com/_q2VraDVN7Lg/TTX2PBClGJI/AAAAAAAAADg/xvbj9xsB3qc/s1600-h/image%5B4%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_q2VraDVN7Lg/TTX2PnL3_kI/AAAAAAAAADk/BVyURHx2ggM/image_thumb%5B2%5D.png?imgmax=800" width="62" height="62" /></a></p> <p>This should be pretty straight forward seeing as we have designed the Tower class to be as extensible as possible, although we will have to make several adjustments to some of the other classes.</p> <a name='more'></a> <p>So let’s get started, the first thing we will do is add four new textures to our project :</p> <p><a href="http://lh3.ggpht.com/_q2VraDVN7Lg/TTX2QLgJViI/AAAAAAAAADo/OMOVg-IuD4U/s1600-h/spike%20tower%5B3%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 225px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="spike tower" border="0" alt="spike tower" align="left" src="http://lh4.ggpht.com/_q2VraDVN7Lg/TTX2QjkgIoI/AAAAAAAAADs/C36LpFo5dhg/spike%20tower_thumb%5B1%5D.png?imgmax=800" width="32" height="32" /></a><a href="http://lh4.ggpht.com/_q2VraDVN7Lg/TTX2R9TTdMI/AAAAAAAAADw/SNzg_j3MhYM/s1600-h/spike%20button%5B3%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 20px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="spike button" border="0" alt="spike button" src="http://lh5.ggpht.com/_q2VraDVN7Lg/TTX2SRV2E4I/AAAAAAAAAD0/Gt0eIAXLy_Q/spike%20button_thumb%5B1%5D.png?imgmax=800" width="32" height="32" /></a><a href="http://lh6.ggpht.com/_q2VraDVN7Lg/TTX2SpSCuvI/AAAAAAAAAD4/b8UufSfhJr0/s1600-h/spike%20hover%5B8%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 20px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="spike hover" border="0" alt="spike hover" src="http://lh5.ggpht.com/_q2VraDVN7Lg/TTX2TWoqlGI/AAAAAAAAAD8/oeyoXdzRoas/spike%20hover_thumb%5B4%5D.png?imgmax=800" width="32" height="32" /></a><a href="http://lh5.ggpht.com/_q2VraDVN7Lg/TTX2UU9-YlI/AAAAAAAAAEA/FfJYq-1BjVU/s1600-h/spike%20pressed%5B3%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="spike pressed" border="0" alt="spike pressed" src="http://lh6.ggpht.com/_q2VraDVN7Lg/TTX2U0Rh1JI/AAAAAAAAAEE/C050bSiBe_g/spike%20pressed_thumb%5B1%5D.png?imgmax=800" width="32" height="32" /></a></p> <p>The “spike tower” texture needs to be added to the main Content Project, whereas the other 3 textures need to be added to a new folder called “Spike Tower” that needs to be added in the GUI folder. Confused yet? When you have done this step you should end up with something like this : </p> <p><a href="http://lh3.ggpht.com/_q2VraDVN7Lg/TTX2VlbvN4I/AAAAAAAAAEI/a_cOLTX3ZCs/s1600-h/image%5B7%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_q2VraDVN7Lg/TTX2WLxTz3I/AAAAAAAAAEM/rus2jecQoog/image_thumb%5B3%5D.png?imgmax=800" width="204" height="244" /></a></p> <p>Hopefully your still with me after that stage! Right, we can move onto creating a new class for our tower. Add a new class into the Tower folder and call it “SpikeTower.cs”. Next, make our new class inherit from the <strong>Tower</strong> class :</p> <div><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> SpikeTower : Tower</pre></div><div><br /></div><div>Now we are going to add some new fields and properties to the class :</div><div><br /></div><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// A list of directions that the tower can shoot in.</span><br /><span style="color: #0000ff">private</span> Vector2[] directions = <span style="color: #0000ff">new</span> Vector2[8];<br /><span style="color: #008000">// All the enimes that are in range of the tower.</span><br /><span style="color: #0000ff">private</span> List<Enemy> targets = <span style="color: #0000ff">new</span> List<Enemy>();</pre></div><p>The first field will store of all the directions that the Spike Tower can shoot in (North, East, South… etc.). The next field will contain a list of all the enemies that are in range of the tower. You may be asking why not just have one target like the last tower? We need to store all these enemies because we aren’t just targeting one enemy, we are shooting bullets off in all directions and hoping one hits! We need to know all of the enemies that might be hit!</p><p>Next we need to give our tower a constructor :</p><div><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Constructs a new Spike Tower object.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #0000ff">public</span> SpikeTower(Texture2D texture, Texture2D bulletTexture, Vector2 position)<br />: <span style="color: #0000ff">base</span>(texture, bulletTexture, position)<br />{<br /><span style="color: #0000ff">this</span>.damage = 20; <span style="color: #008000">// Set the damage.</span><br /><span style="color: #0000ff">this</span>.cost = 40; <span style="color: #008000">// Set the initial cost.</span><br /><br /><span style="color: #0000ff">this</span>.radius = 48; <span style="color: #008000">// Set the radius.</span><br /><br /><span style="color: #008000">// Store a list of all the directions the tower can shoot.</span><br />directions = <span style="color: #0000ff">new</span> Vector2[]<br />{<br /> <span style="color: #0000ff">new</span> Vector2(-1, -1), <span style="color: #008000">// North West</span><br /> <span style="color: #0000ff">new</span> Vector2( 0, -1), <span style="color: #008000">// North</span><br /> <span style="color: #0000ff">new</span> Vector2( 1, -1), <span style="color: #008000">// North East</span><br /> <span style="color: #0000ff">new</span> Vector2(-1, 0), <span style="color: #008000">// West</span><br /> <span style="color: #0000ff">new</span> Vector2( 1, 0), <span style="color: #008000">// East</span><br /> <span style="color: #0000ff">new</span> Vector2(-1, 1), <span style="color: #008000">// South West</span><br /> <span style="color: #0000ff">new</span> Vector2( 0, 1), <span style="color: #008000">// South</span><br /> <span style="color: #0000ff">new</span> Vector2( 1, 1), <span style="color: #008000">// South East</span><br />};<br />}</pre></div><br /><div>This is pretty much the same as the Arrow Tower constructor except here we need to initialize the directions in which the tower can shoot.</div><br /><div>Before we can write an update method for our tower we need to make a quick change to <strong>“Bullet.cs”. </strong>So go to <strong>“Bullet.cs”</strong> and just under the existing constructor we will add a new one :</div><div id="codeSnippetWrapper"><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> Bullet(Texture2D texture, Vector2 position, Vector2 velocity, <span style="color: #0000ff">int</span> speed, <span style="color: #0000ff">int</span> damage)<br />: <span style="color: #0000ff">base</span>(texture, position)<br />{<br /><span style="color: #0000ff">this</span>.rotation = rotation;<br /><span style="color: #0000ff">this</span>.damage = damage;<br /><br /><span style="color: #0000ff">this</span>.speed = speed;<br /><br /><span style="color: #0000ff">this</span>.velocity = velocity * speed;<br />}</pre></div><br /><div>Instead of taking in a rotation and then converting it into a velocity, we directly pass in a velocity to use (Well technically we pass in a direction and use that and the speed to calculate the velocity).</div></div><br /><div>With that added we can go back to <strong>“SpikeTower.cs”</strong> and add our update method :</div><div><br /></div><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime)<br />{<br /><br />}</pre></div><p>We will build this method up step by step. The first thing we will add to this method is some code to create our bullets and make sure the travel in the right direction :</p><div><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">bulletTimer += (<span style="color: #0000ff">float</span>)gameTime.ElapsedGameTime.TotalSeconds;<br /><br /><span style="color: #008000">// Decide if it is time to shoot.</span><br /><span style="color: #0000ff">if</span> (bulletTimer >= 1.0f && targets.Count != 0)<br />{<br /><span style="color: #008000">// For every direction the tower can shoot,</span><br /><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i < directions.Length; i++)<br />{<br /> <span style="color: #008000">// create a new bullet that moves in that direction.</span><br /> Bullet bullet = <span style="color: #0000ff">new</span> Bullet(bulletTexture, Vector2.Subtract(center,<br /> <span style="color: #0000ff">new</span> Vector2(bulletTexture.Width / 2)), directions[i], 6, damage);<br /><br /> bulletList.Add(bullet);<br />}<br /><br />bulletTimer = 0;<br />}</pre></div><div><br /></div><div>First we update the timer that we use to decide if it is time to shoot again. We then check if it is time to shoot, and if it is, we loop through all of the directions that our tower can shoot, and we create a bullet that travels in that direction.</div><div> </div><div>The next thing we will add is some code to update our bullets :</div><div id="codeSnippetWrapper"><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Loop through all the bullets.</span><br /><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i < bulletList.Count; i++)<br />{<br />Bullet bullet = bulletList[i];<br />bullet.Update(gameTime);<br /><br /><span style="color: #008000">// Kill the bullet when it is out of range.</span><br /><span style="color: #0000ff">if</span> (!IsInRange(bullet.Center))<br />{<br /> bullet.Kill();<br />}<br /><br /><span style="color: #008000">// Loop through all the possible targets</span><br /><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> t = 0; t < targets.Count; t++)<br />{<br /> <span style="color: #008000">// If this bullet hits a target and is in range,</span><br /> <span style="color: #0000ff">if</span> (targets[t] != <span style="color: #0000ff">null</span> && Vector2.Distance(bullet.Center, targets[t].Center) < 12)<br /> {<br /> <span style="color: #008000">// hurt the enemy.</span><br /> targets[t].CurrentHealth -= bullet.Damage;<br /> bullet.Kill();<br /><br /> <span style="color: #008000">// This bullet can't kill anyone else.</span><br /> <span style="color: #0000ff">break</span>;<br /> }<br />}<br /><br /><span style="color: #008000">// Remove the bullet if it is dead.</span><br /><span style="color: #0000ff">if</span> (bullet.IsDead())<br />{<br /> bulletList.Remove(bullet);<br /> i--;<br />}<br />}</pre></div><div><br /></div><div>This code is basically the same as the update code in <strong>“ArrowTower.cs” </strong>however notice that we don’t just check if our bullets have hit just one target, we test it against all of the nearby enemies until either we hit one or we run out of enemies to test against.</div></div><p>Our Spike Tower is nearly finished however there is one more property that needs to be added, however first we need to go back to <strong>“Tower.cs” </strong>and add the following property :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">virtual</span> <span style="color: #0000ff">bool</span> HasTarget<br />{<br /><span style="color: #008000">// Check if the tower has a target.</span><br />get { <span style="color: #0000ff">return</span> target != <span style="color: #0000ff">null</span>; }<br />}</pre></div><p>I will explain the significance of this property later. While we are still in <strong>“Tower.cs” </strong>there is one more change that needs to be made, find the GetClosestEnemy method and make it a virtual method, so change this :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> GetClosestEnemy(List<Enemy> enemies)</pre></div><p>to this :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">virtual</span> <span style="color: #0000ff">void</span> GetClosestEnemy(List<Enemy> enemies)</pre></div><p>Now then, go back to <strong>“SpikeTower.cs” </strong>and add the following property :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">bool</span> HasTarget<br />{<br /><span style="color: #008000">// The tower will never have just one target.</span><br />get { <span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span>; }<br />}</pre></div><p>Again I will explain this in more detail later. Before we can move onto to adding a button for this tower, there is a few more changes to be made (yes I know I said we only had one more property to add…). We need to override the GetClosestEnemy method, this is because our now Spike Tower handles enemies differently than the normal method, so let’s override it and add in some new logic :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> GetClosestEnemy(List<Enemy> enemies)<br />{<br /><span style="color: #008000">// Do a fresh search for targets.</span><br />targets.Clear();<br /><br /><span style="color: #008000">// Loop over all the enemies.</span><br /><span style="color: #0000ff">foreach</span> (Enemy enemy <span style="color: #0000ff">in</span> enemies)<br />{<br /> <span style="color: #008000">// Check wether this enemy is in shooting distance.</span><br /> <span style="color: #0000ff">if</span> (IsInRange(enemy.Center))<br /> {<br /> <span style="color: #008000">// Make it a target.</span><br /> targets.Add(enemy);<br /> }<br />}<br />}</pre></div><p>As you can probably see, instead of trying to find the closest enemy, we are just finding all of the enemies that are in range of the tower (see above for the explanation why).</p><p>Before we can add a new button for this tower, we need to make a small method to the Players Update method, so go ahead and find the Update method in <strong>“Player.cs”</strong> and more specifically this line :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">if</span> (tower.Target == <span style="color: #0000ff">null</span>)</pre></div><br /><div>and replace it with the following :</div><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Make sure the tower has no targets.</span><br /><span style="color: #0000ff">if</span> (tower.HasTarget == <span style="color: #0000ff">false</span>)</pre></div><br /><div>This is where the property we added earlier comes into play. Normally this property will just return whether or not a tower has a single target, but in the case of the Spike Tower, it will always return false. This is because the Spike Tower never really has a single target, it can have many, and it always needs to check whether new enemies have come into range or old enemies are no longer in range.</div><div><br /></div><div>While we are in the player class, go to the top of the class and find the towerTexture field, and change it to :</div><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// The textures used to draw our tower.</span><br /><span style="color: #0000ff">private</span> Texture2D[] towerTextures;</pre></div><p>It is no longer possible to only store one texture to use for all of the Towers, we will needs a separate texture for each tower. We need to modify the constructor to accommodate this change :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Construct a new player.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #0000ff">public</span> Player(Level level, Texture2D[] towerTextures, Texture2D bulletTexture)<br />{<br /><span style="color: #0000ff">this</span>.level = level;<br /><br /><span style="color: #0000ff">this</span>.towerTextures = towerTextures;<br /><span style="color: #0000ff">this</span>.bulletTexture = bulletTexture;<br />}</pre></div><p>Now that we have access to different textures to use for different types of tower, we can go ahead and find the AddTower method and change it so it can handle the SpikeTower. You need to change the switch statement so it looks like this :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">switch</span> (newTowerType)<br />{<br /><span style="color: #0000ff">case</span> <span style="color: #006080">"Arrow Tower"</span>:<br />{<br /> towerToAdd = <span style="color: #0000ff">new</span> ArrowTower(towerTextures[0],<br /> bulletTexture, <span style="color: #0000ff">new</span> Vector2(tileX, tileY));<br /> <span style="color: #0000ff">break</span>;<br />}<br /><span style="color: #0000ff">case</span> <span style="color: #006080">"Spike Tower"</span>:<br />{<br /> towerToAdd = <span style="color: #0000ff">new</span> SpikeTower(towerTextures[1],<br /> bulletTexture, <span style="color: #0000ff">new</span> Vector2(tileX, tileY));<br /> <span style="color: #0000ff">break</span>;<br />}<br />}</pre><br /></div>As you can see the code is pretty much the same, the major difference is that the arrow tower uses the first texture stored in our texture array, and the spike tower uses the second texture stored in the array. We must remember this order when we pass our texture array to the player.<br /><div> </div><div>Now all that’s left to do is to add a new button for our tower, so go back to <strong>“Game1.cs” </strong>and at the top add the following field :</div><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">Button spikeButton;</pre></div><p>Next, find the LoadContent method. We need to adjust the code that initializes the player so that we pass in a texture array instead of a single texture :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">Texture2D[] towerTextures = <span style="color: #0000ff">new</span> Texture2D[]<br />{<br />Content.Load<Texture2D>(<span style="color: #006080">"arrow tower"</span>),<br />Content.Load<Texture2D>(<span style="color: #006080">"spike tower"</span>)<br />};<br /><br />player = <span style="color: #0000ff">new</span> Player(level, towerTextures, bulletTexture);</pre></div><p>Now go down to where we load in the textures for the arrow tower and just under, load in the textures for the spike tower :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// The "Normal" texture for the spike button.</span><br />Texture2D spikeNormal = Content.Load<Texture2D>(<span style="color: #006080">"GUI\\Spike Tower\\spike button"</span>);<br /><span style="color: #008000">// The "MouseOver" texture for the spike button.</span><br />Texture2D spikeHover = Content.Load<Texture2D>(<span style="color: #006080">"GUI\\Spike Tower\\spike hover"</span>);<br /><span style="color: #008000">// The "Pressed" texture for the spike button.</span><br />Texture2D spikePressed = Content.Load<Texture2D>(<span style="color: #006080">"GUI\\Spike Tower\\spike pressed"</span>);</pre></div><p>And just under that initialize our new button and assign a click event to it :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Initialize the spike button.</span><br />spikeButton = <span style="color: #0000ff">new</span> Button(spikeNormal, spikeHover,<br />spikePressed, <span style="color: #0000ff">new</span> Vector2(32, level.Height * 32));<br /><br />spikeButton.Clicked += <span style="color: #0000ff">new</span> EventHandler(spikeButton_Clicked);</pre></div><br /><div>Now, just under the LoadContent method, we need to add a new method that will be called when the spike button is clicked :</div><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> spikeButton_Clicked(<span style="color: #0000ff">object</span> sender, EventArgs e)<br />{<br />player.NewTowerType = <span style="color: #006080">"Spike Tower"</span>;<br />}</pre></div><br /><div>You can see an explanation of this in the previous tutorial. All that is left to do now is Update and draw our buttons!</div><br /><div>Fnd the Update method and just after where we update the arrowButton, update the spikeButton :</div><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//Update the spike button.</span><br />spikeButton.Update(gameTime);</pre></div><br /><div>And then go down to the Draw method and just after where we draw the arrowButton, draw the spikeButton :</div><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">spikeButton.Draw(spriteBatch);</pre></div><br /><div>And where finished! Who knew it would take so much to just add in a new tower <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://lh4.ggpht.com/_q2VraDVN7Lg/TTX2W_b7DxI/AAAAAAAAAEQ/1rCbeC7UDB8/wlEmoticon-winkingsmile%5B2%5D.png?imgmax=800" />. I’m still undecided on whether to write another tutorial about creating a custom tower class, or just write a “finishing off” tutorial. Let me know what you think!</div><br /><div><a href="http://www.mediafire.com/file/c3m8ob3d6gicojd/TowerDefenseTutorial_12.zip">Here is the source code for this tutorial.</a></div>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com24tag:blogger.com,1999:blog-8967321114965538903.post-51927784524685260482010-12-23T10:33:00.003+00:002010-12-23T10:37:46.749+00:00Tutorial 11 : Creating the GUI (Part 2)<p>In this tutorial we will be adding a generic button class to our project, and then we will be using this class to add buttons to our toolbar. We will keep this button class a general as possible so it can be re-used throughout the project.</p> <a name='more'></a> <p>The first thing we are going to do is add a new class in the GUI folder called “<strong>Button.cs</strong>” and make it inherit the <strong>Sprite</strong> class. Before we add anything to this class though, we are going to create a new <span>enum</span> just above it :</p> <div id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Describes the state of the button.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">enum</span> ButtonStatus<br />{<br /> Normal,<br /> MouseOver,<br /> Pressed,<br />}<br /><br /><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Stores the appearance and functionality of a button.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Button : Sprite<br />{<br /><br />}</pre><br /><em>Note : The reason the enum is called ButtonStatus is to avoid confusion with the XNA enum called ButtonState.</em></div><p>This <span>enum</span> gives us a way to define what the button should like in certain conditions. There are 3 different states the button can be in :</p><p><a href="http://lh6.ggpht.com/_q2VraDVN7Lg/TRMlW7kT7cI/AAAAAAAAADE/T0VpGjPNn8A/s1600-h/arrow-button3.png"><img style="background-image: none; border-right-width: 0px; margin: 0px 0px 0px 50px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="arrow button" border="0" alt="arrow button" align="left" src="http://lh4.ggpht.com/_q2VraDVN7Lg/TRMlXgKiBzI/AAAAAAAAADI/0dlVuZrkdaA/arrow-button_thumb1.png?imgmax=800" width="32" height="32" /></a><a href="http://lh5.ggpht.com/_q2VraDVN7Lg/TRMlX1XKSoI/AAAAAAAAADM/k9WnJ5b19a8/s1600-h/arrow%20pressed%5B3%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 50px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="arrow pressed" border="0" alt="arrow pressed" align="right" src="http://lh5.ggpht.com/_q2VraDVN7Lg/TRMlYuIXo2I/AAAAAAAAADQ/znaPksDY3iM/arrow%20pressed_thumb%5B1%5D.png?imgmax=800" width="32" height="32" /></a><a href="http://lh3.ggpht.com/_q2VraDVN7Lg/TRMlZRhKD7I/AAAAAAAAADU/l-vSMX2YYE8/s1600-h/arrow-hover3.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="arrow hover" border="0" alt="arrow hover" src="http://lh3.ggpht.com/_q2VraDVN7Lg/TRMlaIZTCCI/AAAAAAAAADY/tFMm39ev3kg/arrow-hover_thumb1.png?imgmax=800" width="32" height="32" /></a></p><p><strong>Normal</strong> : This is the default state of the button – the button is in this state when the mouse is not hovering over the button and the button has not been pressed.</p><p><strong>MouseOver</strong> : The button is in the state when the player has the mouse hovering over the button and is not holding down the left mouse button.</p><p><strong>Pressed</strong> : The button is in the state when the player has the left button held down while hovering over the button.</p><p>Right, let’s makes a start on the actual button class! The first thing we are going to add is some fields :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Store the MouseState of the last frame.</span><br /><span style="color: #0000ff">private</span> MouseState previousState;<br /><br /><span style="color: #008000">// The the different state textures.</span><br /><span style="color: #0000ff">private</span> Texture2D hoverTexture;<br /><span style="color: #0000ff">private</span> Texture2D pressedTexture;<br /><br /><span style="color: #008000">// A rectangle that covers the button.</span><br /><span style="color: #0000ff">private</span> Rectangle bounds;<br /><br /><span style="color: #008000">// Store the current state of the button.</span><br /><span style="color: #0000ff">private</span> ButtonStatus state = ButtonStatus.Normal;</pre><br />These fields should explain themselves, so I'm just going to move onto the constructor :</div><div><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Constructs a new button.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #008000">/// <param name="texture">The normal texture for the button.</param></span><br /><span style="color: #008000">/// <param name="hoverTexture">The texture drawn when the mouse is over the button.</param></span><br /><span style="color: #008000">/// <param name="pressedTexture">The texture drawn when the button has been pressed.</param></span><br /><span style="color: #008000">/// <param name="position">The position where the button will be drawn.</param></span><br /><span style="color: #0000ff">public</span> Button(Texture2D texture, Texture2D hoverTexture, Texture2D pressedTexture, Vector2 position)<br /> : <span style="color: #0000ff">base</span>(texture, position)<br />{<br /> <span style="color: #0000ff">this</span>.hoverTexture = hoverTexture;<br /> <span style="color: #0000ff">this</span>.pressedTexture = pressedTexture;<br /><br /> <span style="color: #0000ff">this</span>.bounds = <span style="color: #0000ff">new</span> Rectangle((<span style="color: #0000ff">int</span>)position.X, (<span style="color: #0000ff">int</span>)position.Y,<br /> texture.Width, texture.Height);<br />}</pre><br /></div><div>This constructor takes in three different textures, each one controls the appearance of the different button states. We also initialize the bounds rectangle to fit around the button based on the buttons position and the sizes of the texture.</div><br /><div>Next we are going to add in a method to update the state of the button :</div><br /><div id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Updates the buttons state.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #008000">/// <param name="gameTime">The current game time.</param></span><br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime)<br />{<br /><br />}</pre> </div><p>The first thing we do in this method is get the current position of the mouse and check whether it is over the button :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Determine if the mouse if over the button.</span><br />MouseState mouseState = Mouse.GetState();<br /><br /><span style="color: #0000ff">int</span> mouseX = mouseState.X;<br /><span style="color: #0000ff">int</span> mouseY = mouseState.Y;<br /><br /><span style="color: #0000ff">bool</span> isMouseOver = bounds.Contains(mouseX, mouseY);</pre><br />We then use this information to either change the button state to <strong>MouseOver</strong> or to change it back to <strong>Normal</strong> :</div><div id="codeSnippetWrapper"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Update the button state.</span><br /><span style="color: #0000ff">if</span> (isMouseOver && state != ButtonStatus.Pressed)<br />{<br /> state = ButtonStatus.MouseOver;<br />}<br /><span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (isMouseOver == <span style="color: #0000ff">false</span> && state != ButtonStatus.Pressed)<br />{<br /> state = ButtonStatus.Normal;<br />}</pre><br />Lastly we check whether the player pressed the mouse while it was over the button, and then if he let it up again while the mouse was still over the button :</div><br /><div id="codeSnippetWrapper"><div id="codeSnippetWrapper"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Check if the player holds down the button.</span><br /><span style="color: #0000ff">if</span> (mouseState.LeftButton == ButtonState.Pressed &&<br /> previousState.LeftButton == ButtonState.Released)<br />{<br /> <span style="color: #0000ff">if</span> (isMouseOver == <span style="color: #0000ff">true</span>)<br /> {<br /> <span style="color: #008000">// Update the button state.</span><br /> state = ButtonStatus.Pressed;<br /> }<br />}<br /><br /><span style="color: #008000">// Check if the player releases the button.</span><br /><span style="color: #0000ff">if</span> (mouseState.LeftButton == ButtonState.Released &&<br /> previousState.LeftButton == ButtonState.Pressed)<br />{<br /> <span style="color: #0000ff">if</span> (isMouseOver == <span style="color: #0000ff">true</span>)<br /> {<br /> <span style="color: #008000">// update the button state.</span><br /> state = ButtonStatus.MouseOver;<br /> }<br /><br /> <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (state == ButtonStatus.Pressed)<br /> {<br /> state = ButtonStatus.Normal;<br /> }<br />}<br /><br />previousState = mouseState;</pre><br /></div></div><p>The next method we are going to add is one that is responsible for drawing the button :</p><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Draws the button.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #008000">/// <param name="spriteBatch">A SpriteBatch that has been started</param></span><br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Draw(SpriteBatch spriteBatch)<br />{<br /> <span style="color: #0000ff">switch</span> (state)<br /> {<br /> <span style="color: #0000ff">case</span> ButtonStatus.Normal:<br /> spriteBatch.Draw(texture, bounds, Color.White);<br /> <span style="color: #0000ff">break</span>;<br /> <span style="color: #0000ff">case</span> ButtonStatus.MouseOver:<br /> spriteBatch.Draw(hoverTexture, bounds, Color.White);<br /> <span style="color: #0000ff">break</span>;<br /> <span style="color: #0000ff">case</span> ButtonStatus.Pressed:<br /> spriteBatch.Draw(pressedTexture, bounds, Color.White);<br /> <span style="color: #0000ff">break</span>;<br /> <span style="color: #0000ff">default</span>:<br /> spriteBatch.Draw(texture, bounds, Color.White);<br /> <span style="color: #0000ff">break</span>;<br /> }<br />}</pre><br />We draw a different texture depending on what state the button is in.<br /><br />And that’s the button class finished for now, we will come back to it later to add in events.<br /><br />Before we add a button to our toolbar we will need to add some new images to our project. Download the images I uploaded at the start of the tutorial and then add them into a new folder called GUI in the Content Project. I know these aren't the greatest images in the world but they’re the best my art skills can create!<br /><br />Now we are ready to add a button to our toolbar, go back to “<strong>Game1.cs</strong>” and add a field for a button :<br /><div id="codeSnippetWrapper"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">Button arrowButton;</pre><br />Next we need to load in our button textures and pass them to our button, add the following to <strong>LoadContent </strong>:</div><div id="codeSnippetWrapper"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// The "Normal" texture for the arrow button.</span><br />Texture2D arrowNormal = Content.Load<Texture2D>(<span style="color: #006080">"GUI\\Arrow Tower\\arrow button"</span>);<br /><span style="color: #008000">// The "MouseOver" texture for the arrow button.</span><br />Texture2D arrowHover = Content.Load<Texture2D>(<span style="color: #006080">"GUI\\Arrow Tower\\arrow hover"</span>);<br /><span style="color: #008000">// The "Pressed" texture for the arrow button.</span><br />Texture2D arrowPressed = Content.Load<Texture2D>(<span style="color: #006080">"GUI\\Arrow Tower\\arrow pressed"</span>);<br /><br /><span style="color: #008000">// Initialize the arrow button.</span><br />arrowButton = <span style="color: #0000ff">new</span> Button(arrowNormal, arrowHover,<br /> arrowPressed, <span style="color: #0000ff">new</span> Vector2(0, level.Height * 32));</pre></div><p>All that’s left is to update and draw the button; in the <strong>Update</strong> method update the button :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">//Update the arrow button.</span><br />arrowButton.Update(gameTime);</pre><br />And in the <strong>Draw</strong> method, just after you draw the toolbar, draw the button :</div><div id="codeSnippetWrapper"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Draw the tool bar first,</span><br />toolBar.Draw(spriteBatch, player);<br /><span style="color: #008000">// and then our buttons.</span><br />arrowButton.Draw(spriteBatch);</pre> </div><p>Hit the F5 key and you will see our new button being drawn in the bottom left corner of our game window, and you should find it is fully interactive with your mouse!</p>So now that we have the button drawn and animated there’s just one thing missing… the ability to detect when the player has clicked the button, let’s go back to “<strong>Button.cs</strong>” and solve this now.<br /><br />Add a new event to the class just under where we define the fields :<br /><br /><span class="Apple-style-span" style="font-family: 'Courier New', courier, monospace; font-size: 11px; color: rgb(0, 128, 0); line-height: 16px; white-space: pre; ">// Gets fired when the button is pressed.</span><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; " id="codeSnippet"><span style="color: rgb(0, 0, 255); ">public</span> <span style="color: rgb(0, 0, 255); ">event</span> EventHandler Clicked;</pre><br /><em>Note : For more information on events see <a href="http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx">http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx</a></em></div><p>All that’s left to do is fire this event when the user clicks so find the <strong>Update</strong> method and find the code that deals with when the player releases the button. This is where we fire our event :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// Check if the player releases the button.</span><br /><span style="color: #0000ff">if</span> (mouseState.LeftButton == ButtonState.Released &&<br /> previousState.LeftButton == ButtonState.Pressed)<br />{<br /> <span style="color: #0000ff">if</span> (isMouseOver == <span style="color: #0000ff">true</span>)<br /> {<br /> <span style="color: #008000">// update the button state.</span><br /> state = ButtonStatus.MouseOver;<br /><br /> <span style="color: #0000ff">if</span> (Clicked != <span style="color: #0000ff">null</span>)<br /> {<br /> <span style="color: #008000">// Fire the clicked event.</span><br /> Clicked(<span style="color: #0000ff">this</span>, EventArgs.Empty);<br /> }<br /> }<br /><br /> <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (state == ButtonStatus.Pressed)<br /> {<br /> state = ButtonStatus.Normal;<br /> }<br />}</pre><br />We first check if the event is null, or in other words if anything attached itself to the event, and, if it has, we fire the event.</div><div><p>And that’s our button class finished for good! All that we have left to do is to attach our button to a method that when called, will allow the player to create a new arrow tower. </p><p>To do this we need to go back to “<strong>Game1.cs</strong>” and find where we initialized the button in the <strong>LoadContent</strong> method. Just under that we will hook up our event to a new method :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">arrowButton.Clicked += <span style="color: #0000ff">new</span> EventHandler(arrowButton_Clicked);</pre><br />Now we need to add a new method called <strong>arrowButton_Clicked</strong> that will be called by the event :</div><br /><span class="Apple-style-span" style="font-family: 'Courier New', courier, monospace; font-size: 11px; line-height: 16px; white-space: pre; "><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> arrowButton_Clicked(<span style="color: #0000ff">object</span> sender, EventArgs e)</span><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; " id="codeSnippet">{<br /> player.NewTowerType = <span style="color: rgb(0, 96, 128); ">"Arrow Tower"</span>;<br />}</pre><br />When this method is called it tells the <strong>Player</strong> class that the player wants to build a new Arrow Tower, the only problem with this code is, the <strong>Player</strong> class doesn’t have a property called NewTowerType, let’s go to “<strong>Player.cs</strong>” now and add one :</div><div id="codeSnippetWrapper"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">// The type of tower to add.</span><br /><span style="color: #0000ff">private</span> <span style="color: #0000ff">string</span> newTowerType;<br /><br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> NewTowerType<br />{<br /> set { newTowerType = <span style="color: #0000ff">value</span>; }<br />}</pre> </div><p>Now that we know what tower we want to build, we need a way to act on this information and create a new tower for the player, lets add a new method to handle this :</p><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #008000">/// <summary></span><br /><span style="color: #008000">/// Adds a tower to the player's collection.</span><br /><span style="color: #008000">/// </summary></span><br /><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> AddTower()<br />{<br /> Tower towerToAdd = <span style="color: #0000ff">null</span>;<br /><br /> <span style="color: #0000ff">switch</span> (newTowerType)<br /> {<br /> <span style="color: #0000ff">case</span> <span style="color: #006080">"Arrow Tower"</span>:<br /> {<br /> towerToAdd = <span style="color: #0000ff">new</span> ArrowTower(towerTexture,<br /> bulletTexture, <span style="color: #0000ff">new</span> Vector2(tileX, tileY));<br /> <span style="color: #0000ff">break</span>;<br /> }<br /> }<br /><br /> <span style="color: #008000">// Only add the tower if there is a space and if the player can afford it.</span><br /> <span style="color: #0000ff">if</span> (IsCellClear() == <span style="color: #0000ff">true</span> && towerToAdd.Cost <= money)<br /> {<br /> towers.Add(towerToAdd);<br /> money -= towerToAdd.Cost;<br /><br /> <span style="color: #008000">// Reset the newTowerType field.</span><br /> newTowerType = <span style="color: #0000ff">string</span>.Empty;<br /> }<br />}</pre><br />What this method does is it checks what type of tower the player wants, and initializes one based on that information. It then checks if there is a space for that tower and also if the player can afford it, and if they can, we add the new tower to the game, charge the player for it, and reset the newTowerType field.</div><br />All that’s left to now is to go to the <strong>Update</strong> method and find the code that used to create tower’s for the player :<br /><br /><span class="Apple-style-span" style="font-family: 'Courier New', courier, monospace; font-size: 11px; line-height: 16px; white-space: pre; "><span style="color: #0000ff">if</span> (mouseState.LeftButton == ButtonState.Released</span><br /><div><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; " id="codeSnippet"> && oldState.LeftButton == ButtonState.Pressed)<br />{<br /> <span style="color: rgb(0, 0, 255); ">if</span> (IsCellClear())<br /> {<br /> Tower tower = <span style="color: rgb(0, 0, 255); ">new</span> Tower(towerTexture, <span style="color: rgb(0, 0, 255); ">new</span> Vector2(tileX, tileY));<br /> towers.Add(tower);<br /> }<br />}</pre><br /></div><div>And replace it with our new method of creating towers :</div><br /><span class="Apple-style-span" style="font-family: 'Courier New', courier, monospace; font-size: 11px; line-height: 16px; white-space: pre; "><span style="color: #0000ff">if</span> (mouseState.LeftButton == ButtonState.Released</span><br /><div id="codeSnippetWrapper"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; " id="codeSnippet"> && oldState.LeftButton == ButtonState.Pressed)<br />{<br /> <span style="color: rgb(0, 0, 255); ">if</span> (<span style="color: rgb(0, 0, 255); ">string</span>.IsNullOrEmpty(newTowerType) == <span style="color: rgb(0, 0, 255); ">false</span>)<br /> {<br /> AddTower();<br /> }<br />}</pre><br />We’re finished! Hit the F5 key and try clicking on a clear space, you should find that no tower is created, however if you click the tower button first and then click a space you should find that a new tower is created and you should also see that the player’s money goes down.</div><br /><a href="http://www.mediafire.com/file/iv6a1b1wavtl3oy/TowerDefenseTutorial_11.zip" target="_blank">Here is the source code for this tutorial.</a><br /><br /><em>Note : As I see it, there is only one more tutorial left in this series which will contain a small bug fix and a small addition to the GUI. However if you have any suggestions for any more tutorials in the series feel free to tell me then and I will see what I can do.</em> </div>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com13tag:blogger.com,1999:blog-8967321114965538903.post-41053461062335630852010-12-17T13:44:00.006+00:002010-12-22T19:23:45.762+00:00Tutorial 10 : Creating the GUI (Part 1)<p> Sorry for the delay in tutorials, but real life got in the way again. In this tutorial we are going to make a start on our games interface, the interface I'm going to show you how to make is going to be incredibly simple for now.</p> <p>By the end of this tutorial we will have a toolbar that runs along the bottom of our game window that will show the player some useful information.</p> <a name='more'></a> <p>So, let’s begin! The first thing that we are going to do is to make our game window a bit longer so we can fit our toolbar along the bottom. Find the Initialize method in “<strong>Game1.cs</strong>” and make the following change :</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">// The width of the level in pixels</span></pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre; ">graphics.PreferredBackBufferWidth = level.Width * 32;</span><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">// The height of the toolbar + the height of the level in pixels</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">graphics.PreferredBackBufferHeight = 32 + level.Height * 32;</pre><!--CRLF--></div></div><p>As you can see all we are doing here is stretching the window a bit. If you ran the game now in it’s current state you should see a blue gap at the bottom of the window, and if you try and click on it it will throw an error : “Index was outside the bounds of the array.” Let's fix that now, go to “<strong>Level.cs</strong>” and find the GetIndex method. We need to change the if statement so it looks like this :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">// It needed to be Width - 1 and Height - 1.</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">if</span> (cellX < 0 || cellX > Width - 1 || cellY < 0 || cellY > Height - 1)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> 0;</pre><br /><!--CRLF--></div></div><p>If you run the game again now and try clicking in the gap no error should be thrown now! Now that’s out of the way, we can add some new assets to our game. Firstly add this texture to our Content Project :</p><p><a href="http://lh4.ggpht.com/_q2VraDVN7Lg/TQtpLp1-RKI/AAAAAAAAAC4/x0JqneUygAw/s1600-h/tool%20bar%5B2%5D.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="tool bar" border="0" alt="tool bar" src="http://lh6.ggpht.com/_q2VraDVN7Lg/TQtpNOfebYI/AAAAAAAAAC8/9rCvMAwqtfA/tool%20bar_thumb.png?imgmax=800" width="244" height="34" /></a></p><p>I know it’s not very inspiring to look at, but that’s programmer art for you <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://lh5.ggpht.com/_q2VraDVN7Lg/TQtpN-z2KoI/AAAAAAAAADA/JZHltsOV-Dc/wlEmoticon-winkingsmile%5B2%5D.png?imgmax=800" />. Next we are going to add a Sprite font to our project, to do this right click in the Content Project and click Add –> New Item and select the Sprite Font option, call it “<strong>Arial.spritefont</strong>” and press ok. </p><p>We are now going to alter some of the font’s properties, so go ahead and open up “Ariel.spritefont” and change the font name to Arial ( or whatever font you like to use ), then change the size to 9, then find where it says Style and change it from Regular to Bold.</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><!--</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Modify <span style="color: #0000ff">this</span> <span style="color: #0000ff">string</span> to change the font that will be imported.</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">--></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><FontName>Arial</FontName></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><!--</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Size <span style="color: #0000ff">is</span> a <span style="color: #0000ff">float</span> <span style="color: #0000ff">value</span>, measured <span style="color: #0000ff">in</span> points. Modify <span style="color: #0000ff">this</span> <span style="color: #0000ff">value</span> to change</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">the size of the font.</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">--></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><Size>9</Size></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><!--</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Style controls the style of the font. Valid entries are <span style="color: #006080">"Regular"</span>, <span style="color: #006080">"Bold"</span>, <span style="color: #006080">"Italic"</span>,</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">and <span style="color: #006080">"Bold, Italic"</span>, and are <span style="color: #0000ff">case</span> sensitive.</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">--></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><Style>Bold</Style></pre><!--CRLF--></div></div><p>And that’s it, we have all of the assets that we will need to draw our toolbar. So let’s actually draw it! Add an new folder to the project called GUI and in it add a new class called “Toolbar.cs”. </p><p>Now we need to add a few fields that will store a texture that we will use to draw the tool bar and one to store our font. We also need two store two vectors that describe where to draw the toolbar and where to draw our text.</p><div id="codeSnippetWrapper"><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> Texture2D texture;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">// A class to access the font we created</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> SpriteFont font;</pre><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">// The position of the toolbar</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> Vector2 position;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">// The position of the text</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> Vector2 textPosition;</pre><!--CRLF--></div></div><p>Next we need to add a constructor to our class :</p><div id="codeSnippetWrapper"><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> Toolbar(Texture2D texture, SpriteFont font, Vector2 position)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.texture = texture;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.font = font;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><br /></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.position = position;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #008000">// Offset the text to the bottom right corner</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> textPosition = <span style="color: #0000ff">new</span> Vector2(130, position.Y + 10);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><p>It is a pretty standard constructor with the only thing worth noticing is the bottom line where initialize the textPosition field. If you are wondering where 130 and 10 came from, these are just numbers I picked after playing around with the position of the text, you can set these to anything you want to change the position of the text.</p><p>The last thing we are going to add to this class for now is a draw method :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Draw(SpriteBatch spriteBatch, Player player)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> spriteBatch.Draw(texture, position, Color.White);</pre><!--CRLF--><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">string</span> text = <span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"Gold : {0} Lives : {1}"</span>, player.Money, player.Lives);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> spriteBatch.DrawString(font, text, textPosition, Color.White);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><br /><div>Notice that we pass in a reference to the player class so that we can access how many lives he has left and how much gold he has so we can draw that on our toolbar.</div><br /><div>Right, that’s it for our toolbar class finished for now, we will come back to it in later tutorials to add some buttons! For now though go back to “<strong>Game1.cs</strong>” and add the following field :</div><div id="codeSnippetWrapper"><br /><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Toolbar toolBar;</pre><br /><!--CRLF--></div></div><p>Now let’s go to the LoadContent method and load in the texture and font we added in earlier and use them to initialize our toolbar :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Texture2D topBar = Content.Load<Texture2D>(<span style="color: #006080">"tool bar"</span>);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">SpriteFont font = Content.Load<SpriteFont>(<span style="color: #006080">"Arial"</span>);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">toolBar = <span style="color: #0000ff">new</span> Toolbar(topBar, font, <span style="color: #0000ff">new</span> Vector2(0, level.Height * 32));</pre><!--CRLF--></div></div><p>Finally, all that’s left to do is draw our tool bar so go to the Draw method and add the following just before we end the sprite batch :</p><div id="codeSnippetWrapper"><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">toolBar.Draw(spriteBatch, player);</pre><br /><!--CRLF--></div><br />Now when you run the game the blue gap at the bottom of our window should be replaced with our shiny new toolbar! Next time we will be adding some buttons to our toolbar.<br /><br /><p><a href="http://www.mediafire.com/file/ccctcmm47k7ax7c/TowerDefenseTutorial_10.zip" target="_blank">Here is the source code for this tutorial</a></p><br /></div>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com8tag:blogger.com,1999:blog-8967321114965538903.post-31815469887675367222010-10-29T12:06:00.003+01:002010-10-29T12:19:10.518+01:00Tutorial 9 : Multiple Waves<p>In this tutorial we are going to create the class that will handle the creation of our waves, update our waves, and then move the player onto the next wave when the previous one has finished. </p> <p>This will be one of the most important classes in our game. We are going to store all our waves in one big queue, and just move through them one by one with a short period of time in-between waves so the player has time to breath and make new towers. This class will also determine how many enemies we create per wave, so we can make the waves harder as time progresses.</p> <a name='more'></a> <p>So, let’s get started, start off by creating a new class called “WaveManager.cs” and add the following fields and properties :</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; " id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> numberOfWaves; <span style="color: #008000">// How many waves the game will have</span></pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre; "><span style="color: #0000ff">private</span> <span style="color: #0000ff">float</span> timeSinceLastWave; <span style="color: #008000">// How long since the last wave ended</span></span><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "><span style="color: #0000ff">private</span> Queue<Wave> waves = <span style="color: #0000ff">new</span> Queue<Wave>(); <span style="color: #008000">// A queue of all our waves</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "><span style="color: #0000ff">private</span> Texture2D enemyTexture; <span style="color: #008000">// The texture used to draw the enemies</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "><span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> waveFinished = <span style="color: #0000ff">false</span>; <span style="color: #008000">// Is the current wave over?</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "><span style="color: #0000ff">private</span> Level level; <span style="color: #008000">// A reference to our level class</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "><span style="color: #0000ff">public</span> Wave CurrentWave <span style="color: #008000">// Get the wave at the front of the queue</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; ">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "> get { <span style="color: #0000ff">return</span> waves.Peek(); }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; ">}</pre><!--CRLF--><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "><span style="color: #0000ff">public</span> List<Enemy> Enemies <span style="color: #008000">// Get a list of the current enemeies</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; ">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "> get { <span style="color: #0000ff">return</span> CurrentWave.Enemies; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; ">}</pre><!--CRLF--><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Round <span style="color: #008000">// Returns the wave number</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; ">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244, 244, 244); margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; "> get { <span style="color: #0000ff">return</span> CurrentWave.RoundNumber + 1; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow-x: visible; overflow-y: visible; padding-top: 0px; ">}</pre><br /><!--CRLF--></div></div><br /><div>As I explained earlier we are going to store our waves in a queue so we can access our waves in the order they were added. Next we are going to add in a constructor for the class :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> WaveManager(Level level, <span style="color: #0000ff">int</span> numberOfWaves, Texture2D enemyTexture)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.numberOfWaves = numberOfWaves;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.enemyTexture = enemyTexture;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><br /></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.level = level;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i < numberOfWaves; i++)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">int</span> initialNumerOfEnemies = 6;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">int</span> numberModifier = (i / 6) + 1;</pre><!--CRLF--><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Wave wave = <span style="color: #0000ff">new</span> Wave(i, initialNumerOfEnemies * </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> numberModifier, level, enemyTexture);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> waves.Enqueue(wave);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div></div><br /><div>This is where we are going to create all of the waves for the game. As you can see we progressively add wave after wave with the use of a for loop. The only interesting part of this method are the first two lines in the for loop.</div><div><br /></div><div>These two lines alter the number of enemies each wave has, basically what these two lines do is every six waves, six extra enemies are produced. So for example the 1st, 2nd, 3rd, 4th and 5th waves will have 6 enemies, the 6th, 7th, 8th, 9th, 10th and 11th waves will have 12 enemies, and the 12th 13th… wave will have 18 enemies.</div><br /><div>Of course the mechanism is extremely boring and in your own games you are probably going to want to add in boss levels, or fast levels etc, but for simplicity, this is all we are going to do.</div><br /><div>Now we are going to add a method that will start the next wave :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> StartNextWave()</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (waves.Count > 0) <span style="color: #008000">// If there are still waves left</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> waves.Peek().Start(); <span style="color: #008000">// Start the next one</span></pre><!--CRLF--><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> timeSinceLastWave = 0; <span style="color: #008000">// Reset timer</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> waveFinished = <span style="color: #0000ff">false</span>;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br />Here we just check if there is a wave to start, and if there is we start it, and reset our timer. We need to add a call to this method in our constructor otherwise our waves will never start! At the bottom of the constructor add this :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">StartNextWave();</pre><br /><!--CRLF--></div></div><p>All that is left to do now is to update our waves and then draw them, let’s start by updating them :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> CurrentWave.Update(gameTime); <span style="color: #008000">// Update the wave</span></pre><!--CRLF--><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (CurrentWave.RoundOver) <span style="color: #008000">// Check if it has finished</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> waveFinished = <span style="color: #0000ff">true</span>;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (waveFinished) <span style="color: #008000">// If it has finished</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> timeSinceLastWave += (<span style="color: #0000ff">float</span>)gameTime.ElapsedGameTime.TotalSeconds; <span style="color: #008000">// Start the timer</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre><!--CRLF--><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (timeSinceLastWave > 30.0f) <span style="color: #008000">// If 30 seconds has passed</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> waves.Dequeue(); <span style="color: #008000">// Remove the finished wave</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> StartNextWave(); <span style="color: #008000">// Start the next wave</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div></div></div><br /><div>As you can see there is nothing complicated happening here, we just update the wave we are on, and when it has finished, we wait 30 seconds, and then move onto the next wave. Simples!</div><br /><div>Lastly, we just need to add a way to draw our current wave :</div><div id="codeSnippetWrapper"><br /><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Draw(SpriteBatch spriteBatch)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> CurrentWave.Draw(spriteBatch);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div></div><br /><div>And there we have it, an easy way of handling multiple waves! All that’s left to do now is to update “Game1.cs” to use our new WaveManager.</div><br /><div>Go to “Game1.cs” and at the top of the class replace where we created our wave with this :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">//Wave wave;</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">WaveManager waveManager;</pre><!--CRLF--></div></div><p>Then in our LoadContent() method instead of initializing a single wave, initialize our wave manager :</p><div id="codeSnippetWrapper"><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">//wave = new Wave(0, 10, level, enemyTexture);</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">//wave.Start();</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">waveManager = <span style="color: #0000ff">new</span> WaveManager(level, 24, enemyTexture);</pre><!--CRLF--></div><br /></div><div>Update our WaveManager in the Update() method and make sure to pass in the list of enemies from our current wave to the player :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> waveManager.Update(gameTime);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> player.Update(gameTime, waveManager.Enemies);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.Update(gameTime);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><br /><div>Finally in the draw method, draw our WaveManager instead of the single Wave :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">//wave.Draw(spriteBatch);</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">waveManager.Draw(spriteBatch);</pre><!--CRLF--></div><br /></div><p>And we are finished, we now have multiple waves!!</p><p><a href="http://www.mediafire.com/file/8a3ssi5w7o7b764/TowerDefenseTutorial_9.zip" target="_blank">Here is the source code for this tutorial.</a></p>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com36tag:blogger.com,1999:blog-8967321114965538903.post-34623663529006838262010-10-05T19:20:00.006+01:002010-12-17T15:50:47.473+00:00Tutorial 8 : Waves (Featuring Tower Modifications)<div align="left">In this tutorial we will be focusing on creating so called “waves” of units. </div><div align="left">We will start off by fixing some nasty bugs that I overlooked in the last two tutorials. </div><div align="left">Then we will move onto creating our Wave class. This will contain information such as how many enemies should be created this wave, and which of these created enemies are still alive. It will be responsible for creating, updating and drawing the enemies.<br /><br /></div><div align="left"><em>For the sake of simplicity I am not going to add in any “boss levels” or “fast levels” etc. for now as that would mean coming up with some pretty difficult formulas!</em><br /><em><a name='more'></a></em><br />So, let’s begin, to start with go into “ArrowTower.cs” and find where we update our bullets. We are going to add in some code that will actually make our bullets damage the tower’s target. Just before we check if the bullet is dead add the following :<br /><br /></div><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">if</span> (target != <span style="color: blue;">null</span> && Vector2.Distance(bullet.Center, target.Center) < 12)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> target.CurrentHealth -= bullet.Damage;</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> bullet.Kill();</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre><br /></div></div><div align="left"><br />All this code does is check whether the bullet has hit out target, and if it has, make sure we take some health off of the enemy and then kill the bullet. So where did the 12 come from – quite simply it is this :</div><div align="center"><br />(width of bullet / 2) + (width of enemy / 2) = (12 / 2) + (12 / 2)<br /><br /></div>So now the code to update our bullets should look like this :<br /><br /><div align="left"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">for</span> (<span style="color: blue;">int</span> i = 0; i < bulletList.Count; i++)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> Bullet bullet = bulletList[i];</pre><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> bullet.SetRotation(rotation);</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> bullet.Update(gameTime);</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> if</span> (!IsInRange(bullet.Center))</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> bullet.Kill();</pre><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> if</span> (Vector2.Distance(bullet.Center, target.Center) < 12)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> {</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> target.CurrentHealth -= bullet.Damage;</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> bullet.Kill();</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> }</pre><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> if</span> (bullet.IsDead())</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> {</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> bulletList.Remove(bullet);</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> i--;</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> }</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre></div><br /></div><div align="left">Next you need to go to Tower.cs and, in the Update method, find the lines that look like this :</div><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">if</span> (target != <span style="color: blue;">null</span>)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> FaceTarget();</pre> <br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> if</span> (!IsInRange(target.Center))</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> {</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> target = <span style="color: blue;">null</span>;</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> bulletTimer = 0;</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> }</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre></div></div>and replace them with these :<br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">if</span> (target != <span style="color: blue;">null</span>)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> FaceTarget();</pre><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"></span></span><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> if</span> (!IsInRange(target.Center) || target.IsDead)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> {</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> target = <span style="color: blue;">null</span>;</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> bulletTimer = 0;</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> }</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre></div><br /></div><strong><em>I’m sorry I missed these things out in the last tutorial!! I would have just modified the last tutorials to fix these bugs but I thought it might confuse some people.</em></strong><br /><br />And that’s our modifications to the tower class finished. If you run the project now and place a tower, it should shoot the enemy and the enemy should gradually change colour when hit.<br /><br /><div align="left">Right, let’s move onto our waves, create a new class called “Wave.cs” and add the following fields and variables :</div><br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">int</span> numOfEnemies; <span style="color: green;">// Number of enemies to spawn</span></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">int</span> waveNumber; <span style="color: green;">// What wave is this?</span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">float</span> spawnTimer = 0; <span style="color: green;">// When should we spawn an enemy</span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">int</span> enemiesSpawned = 0; <span style="color: green;">// How mant enemies have spawned</span></pre> <br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">bool</span> enemyAtEnd; <span style="color: green;">// Has an enemy reached the end of the path?</span></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">bool</span> spawningEnemies; <span style="color: green;">// Are we still spawing enemies?</span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> Level level; <span style="color: green;">// A reference of the level</span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> Texture2D enemyTexture; <span style="color: green;">// A texture for the enemies</span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> List<Enemy> enemies = <span style="color: blue;">new</span> List<Enemy>(); <span style="color: green;">// List of enemies</span></pre> <br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">bool</span> RoundOver</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> get </pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> { </pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> return</span> enemies.Count == 0 && enemiesSpawned == numOfEnemies; </pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> }</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">int</span> RoundNumber</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> get { <span style="color: blue;">return</span> waveNumber; }</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">bool</span> EnemyAtEnd</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> get { <span style="color: blue;">return</span> enemyAtEnd; }</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> set { enemyAtEnd = <span style="color: blue;">value</span>; }</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> List<Enemy> Enemies</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> get { <span style="color: blue;">return</span> enemies;}</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre><br /></div><br /></div><div align="left">A lot of these variables should explain themselves, however it may not be clear why we have added a couple of them. The reason we have a reference to the Level class is so that we can access the level’s waypoints. We must also store a copy of the enemy texture so that can be passed to the enemy when we create it.</div><br /><div align="left">Next we will add a constructor for the class :</div><br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> Wave(<span style="color: blue;">int</span> waveNumber, <span style="color: blue;">int</span> numOfEnemies,</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> Level level, Texture2D enemyTexture)</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> this</span>.waveNumber = waveNumber;</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> this</span>.numOfEnemies = numOfEnemies;</pre> <br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> this</span>.level = level;</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> this</span>.enemyTexture = enemyTexture;</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre><br /></div></div><div>I’m not going to insult you be explaining this :P. Now we are going to add to add three new methods, one to update the wave, and one to start the wave and one to add a new enemy. Here is the first :</div><br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">void</span> AddEnemy()</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> Enemy enemy = <span style="color: blue;">new</span> Enemy(enemyTexture,</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> level.Waypoints.Peek(), 50, 1, 0.5f);</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> enemy.SetWaypoints(level.Waypoints);</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> enemies.Add(enemy);</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span class="Apple-style-span" style="white-space: normal;"></span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> spawnTimer = 0;</pre><br /><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> enemiesSpawned++;</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre><br /></div></div><div><br /></div><div>This is most of the magic of the wave class will happen. This is the method were you can alter the stats of the enemy based on the wave number. e.g Say that you want wave 5 to be a fast stage, you would do something like this :</div><br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">if</span> (waveNumber == 5)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> float</span> speed = 2.0f;</pre><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> enemy = <span style="color: blue;">new</span> Enemy(enemyTexture,</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> level.Waypoints.Peek(), 50, 1, speed);</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> enemy.SetWaypoints(level.Waypoints);</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre><br /></div></div><br /><div>The second method we will add looks like this :</div><br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">void</span> Start()</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> spawningEnemies = <span style="color: blue;">true</span>;</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre></div></div>This method just tells the wave that it is time to start churning out enemies for us to gun down. Before we can move onto the Update method, go to Enemy.cs and replace the IsDead property with this :<br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">bool</span> IsDead</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> get { <span style="color: blue;">return</span> !alive; }</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre></div></div>We needed to make this change because it is no longer enough to make sure that an enemy has health, we also need to make sure is not at the end of the path.<br /><div>Now we can move onto the Update method :</div><br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">void</span> Update(GameTime gameTime)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span class="Apple-style-span" style="white-space: normal;"><span class="Apple-style-span" style="white-space: pre;"></span></span></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre></div></div>The first thing we will add to this method is the code to spawn our enemies :<br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">if</span> (enemiesSpawned == numOfEnemies)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> spawningEnemies = <span style="color: blue;">false</span>; <span style="color: green;">// We have spawned enough enemies</span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">if</span> (spawningEnemies)</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> spawnTimer += (<span style="color: blue;">float</span>)gameTime.ElapsedGameTime.TotalSeconds;</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> if</span> (spawnTimer > 2)</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> AddEnemy(); <span style="color: green;">// Time to add a new enemey</span></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre></div></div>First we check if we still need to spawn enemies. Then if we do, we update the time since an enemy was last created. If 2 seconds have passed since the last time we created an enemy, then we will spawn a new enemy.<br />Next we will add some code to update and remove dead enemies :<br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">for</span> (<span style="color: blue;">int</span> i = 0; i < enemies.Count; i++)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> Enemy enemy = enemies[i];</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> enemy.Update(gameTime);</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> if</span> (enemy.IsDead)</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> {</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> if</span> (enemy.CurrentHealth > 0) <span style="color: green;">// Enemy is at the end</span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> {</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> enemyAtEnd = <span style="color: blue;">true</span>;</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> }</pre><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> enemies.Remove(enemy);</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> i--;</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> }</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre></div></div><div><br /></div>Here, after we Update the enemy, we check if he is “dead”. I put “dead” in speech marks because, although IsDead tells us if an enemy should be dead, it can also indicate that the enemy has reached the end of his path. This is what we check for next, if an enemy IsDead but still has health this must mean he is at the end of his path, so we therefore set enemyAtEnd to true seeing an enemy has reached the end.<br />All that is left to do is draw the enemies in this wave :<br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">void</span> Draw(SpriteBatch spriteBatch)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">{</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: blue;"> foreach</span> (Enemy enemy <span style="color: blue;">in</span> enemies)</pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"> enemy.Draw(spriteBatch);</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">}</pre><br /></div></div><div><br /></div><div>And there we have it, our wave class!! Now let’s make a few changes to Game1.cs so our changes will show up. At the top of Game1.cs replace the line were we define our enemy with the following : </div><br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">//Enemy enemy1;</span></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">Wave wave;</pre></div></div><div><br /></div>Next find where we initialize our enemy and replace it with this :<br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">//enemy1 = new Enemy(enemyTexture, Vector2.Zero, 100, 10, 0.5f);</span></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">//enemy1.SetWaypoints(level.Waypoints);</span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">wave = <span style="color: blue;">new</span> Wave(0, 10, level, enemyTexture);</pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">wave.Start();</pre><br /></div></div>After that find where we update our enemy and replace it with this :<br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: rgb(244, 244, 244); border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%; "><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%; "><span style="color: green;">//enemy1.Update(gameTime);</span></pre><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%; "><span style="color: green;">//List<Enemy> enemies = new List<Enemy>();</span></pre><pre style="background-color: rgb(244, 244, 244); border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%; "><span style="color: green;">//enemies.Add(enemy1);</span></pre><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%; "></pre><pre style="background-color: rgb(244, 244, 244); border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%; ">wave.Update(gameTime);</pre><pre style="background-color: rgb(244, 244, 244); border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; margin-top: 0em; margin-right: 0em; margin-bottom: 0em; margin-left: 0em; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%; "><span class="Apple-style-span" ><span class="Apple-style-span" style="font-size: 11px; line-height: 16px;">player.Update(gameTime, wave</span></span><span class="Apple-style-span" style="font-family: 'Courier New', courier, monospace; font-size: 11px; line-height: 16px; ">.Enemies);</span></pre></div></div><div><br /></div>Finally find where we draw the enemy and replace it with this :<br /><div id="codeSnippetWrapper"><div id="codeSnippet" style="background-color: rgb(244, 244, 244); border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; direction: ltr; overflow-x: visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%; line-height: 12pt; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; "><br /><pre style="background-color: white; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;"><span style="color: green;">//enemy.Draw(spriteBatch);</span></pre><pre style="background-color: #f4f4f4; border-bottom-style: none; border-left-style: none; border-right-style: none; border-top-style: none; color: black; direction: ltr; font-family: 'Courier New', courier, monospace; font-size: 8pt; line-height: 12pt; margin: 0em; overflow: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 100%;">wave.Draw(spriteBatch);</pre></div><br /></div>Now you should see about ten black dots appear at the start of your path and march to the end!! Happy hunting.<br /><br /><a href="http://www.mediafire.com/file/pbfve108uli0rip/TowerDefenseTutorial_8.zip" target="_blank"></a><br /><div><a href="http://www.mediafire.com/file/pbfve108uli0rip/TowerDefenseTutorial_8.zip" target="_blank">Here is the source code for this tutorial.</a> </div>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com25tag:blogger.com,1999:blog-8967321114965538903.post-82098326502836230072010-10-03T16:29:00.005+01:002010-10-03T16:41:57.683+01:00Tutorial 7 : Firepower<p>Now that we have the ability to place down tower’s and have a basic targeting system working, we can move onto making our tower’s shoot so we can finally obliterate that little black dot smugly walking along our path!</p> <p>We are going to start off by creating our first type of tower, the “Arrow Tower”, then move on to creating a “Bullet” class, and to top it all off, we will combine the two classes and create a targeting shooting tower.</p> <a name='more'></a> <p>Right, let’s begin! Before we create our new type of tower, there are a couple of changes we need to make to “Tower.cs”. Add the following field to the Tower class :</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> Texture2D bulletTexture;</pre></div></div><p>Then modify the constructor so it looks like this :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> Tower(Texture2D texture, Texture2D bulletTexture, Vector2 position)</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> : <span style="color: #0000ff">base</span>(texture, position)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.bulletTexture = bulletTexture;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><div><br /></div><div>You will notice the new constructor takes in another texture, this will be the texture that is used when drawing all the towers bullets.</div><div><br /></div><div>With those small changes done, add a new class to the project called “ArrowTower.cs” and modify it so it looks like the following :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ArrowTower : Tower</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> ArrowTower(Texture2D texture, Texture2D bulletTexture, Vector2 position)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> : <span style="color: #0000ff">base</span>(texture, bulletTexture, position)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.damage = 15; <span style="color: #008000">// Set the damage</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.cost = 15; <span style="color: #008000">// Set the initial cost</span></pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.radius = 80; <span style="color: #008000">// Set the radius</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><div><br /></div><div>All we are doing here is making our new class inherit from the Tower class, and setting up the tower’s settings in the tower’s constructor. That is it for our ArrowTower class for now, we will come back to it later to add in an Update method where our bullets will be created. But before we can create a bullet, we need to create a Bullet class. So let’s do that now, add a new class called “Bullet.cs” and modify it so it looks like this :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Bullet : Sprite</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> damage;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> age;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> speed;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Damage</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> damage; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> IsDead()</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> age > 100;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> Bullet(Texture2D texture, Vector2 position, <span style="color: #0000ff">float</span> rotation, </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">int</span> speed, <span style="color: #0000ff">int</span> damage) : <span style="color: #0000ff">base</span>(texture, position)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.rotation = rotation;</pre><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.damage = damage;</pre><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.speed = speed;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br /></div><div>This is the basic shell for our bullet class, all the fields and properties should be pretty obvious except maybe for age. We will use the age field to track when a bullet should die. Next we are going to add in a simple method to “kill” the bullet :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Kill()</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.age = 200;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br />I’m sure you are asking, how will this kill a bullet? Well, if you look up at the last bit of code we added in the “IsDead” property, you will see that if a bullet is older than 100, it is classed as dead, so by setting a bullet’s age to 200, we are essentially killing it.<br />One of the final things we are going to add is an update method for the bullet, without this, the bullets would just sit in the barrel of the tower doing nothing :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> age++;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> position += velocity;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.Update(gameTime);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><div>It’s pretty simple what we are doing here, first we increase the age of the bullet, if we didn’t do this and by some bug the bullet didn’t hit an enemy, it could live forever! Next we are add the velocity of the bullet onto it’s position, and I know what your going to say, that ‘Wait, we haven’t set a velocity yet!’ and that’s what we are going to do next.</div><br />In the real world, when we shoot a bullet out of a gun, it is pretty much going to move linearly (in a straight line) until it hits something, but we aren't making a simulation! It would be frustration for the player if his towers never hit any enemies because they moved to fast and the bullets just zoomed behind the enemies! So we are going to cheat, we are going to “bend” our bullets, as if we were in the film “Wanted”. To do this, every frame we are going to making sure our bullet is moving towards our target :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> SetRotation(<span style="color: #0000ff">float</span> <span style="color: #0000ff">value</span>)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> rotation = <span style="color: #0000ff">value</span>;</pre><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> velocity = Vector2.Transform(<span style="color: #0000ff">new</span> Vector2(0, -speed), </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Matrix.CreateRotationZ(rotation));</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div><br /></div><div>I’m not sure if you have come across the Transform method before but it is incredibly useful, it allows us to manipulate a vector by using a matrix. In our case we want to rotate a vector representing our speed, to have the same rotation as our tower, like the following example where the dotted arrow represents our initial velocity before rotation:</div><br /><div><a href="http://lh3.ggpht.com/_q2VraDVN7Lg/TKihPrtQlxI/AAAAAAAAACo/qfbs14SfTIg/s1600-h/diag4.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="diag" border="0" alt="diag" src="http://lh3.ggpht.com/_q2VraDVN7Lg/TKihQq1s_OI/AAAAAAAAACs/rwmU0NnzXjQ/diag_thumb2.png?imgmax=800" width="80" height="80" /></a><br /></div><div>We are using the Matrix.CreateRotationZ method because we want to rotate the velocity around the axis that sticks out of the screen. One thing to notice is we use -speed. This is because when the tower hasn't been rotated it points up, which in terms of vectors is (0, -1). Right, that’s our bullet class finished.</div><br /><i><a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2D/Angle_to_Direction.php">For more information on this see Riemers Tutorial.</a></i></div><div id="codeSnippetWrapper"><i><a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2D/Angle_to_Direction.php"></a><br /></i> <div> </div><div>We are now going to make a few more changes to Tower.cs, at the top of Tower add the following fields :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> <span style="color: #0000ff">float</span> bulletTimer; <span style="color: #008000">// How long ago was a bullet fired</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> List<Bullet> bulletList = <span style="color: #0000ff">new</span> List<Bullet>();</pre><!--CRLF--></div></div><br /><div>The bulletTimer field will track the time since the last bullet fired, we can use this to work out when the next bullet should be fired. The second field will just store all our bullets in a handy list.</div><div><br /></div> <div>Now we are going to have to modify the update method so it looks like this :</div><div><br /></div><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.Update(gameTime);</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bulletTimer += (<span style="color: #0000ff">float</span>)gameTime.ElapsedGameTime.TotalSeconds;</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (target != <span style="color: #0000ff">null</span>)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> FaceTarget();</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (!IsInRange(target.Center))</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> target = <span style="color: #0000ff">null</span>;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bulletTimer = 0;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div></div><br /><div>Let’s go through the changes step by step.</div><div><br /></div><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">bulletTimer += (<span style="color: #0000ff">float</span>)gameTime.ElapsedGameTime.TotalSeconds;</pre><br /><!--CRLF--></div><br />This line just updates the timer, this will be set to zero when a bullet is fired.<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">if</span> (!IsInRange(target.Center))</pre><!--CRLF--><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> target = <span style="color: #0000ff">null</span>;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bulletTimer = 0;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div><br /></div></div><div>Here we check whether or not our target is in range of the tower, and if it’s not, we set the target to null, there’s no point on wasting ammo on enemies we will never hit! We also reset the bullet timer so that we start the bullet shooting cycle again when a new target is picked.</div><br /><div>Once again it seems like I have overshot myself and called a method that doesn’t even exist, lets fix that now! :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> IsInRange(Vector2 position)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> Vector2.Distance(center, position) <= radius;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br />IsInRange is a very simple method that just checks whether or not a point is within the range of the tower. Last but not least we will add in the method that will draw our bullets :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Draw(SpriteBatch spriteBatch)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">foreach</span> (Bullet bullet <span style="color: #0000ff">in</span> bulletList)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bullet.Draw(spriteBatch);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.Draw(spriteBatch);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div></div><div><br /></div><div>We loop through all the bullets and draw them before we draw our actual tower, this stop’s the bullets being drawn on top of the tower that shot them. And that’s it for now for our tower class!</div><br /><div>We are now going to go back to the ArrowTower class to finish it off by adding an Update method :</div><div id="codeSnippetWrapper"><br /><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.Update(gameTime);</pre><br /><!--CRLF--></div><br /></div>The first thing we are going to do in this method is check whether or not enough time has passed to fire a bullet, and whether or not we actually have something to shoot at. If both checks come back true, then we will create a new bullet at the center of the tower, and then reset the timer.<br /><p></p><div id="codeSnippetWrapper"><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">if</span> (bulletTimer >= 0.75f && target != <span style="color: #0000ff">null</span>)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Bullet bullet = <span style="color: #0000ff">new</span> Bullet(bulletTexture, Vector2.Subtract(center,</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">new</span> Vector2(bulletTexture.Width / 2)), rotation, 6, damage);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bulletList.Add(bullet);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bulletTimer = 0;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div></div><br /><div>After that we will loop through all of the bullets and update and “bend” them towards the target. We will also check if the bullet has gone out of range of the tower, and if it has, we will kill it! The last check we will make is whether the bullet is still alive, and if it isn’t, we will remove it from the game :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i < bulletList.Count; i++)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Bullet bullet = bulletList[i];</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bullet.SetRotation(rotation);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bullet.Update(gameTime);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (!IsInRange(bullet.Center))</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bullet.Kill();</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (bullet.IsDead())</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bulletList.Remove(bullet);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> i--;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><br /><div>And that’s it for our towers for now, we should now have a fully functioning tower class, but before it will shoot, we must first update a couple of things.</div><br /><div>Add the following field to Player.cs :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> Texture2D bulletTexture;</pre><br /><!--CRLF--></div></div><br /><div>Then change the constructor to this :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> Player(Level level, Texture2D towerTexture, Texture2D bulletTexture)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.level = level;</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.towerTexture = towerTexture;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.bulletTexture = bulletTexture;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div><br /></div><p>Lastly find the following line in the Update method :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Tower tower = <span style="color: #0000ff">new</span> Tower(towerTexture, <span style="color: #0000ff">new</span> Vector2(tileX, tileY));</pre><br /><!--CRLF--></div></div><p>And replace it with this :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">ArrowTower tower = <span style="color: #0000ff">new</span> ArrowTower(towerTexture, </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> bulletTexture, <span style="color: #0000ff">new</span> Vector2(tileX, tileY));</pre><br /><!--CRLF--></div><br /></div><p>All that is left now is to go into Game1.cs and find the code where we create a new Player, and replace it with this :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Texture2D towerTexture = Content.Load<Texture2D>(<span style="color: #006080">"arrow tower"</span>);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Texture2D bulletTexture = Content.Load<Texture2D>(<span style="color: #006080">"bullet"</span>);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">player = <span style="color: #0000ff">new</span> Player(level, towerTexture, bulletTexture);</pre><!--CRLF--></div></div><p>Then all we must do is add the following image to the Content Project :</p><p><a href="http://lh6.ggpht.com/_q2VraDVN7Lg/TKihRbfogCI/AAAAAAAAACw/Y5hY4cM76Js/s1600-h/bullet4.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="bullet" border="0" alt="bullet" src="http://lh5.ggpht.com/_q2VraDVN7Lg/TKihScqjuWI/AAAAAAAAAC0/ADVamMVwtSI/bullet_thumb2.png?imgmax=800" width="32" height="32" /></a> That’s it for this tutorial, we now have working shooting towers!!!</p><p><a href="http://www.mediafire.com/file/3a22n3ya4al1ang/TowerDefenseTutorial_7.zip" target="_blank">Here is the source code for this tutorial.</a></p>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com19tag:blogger.com,1999:blog-8967321114965538903.post-9356352592645871642010-09-29T16:15:00.003+01:002010-09-29T17:48:41.142+01:00Tutorial 6 : Tower Management<p>This tutorial will mainly focus on how the player will add in new towers through the addition of a new class called “Player.cs”. </p> <p>The Player class will hold all the information about a specific player, such as how much money he has, what stage he is on etc. The reason we are putting all this information in it’s own class and not just in “Game1.cs” is that if we do decide to make this game multiplayer, it will make it much easier to store information about each person playing.</p> <a name='more'></a> <p>So let’s get started, the first thing we will do as I'm sure you have guessed is add a new class called “Player.cs”. To start with we are going to add a few fields and properties :</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> money = 50;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> lives = 30;</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> List<Tower> towers = <span style="color: #0000ff">new</span> List<Tower>();</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> MouseState mouseState; <span style="color: #008000">// Mouse state for the current frame</span></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> MouseState oldState; <span style="color: #008000">// Mouse state for the previous frame</span></pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Money</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> money; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Lives</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> lives; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br /></div><div>The first three fields are pretty self explanatory. The next two describe what is happening with the mouse, we will use them to determine if the player has clicked, and if so where etc.</div><br />Next we are going to add in one more field and a constructor for the class :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> Level level;</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> Player(Level level)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.level = level;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br /></div><div>We are going to pass in a reference to the level, this will come in handy when the player wants to add a new tower, as we can use the level class to make sure the tower fits on the level and that we don’t place any towers over paths.</div><br />Now we are going to add in an Update method for our Player, this is where we will handle the creation of new towers, and also the updating of existing towers.<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> cellX;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> cellY;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> tileX;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> tileY;</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime, List<Enemy> enemies)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> mouseState = Mouse.GetState();</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> cellX = (<span style="color: #0000ff">int</span>)(mouseState.X / 32); <span style="color: #008000">// Convert the position of the mouse</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> cellY = (<span style="color: #0000ff">int</span>)(mouseState.Y / 32); <span style="color: #008000">// from array space to level space</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> tileX = cellX * 32; <span style="color: #008000">// Convert from array space to level space</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> tileY = cellY * 32; <span style="color: #008000">// Convert from array space to level space</span></pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> oldState = mouseState; <span style="color: #008000">// Set the oldState so it becomes the state of the previous frame.</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div></div><p>Right, I know this method looks completely pointless but I assure you it’s not!! The first and last lines are quite straight forward, we just update the mouseState so it is correct for the current frame, and update the oldState so it is correct for the previous frame. Now I’m sure your asking your self why are we dividing the mouse position by 32 only to multiply it by 32 again. </p><p>The reason if quite simple really, if you think about what happens when you divide a floating point number by another floating point number, and then cast it to and integer, you will get the integer part number of the number. So lets take a look at an example :</p><p><a href="http://lh6.ggpht.com/_q2VraDVN7Lg/TKNX80xfw6I/AAAAAAAAACg/COHTtaCyEys/s1600-h/image4.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_q2VraDVN7Lg/TKNX9GlAbTI/AAAAAAAAACk/m8HFrPvqtVE/image_thumb2.png?imgmax=800" width="130" height="130" /></a><br /></p><p>In the above example if the mouse was at position (77, 114) and we use the above equation to calculate where that is in array space we get the following :</p><p>CellX = (int) (77 / 32)</p><p> = (int) (2.40625)</p><p> = 2</p><p>Which is correct, as we can see in the image the point is in the third square along. Now we know what cell the pointer is in we can work out where that cell is in level space by multiplying it by 32 (The the widow of our tiles)</p><p>TileX = 2 * 32 = 64</p><br />Which is the level space position of the top right corner of the 3rd tile along, so hopefully now you can see why this works.<br /><br /><div>Before we handle creating new towers, first we will add in short helper method to make adding a new tower easier, and before we can do that, we need to add a new method to Level.cs. Go to Level.cs and add the following :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> GetIndex(<span style="color: #0000ff">int</span> cellX, <span style="color: #0000ff">int</span> cellY)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (cellX < 0 || cellX > Width || cellY < 0 || cellY > Height)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> 0;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> map[cellY, cellX];</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><p>All this code does is return the index of the requested cell. We can use this index to check if we are on a path or not. Right, now we are ready to add the following method to “Player.cs” :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> IsCellClear()</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">bool</span> inBounds = cellX >= 0 && cellY >= 0 && <span style="color: #008000">// Make sure tower is within limits</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> cellX < level.Width && cellY < level.Height; </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">bool</span> spaceClear = <span style="color: #0000ff">true</span>;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">foreach</span> (Tower tower <span style="color: #0000ff">in</span> towers) <span style="color: #008000">// Check that there is no tower here</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> spaceClear = (tower.Position != <span style="color: #0000ff">new</span> Vector2(tileX, tileY));</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (!spaceClear)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">break</span>;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">bool</span> onPath = (level.GetIndex(cellX, cellY) != 1);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> inBounds && spaceClear && onPath; <span style="color: #008000">// If both checks are true return true</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div><br /></div><div>The first thing we do here is check whether the cell the mouse is in is actually part of our level i.e. not floating off the screen somewhere. Next we loop through all of the towers the player currently owns, and make sure that there isn’t a tower already in that tile. Then we check to see if the cell has an index of 1 (the index of a path).</div><br />Now, as you may have noticed in this method we are trying to access tower.Position, but we never actually created that property in the sprite class… my bad. So lets go to “Sprite.cs” and add the following property :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> Vector2 Position</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> position; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br /></div>With that added, we can now go back to “Player.cs” and we just need one more field before we can add us some towers. Add the following field :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">private</span> Texture2D towerTexture;</pre><br /><!--CRLF--></div></div><p>Now we need to modify the constructor slightly to allow for a tower texture to be passed in :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> Player(Level level, Texture2D towerTexture)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.level = level;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">this</span>.towerTexture = towerTexture;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><p>And that’s all the fields we will add for now. Next, in the Update method add the following just before where we set oldState :</p><div id="codeSnippetWrapper"><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">if</span> (mouseState.LeftButton == ButtonState.Released</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> && oldState.LeftButton == ButtonState.Pressed)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (IsCellClear())</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Tower tower = <span style="color: #0000ff">new</span> Tower(towerTexture, <span style="color: #0000ff">new</span> Vector2(tileX, tileY));</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> towers.Add(tower);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div><br /></div><div>This little snippet of code is what actually adds a new tower to the game. The first two lines check whether the player had the left mouse button pressed down the last frame and if it is now released this frame i.e did the player just click. Next we check whether or not the cell that the player just clicked in is clear, and if it is, we add in a new tower at the location of the cell.</div><br />We are almost finished with the Player class, but there is one big thing that we are missing, have you spotted it yet? At no point are our towers updated, we will handle this now, just under the code we just added, add the following :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">foreach</span> (Tower tower <span style="color: #0000ff">in</span> towers)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (tower.Target == <span style="color: #0000ff">null</span>)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> tower.GetClosestEnemy(enemies);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> tower.Update(gameTime);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div><br /></div><div>All this little snippet does is loop through all of the players towers, and updates them. It also checks whether the tower has a target or not, and if it doesn’t, it finds one for it.</div><br /><div>So, we now have a new class that handles when new towers are created, and updates all of those towers, but what's the point of that when at the moment we can’t draw them!! Add the following method to the end of the Player class :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> Draw(SpriteBatch spriteBatch)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">foreach</span> (Tower tower <span style="color: #0000ff">in</span> towers)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> tower.Draw(spriteBatch);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><br /><div>And now we’re done, all we have left to do is set up a new player class in Game1 and we are good to go. So, let’s go to “Game1.cs” and replace the line where create define a new tower with the following :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">//Tower tower;</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Player player;</pre><br /><!--CRLF--></div></div><br /><div>Next, find where we initialized the tower and replace it with the following :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Texture2D towerTexture = Content.Load<Texture2D>(<span style="color: #006080">"arrow tower"</span>);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #008000">//tower = new Tower(towerTexture, Vector2.Zero);</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">player = <span style="color: #0000ff">new</span> Player(level, towerTexture);</pre><br /><!--CRLF--></div></div><p>Next replace the update method with this one :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> enemy1.Update(gameTime);</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> List<Enemy> enemies = <span style="color: #0000ff">new</span> List<Enemy>();</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> enemies.Add(enemy1);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><br /></pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> player.Update(gameTime, enemies);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.Update(gameTime);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div><br /></div><div>Finally, make sure your draw method looks like this :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Draw(GameTime gameTime)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> GraphicsDevice.Clear(Color.CornflowerBlue);</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> spriteBatch.Begin(); </pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> level.Draw(spriteBatch);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> enemy1.Draw(spriteBatch);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> player.Draw(spriteBatch);</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> spriteBatch.End();</pre><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.Draw(gameTime);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br /></div><div>And there we have it, a fully functioning player class that enables us to create and update new towers. If you run the project now, and click on empty cells you will see that new towers get created there, and they will all track our enemy.</div><br /><div><a href="http://www.mediafire.com/file/q6apbq53ud69c96/TowerDefenseTutorial_6.zip" target="_blank">Here is the source code for this tutorial.</a></div> </div>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com36tag:blogger.com,1999:blog-8967321114965538903.post-86969636311259202552010-09-26T15:36:00.004+01:002011-01-18T20:33:10.613+00:00Tutorial 5 : Towers<p>Now that we have something to shoot at, I think it is about time that we start adding in the “Tower” part of our Tower Defence. We will start off by creating a simple base class for the tower and getting it drawn, then we will move on to making it aim at our enemy. I will be leaving shooting, and placement of towers till next time. So, lets begin!</p> <a name='more'></a> <p>Start off by adding a new class to the project called “Tower.cs”, and make it inherit from the Sprite class :</p> <div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> Tower : Sprite</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br /></div><div>Next we will add in some of the basic fields and properties that all towers will share :</div><br /><div id="codeSnippetWrapper"><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> <span style="color: #0000ff">int</span> cost; <span style="color: #008000">// How much will the tower cost to make</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> <span style="color: #0000ff">int</span> damage; <span style="color: #008000">// The damage done to enemy's</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> <span style="color: #0000ff">float</span> radius; <span style="color: #008000">// How far the tower can shoot</span></pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Cost</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> cost; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> Damage</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> damage; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">float</span> Radius</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> radius; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br /></div><div>All these fields are self explanatory. Next we will add in a simple constructor for our class :</div><br /><span class="Apple-style-span" style="font-family: 'Courier New', courier, monospace; font-size: 11px; line-height: 16px; white-space: pre; "><span style="color: #0000ff">public</span> Tower(Texture2D texture, Vector2 position)</span><div id="codeSnippetWrapper"><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> : <span style="color: #0000ff">base</span>(texture, position)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div></div><br /><div>Notice how we don’t set any values for the tower’s fields, this is because each different tower type will have different costs and ranges and damages etc, so it will be easier if each type of tower sets it’s own values, as you will see later on in the tutorials.</div><p>And that’s the basics done, go back into Game1.cs and add the following field :</p><div id="codeSnippetWrapper"><div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Tower tower;<span class="Apple-style-span" style="font-family: Georgia, serif; line-height: normal; white-space: normal; font-size: 16px; "> </span></pre></div></div><br /><div>Before we can initialize the new tower we first need to add the following texture to the content project :</div><br /><div><a href="http://lh5.ggpht.com/_q2VraDVN7Lg/TJ9aSptn0CI/AAAAAAAAACQ/vW2Z1BwfOMM/s1600-h/arrowtower4.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="arrow tower" border="0" alt="arrow tower" src="http://lh4.ggpht.com/_q2VraDVN7Lg/TJ9aTn0q3GI/AAAAAAAAACU/JSeXWRjcVCw/arrowtower_thumb2.png?imgmax=800" width="32" height="32" /></a></div><div><br /></div><div>With that added we can move onto initializing and drawing our tower. In the LoadContent method add the following :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">Texture2D towerTexture = Content.Load<Texture2D>(<span style="color: #006080">"arrow tower"</span>);</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">tower = <span style="color: #0000ff">new</span> Tower(towerTexture, Vector2.Zero);</pre><br /><!--CRLF--></div><br />All this code does is create a shiny new tower in the top left corner of our screen, using the texture we just added.<br /><br /></div><div id="codeSnippetWrapper">Now all that’s left is to draw it, so in the draw method just after where we draw our enemy, add the following :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">tower.Draw(spriteBatch);</pre><br /><!--CRLF--></div></div></div><p>Now if you run the project you should see something like this :</p><p><a href="http://lh4.ggpht.com/_q2VraDVN7Lg/TJ9aUB5EmoI/AAAAAAAAACY/-bRdIRNhTco/s1600-h/image3.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_q2VraDVN7Lg/TJ9aU07bWOI/AAAAAAAAACc/1apqA5YfYZE/image_thumb1.png?imgmax=800" width="244" height="244" /></a> </p><p>Now we have our tower drawn, we can move on to something slightly more interesting, making the tower aim,</p><p>To start with we are going to give our a bigger range just for testing purposes, so go into Tower.cs and in the constructor add the following :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">radius = 1000;</pre><br /><!--CRLF--></div><br /></div><div>Next we will add in a simple helper method to check whether an enemy is in range of the tower :</div><div><br /></div><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">bool</span> IsInRange(Vector2 position)</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (Vector2.Distance(center, position) <= radius)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span>;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> <span style="color: #0000ff">false</span>;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div><br /></div><div>Here we simple check whether the distance from the centre of the tower to the inputted position is within range. With that added we can move onto writing a method that will return the closest enemy to the tower, this will be how we choose what to shoot!</div><br />Before we add that we need one more field and property to store the enemy we are targeting. Add this to the top of Tower.cs :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> Enemy target;</pre><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> Enemy Target</pre><!--CRLF--><pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> target; }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br /></div><div>Now that's sorted, add the following method to the Tower class :</div><div><br /></div><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> GetClosestEnemy(List<Enemy> enemies)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> target = <span style="color: #0000ff">null</span>;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">float</span> smallestRange = radius;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">foreach</span> (Enemy enemy <span style="color: #0000ff">in</span> enemies)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (Vector2.Distance(center, enemy.Center) < smallestRange)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> {</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> smallestRange = Vector2.Distance(center, enemy.Center);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> target = enemy;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> }</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--></div><br /></div><div>This is where the magic happens, and it’s quite simple really, we loop through every enemy that is currently alive in the level, and if that enemy is closer than the previously found closest enemy, then the enemy is set to be the target.</div><br />Right, onto the aiming method, what we do here is find the direction from the tower to the target, and find out what that direction is by using some trigonometry.<br /><br /><em>For more information about finding an angle from a direction check out <a href="http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2D/Direction_to_Angle.php" target="_blank">Riemers Tutorial.</a></em><br /><br />Without for ado, here is the method :<br /><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">protected</span> <span style="color: #0000ff">void</span> FaceTarget()</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> Vector2 direction = center - target.Center;</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> direction.Normalize();</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> rotation = (<span style="color: #0000ff">float</span>)Math.Atan2(-direction.X, direction.Y);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div><br /></div><div>To call this method we simply override the Sprites Update method, and if we have a target, call FaceTarget() :</div><br /><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Update(GameTime gameTime)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.Update(gameTime);</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"></span></span><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span> (target != <span style="color: #0000ff">null</span>)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> FaceTarget();</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><br /><!--CRLF--></div></div><p>And that’s our tower class finished for now! Go back to Game1.cs and in the Update method, just after we Update the enemy, add the following :</p><div id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><br /> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #0000ff">if</span> (tower.Target == <span style="color: #0000ff">null</span>)</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">{</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> List<Enemy> enemies = <span style="color: #0000ff">new</span> List<Enemy>();</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> enemies.Add(enemy1);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> </pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"> tower.GetClosestEnemy(enemies);</pre> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">}</pre><!--CRLF--><span class="Apple-style-span" style="white-space: pre;"><span class="Apple-style-span" style="white-space: normal;"><br /></span></span> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">tower.Update(gameTime);</pre><br /><!--CRLF--></div><br />Here, we just check if the tower has a target, and if it doesn’t we give it one using the method we added earlier.<br /><br />And that’s it for now, if you run the project you should see your black dot following the path, with our shiny new tower following his every move!<br /><br /><a href="http://www.mediafire.com/file/0h7zp216r2odgep/TowerDefenseTutorial_5.zip" target="_blank">Here is the source code for this tutorial.</a><br /><br /></div>FireFlyhttp://www.blogger.com/profile/08398015936723710602noreply@blogger.com18