<?xml version="1.0" encoding="ISO-8859-1" ?>
<rss version="2.0">
<channel>
  <title>RightAngleGames</title>
  <link>http://www.haaks.net</link>
  <description>Contains information about Thomas Haaks.&#60;br&#62;Deals with game programming in general and PlayBasic, BlitzMax and Java/LWJGL/Slick specifically.&#60;br&#62;Offers downloads of my games and a blog.</description>
  <generator>Lauyan TOWeb</generator>
  <language>en</language>
  <pubDate>Tue, 8 Jun 2010 19:57:01 GMT</pubDate>
<item>
  <title>[Game Dev] First screenshot of shape editor for &#34;They Come&#34;</title>
  <description>&#60;i&#62; Tuesday, June 08, 2010, 9:36 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Since several weeks I&#39;m working on a shape editor for my procedurally generated images for &#34;They Come&#34;. As I already mentioned a few times most of the graphics in the game will be randomly generated based on shapes.&#60;br&#62;&#60;br&#62;The editor will help me to graphically design those shapes instead of manually typing strange characters into a definition file.&#60;br&#62;&#60;br&#62;A first version is nearly done. I can already load a definition file, &#34;paint&#34; a shape on a grid, modify colors, watch some random images in the preview window and save everything back into a definition file.&#60;br&#62;&#60;br&#62;There is still some stuff missing like working on the categories, naming shapes, duplicating or creating them. Saving an image or texture with a bunch of generated images would also be a nice feature. But that&#39;s all minor stuff and easy to be added. Looking at my spare time it will still take some time to get this into some releasable alpha version but hey - it&#39;s my personal &#34;have fun coding time&#34; &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Feedback, suggestions or criticism is already appreciated. Do you think this could be sold for some Euros? Or isn&#39;t it even worth the efforts? I doubt a Paypal &#34;Donate&#34; button would have any effect...&#60;br&#62;...but earning some money by coding games or game dev tools would feel pretty good &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Cheers,&#60;br&#62;Tommy</description>
  <link>http://www.haaks.net/blog/index.html#201011</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201011</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] Minor fixes in more than 10 seconds</title>
  <description>&#60;i&#62; Sunday, May 02, 2010, 2:48 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;I uploaded a new version of &#34;How long are 10 seconds?&#34; to my site. It contains some small fixes and improvements. You can find all information in the readme.txt contained in the zip file.&#60;br&#62;Mainly code cleanups and simplification - amazing what you can automate with the mbmFramework!&#60;br&#62;&#60;br&#62;For example the animated main menu screen (rotating and scaling the game title) is all done by the configuration file settings and the general framework code - not a single line of code in my mainmenu.bmx file is required to do this!&#60;br&#62;&#60;br&#62;Additionally I tweaked the website layout a bit. And because of a bug in &#60;a href=&#34;../toweb/index.html&#34;&#62;TOWeb&#60;/a&#62; (by duplicating topics with comments) I lost Matt&#39;s comment for &#60;a href=&#34;../10seconds/index.html&#34;&#62;10 seconds&#60;/a&#62;. Sorry Matt &#60;img src=&#34;../_frame/icon_sad.gif&#34; border=&#34;0&#34;&#62; Maybe you just add it again or another one.</description>
  <link>http://www.haaks.net/blog/index.html#201010</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201010</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] 10 seconds are over!</title>
  <description>&#60;i&#62; Monday, April 26, 2010, 9:47 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Or better - the game is done! It&#39;s named &#34;&#60;b&#62;How long are 10 seconds?&#60;/b&#62;&#34; and is a little game of dexterity. Mainly it was a learning exercise for me to get used to the &#60;a target=&#34;_blank&#34; href=&#34;http://www.matibee.co.uk/wpsite/?page_id=9&#34;&#62;mbmFramework&#60;/a&#62; for BlitzMax. Additionally I got some beginner experience for my new graphics tool &#60;a target=&#34;_blank&#34; href=&#34;http://www.mediachance.com/realdraw/index.html&#34;&#62;Real-DRAW Pro 5&#60;/a&#62;.&#60;br&#62;&#60;br&#62;Just download it using the quick link on the right or jump to it&#39;s game page &#60;a href=&#34;../10seconds/index.html&#34;&#62;10 seconds&#60;/a&#62;.&#60;br&#62;&#60;br&#62;I hope you like the game! Any feedback using the comments is highly appreciated.&#60;br&#62;&#60;br&#62;I&#39;m thinking about extending it a bit more using the TimelineFX particle engine to get some nice particle effects.&#60;br&#62;&#60;br&#62;But for now it&#39;s back to &#60;a href=&#34;../theycome/index.html&#34;&#62;They Come&#60;/a&#62;!</description>
  <link>http://www.haaks.net/blog/index.html#201009</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201009</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] Slooooow times.....</title>
  <description>&#60;i&#62; Saturday, April 17, 2010, 3:43 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;A whole month passed and it feels like nothing happened! Although I played around with mbmFramework, some graphics tool (Real-Draw Pro), looked at Fruity Loops (FLStudio) and wasted time reading stuff here and there I didn&#39;t really progress with &#60;a href=&#34;../theycome/index.html&#34;&#62;They Come&#60;/a&#62;.&#60;br&#62;&#60;br&#62;I started a little mini game which will be finished real soon (tm) to learn more about the mbmFramework. The game itself is already done, right now I&#39;m fiddling around with creating graphics, adjusting menus and info screens and so on. But I hope to finish it this month!&#60;br&#62;&#60;br&#62;That&#39;s pretty much it except my pretty busy real life. I hope to show my mini game at the next web site update and then continue with &#60;a href=&#34;../theycome/index.html&#34;&#62;They Come&#60;/a&#62;.&#60;br&#62;&#60;br&#62;Later,&#60;br&#62;Tommy</description>
  <link>http://www.haaks.net/blog/index.html#201008</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201008</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Website, Game Dev] Logo is done, game continues</title>
  <description>&#60;i&#62; Sunday, March 14, 2010, 5:41 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;So the logo design is finished and I&#39;m very pleased with it! You can see a small version of it on the right.&#60;br&#62;&#60;br&#62;I will use this logo more and more for my games and for this website. As already mentioned I plan to rework the site a bit. Let&#39;s see how long that takes and when it will be finished &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;The logo design itself was done by Susan from Logolane. You can see their ebay offers here: &#60;a target=&#34;_blank&#34; href=&#34;http://shop.ebay.com/logolane/m.html?_nkw=&#38;_armrs=1&#38;_from=&#38;_ipg=25&#34;&#62;http://shop.ebay.com/logolane/m.html?_nkw=&#38;_armrs=1&#38;_from=&#38;_ipg=25&#60;/a&#62;.&#60;br&#62;I can highly recommend their services to everyone who needs a logo for whatsoever purpose.&#60;br&#62;&#60;br&#62;On the game development side I managed to port the space nebula generation from the &#60;a href=&#34;../sourcecode/index.html&#34;&#62;Source code&#60;/a&#62; pages from PlayBasic to BlitzMax. That was pretty easy and works like a charm. And it&#39;s much faster in BlitzMax compared to PlayBasic which is already a fast interpreted language.&#60;br&#62;&#60;br&#62;Additionally I started to code a small tool to draw the templates for my shape generator. That will take a while before it&#39;s done but should help me to speed up in designing the content for &#60;a href=&#34;../theycome/index.html&#34;&#62;They come&#60;/a&#62;. I even thought about offering it as a separate tool to generate random images based on the designed and stored shape templates...</description>
  <link>http://www.haaks.net/blog/index.html#201007</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201007</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Website]Logo time!</title>
  <description>&#60;i&#62; Sunday, February 28, 2010, 6:02 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;No, I&#39;m not talking about this old programming language from the past featuring a triangle turtle &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;Instead I decided to get a new logo design for my web site.&#60;br&#62;Over the next months I plan to transform this web site a bit. First it will feature the new logo and the starting page will be remade and feature the games I created and will create in the future.&#60;br&#62;This blog will not disappear but it won&#39;t stay as the starting page - you will have to jump to it using the menu or you will have to add a direct link to it in your browser.&#60;br&#62;&#60;br&#62;The most adventurous thing for me is that I decided to &#60;b&#62;pay money&#60;/b&#62; for a logo design! In the next few days I will receive the first drafts for the new logo and decide which one will be chosen for final iterations. I&#39;m so excited &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Expect to see it here in the near future!&#60;br&#62;</description>
  <link>http://www.haaks.net/blog/index.html#201006</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201006</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] mbmFramework</title>
  <description>&#60;i&#62; Sunday, February 28, 2010, 5:50 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Recently I had a look at matibee&#39;s framework &#60;a target=&#34;_blank&#34; href=&#34;http://www.matibee.co.uk/wpsite/?page_id=9&#34;&#62;mbmFramework&#60;/a&#62; for BlitzMax.&#60;br&#62;It&#39;s a great framework that contains tons of stuff you&#39;ll require to give your games the finishing touch.&#60;br&#62;Some of it&#39;s features are:&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; &#60;b&#62;cross platform&#60;/b&#62; for all BlitzMax platforms (Windows, Linux, Mac),&#60;/li&#62;&#60;li&#62; &#60;b&#62;multi lingual&#60;/b&#62; by supporting multiple languages for your games which can easily be applied to your game,&#60;/li&#62;&#60;li&#62; &#60;b&#62;funky animation stuff&#60;/b&#62; to make your game elements or GUI wobble, bounce and sweep by adding simple animator objects,&#60;/li&#62;&#60;li&#62; &#60;b&#62;sprite enhancements&#60;/b&#62; to ease programmer&#39;s life,&#60;/li&#62;&#60;li&#62; &#60;b&#62;GUI controls&#60;/b&#62; for typical game GUIs with buttons, sliders, check boxes and input fields,&#60;/li&#62;&#60;li&#62; &#60;b&#62;Player profiles, settings and highscore management&#60;/b&#62; in prebuilt classes, ready to be used, even encrypted,&#60;/li&#62;&#60;li&#62; &#60;b&#62;automated application flow&#60;/b&#62; resolved with AppModules that you can simply subclass and switch between,&#60;/li&#62;&#60;li&#62; &#60;b&#62;automated loading process&#60;/b&#62; with integrated resource handling,&#60;/li&#62;&#60;li&#62; &#60;b&#62;particle system&#60;/b&#62; that should solve many effect issues with a particle editor for free,&#60;/li&#62;&#60;li&#62; &#60;b&#62;code profiling, screenshots via hotkey, tutorials, samples and documentation&#60;/b&#62; and more that I might have forgotten &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;Best of all: this framework is free to use for non commercial games and you can buy a commercial license with all of the source code included!&#60;br&#62;&#60;br&#62;I am currently porting  &#60;a href=&#34;../theycome/index.html&#34;&#62;They Come&#60;/a&#62; over to this framework because it contains many features that I simply hadn&#39;t implemented yet and that I won&#39;t implement now but instead use this cool framework.&#60;br&#62;&#60;br&#62;Great work, matibee!</description>
  <link>http://www.haaks.net/blog/index.html#201005</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201005</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev]Random ships again!</title>
  <description>&#60;i&#62; Tuesday, February 16, 2010, 9:15 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Woohoo! Finally I found enough time and energy to port my random space ship generation code from Java to BlitzMax. I even got it enhanced because now I can read the shape and color definitions from a flat file instead of using some hard coded arrays...&#60;br&#62;&#60;br&#62;The shape definitions can be named and categorized and I can have different shape definitions for each category. This will allow me to use different human space ship shapes on each game start! So I don&#39;t just have an endless amount of space ships for one shape but for many shapes! Endless multiplied by endless ships - muhahaha!&#60;br&#62;&#60;br&#62;Assigned screen shot proves it. The ships are scaled by factor 4, so in game they are much smaller. If they end up being too small I can increase the size of the shapes (and allow more details) or use the scaling factor as I did for this test screen shot.&#60;br&#62;&#60;br&#62;The used shape definitions will receive some fine tuning to produce nicer ships. Additionally I plan to play around with brightening and darkening the colors to get more than just the 3 defined colors per ship.&#60;br&#62;&#60;br&#62;Next I will add some boids or flocking code to represent the fleet of little human space ships following their leader mother ship...&#60;br&#62;&#60;br&#62;Feel free to give some feedback!</description>
  <link>http://www.haaks.net/blog/index.html#201004</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201004</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] Nothing to see but stuff under the hood</title>
  <description>&#60;i&#62; Tuesday, January 26, 2010, 9:18 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;The last few days were not so busy regarding game development but I worked on stuff here, refactored code there and fixed other things in between.&#60;br&#62;I really reworked the map generation algorithm and can now pretty surely guarantee the generation of a playable map.&#60;br&#62;There is still one game element missing but that&#39;s due to the fact that I completely forgot it in my overall list and just found it in my design notes &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Additionally I&#39;m &#34;wasting&#34; time browsing forums or the internet in general. Currently I&#39;m watching the Assemblee competition over at Tigsource, I&#39;m of course reading most of the stuff on the BlitzMax forums and over at the BlitzMonkeys forum.&#60;br&#62;&#60;br&#62;Anyway, back to coding - I still have a few minutes left for tonight &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;</description>
  <link>http://www.haaks.net/blog/index.html#201003</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201003</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[TOWeb] New bugfix release</title>
  <description>&#60;i&#62; Saturday, January 16, 2010, 6:57 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;In general that&#39;s not this worth mentioning because a new bugfix release of &#60;a target=&#34;_blank&#34; href=&#34;http://www.lauyan.com&#34;&#62;TOWeb&#60;/a&#62; appears nearly once a month with bug fixes and enhancements.&#60;br&#62;&#60;br&#62;But this time I mention it because it&#39;s fixing a problem regarding the generated RSS feeds. I hope you all will get rid of those irritating numbers at the beginning of each topic. We&#39;ll see in a minute after publishing the site &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62; Keep your fingers crossed!</description>
  <link>http://www.haaks.net/blog/index.html#201002</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201002</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Real life] Happy new 2010!</title>
  <description>&#60;i&#62; Friday, January 01, 2010, 1:34 AM &#60;/i&#62;&#60;br&#62;&#60;br&#62;So as usual I&#39;m wishing a happy new year to all of you!&#60;br&#62;It&#39;s 1:30 something in the morning, all rockets are fired into the sky, all explosives are exploded, the fingers are frozen, my wife and my kids are in bed (although I&#39;m not sure about my daughter who is celebrating new year&#39;s eve in Berlin) and I&#39;m finally sitting at my laptop, drinking the last drops of sparkling wine and will have my new year&#39;s single malt in a few minutes &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;The last year wasn&#39;t this great job wise but pretty good considering the rest of it. So I guess the new year can and will get better in certain areas! I hope it does the same for you!&#60;br&#62;&#60;br&#62;I don&#39;t know if you&#39;re up to resolutions - I pretty much laugh about them. I make up my personal resolutions whenever I think they are necessary! I don&#39;t have to wait until new year&#39;s eve or save them until then. Start your personal improvements whenever you are ready to do so!&#60;br&#62;&#60;br&#62;Having said this: A happy new year to all of you, health and fun and a wonderful year!&#60;br&#62;&#60;br&#62;Good night and see you,&#60;br&#62;Tommy&#60;br&#62;</description>
  <link>http://www.haaks.net/blog/index.html#201001</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#201001</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>Quick shortcuts</title>
  <description>&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; &#60;a href=&#34;../topdownshootertu/index.html&#34;&#62;Top down shooter tutorial&#60;/a&#62;, my first BlitzMax tutorial in the making&#60;/li&#62;&#60;li&#62;  &#60;a href=&#34;../spaceinvaders1/index.html&#34;&#62;Space Invaders tutorial part 1&#60;/a&#62;, a nice tutorial for PlayBasic&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;</description>
  <link>http://www.haaks.net/blog/index.html#bv000055</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#bv000055</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>Blog Archives</title>
  <description>&#60;a href=&#34;../blog2009/index.html&#34;&#62;Blog Archive 2009&#60;/a&#62;&#60;br&#62;&#60;a href=&#34;../blog2008/index.html&#34;&#62;Blog Archive 2008&#60;/a&#62;&#60;br&#62;&#60;a href=&#34;../blog2007/index.html&#34;&#62;Blog Archive 2007&#60;/a&#62;&#60;br&#62;&#60;a href=&#34;../blog2006/index.html&#34;&#62;Blog Archive 2006&#60;/a&#62;&#60;br&#62;</description>
  <link>http://www.haaks.net/blog/index.html#bv000001</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#bv000001</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>Search my site!</title>
  <description>Looking for something on my home page I mentioned years ago?&#60;br&#62;Don&#39;t worry - use the builtin search engine &#60;img src=&#34;../_frame/icon_eek.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;%TW-SEARCH% </description>
  <link>http://www.haaks.net/blog/index.html#bv000008</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#bv000008</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>Bookmark this site</title>
  <description>Feel free to bookmark my site in your web browser.&#60;br&#62;&#60;br&#62;%TW-FAVORITE-BTN% </description>
  <link>http://www.haaks.net/blog/index.html#bv000005</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#bv000005</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>Contact me!</title>
  <description>If you want to discuss any topic or content you can contact me.&#60;br&#62;Just click on the icon above to send me an email!</description>
  <link>http://www.haaks.net/blog/index.html#bv000003</link>
  <guid isPermaLink="true">http://www.haaks.net/blog/index.html#bv000003</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>I made 175!</title>
  <description>&#60;i&#62; Thursday, December 31, 2009, 4:18 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Yup, the year is nearly over and I&#39;m enjoying my Christmas holidays so no way to improve my current score of &#60;b&#62;175&#60;/b&#62; rides to work with my bike.&#60;br&#62;I&#39;m very proud on myself if I am allowed to say so &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Unfortunately I&#39;m afraid I won&#39;t break this record next year - our office will be closed end of 2010 and I&#39;m going to have to take a car to the new office or (yikes!) change the employer and look for a job in Hamburg. Then I would ride to the train station on my bike and continue by train. We&#39;ll see.&#60;br&#62;&#60;br&#62;As one of our former CEOs said: &#34;Change is constant. Change is opportunity.&#34;...</description>
  <link>http://www.haaks.net/gettingbetter/index.html#bv000017</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#bv000017</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>New personal bicycle record!</title>
  <description>&#60;i&#62; Monday, October 19, 2009, 8:58 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Today I reached 141. This means I rode to work on my bike 141 days this year. That&#39;s exactly the number of days I used my bike to ride to the office the whole last year! So I have more than two months left to increase my personal &#34;use your bike to get to the office&#34; record!&#60;br&#62;&#60;br&#62;Will I reach 160? Or maybe 175? We&#39;ll see. I&#39;m telling you at the end of this year &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;</description>
  <link>http://www.haaks.net/gettingbetter/index.html#bv000016</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#bv000016</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Mind mapping tools?</title>
  <description>&#60;i&#62; Tuesday, July 28, 2009, 10:54 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Can anyone of you recommend a good mind mapping tool?&#60;br&#62;Criteria are:&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; free or low cost,&#60;/li&#62;&#60;li&#62; fast,&#60;/li&#62;&#60;li&#62; can export to some formats like PDF or HTML.&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;I already looked at &#60;a target=&#34;_blank&#34; href=&#34;http://freemind.sourceforge.net/wiki/index.php/Main_Page&#34;&#62;FreeMind&#60;/a&#62; which is pretty cool but sooooo slow on startup. Next - you are dismissed &#60;img src=&#34;../_frame/icon_doubt.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Can you recommend a web based mind mapping tool? I&#39;ve read that there are some popping up here and there but I&#39;m afraid they&#39;ll turn into payable ones sooner or later or they force you to give them the right to use your private maps (or their content)! Not very polite - sounds like a business model &#60;img src=&#34;../_frame/icon_sad.gif&#34; border=&#34;0&#34;&#62;</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better15</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better15</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Your personal finance</title>
  <description>&#60;i&#62; Sunday, May 17, 2009, 10:40 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Here is the link to a free document which tells you &#34;Everything You Ever Really Needed to Know About Personal Finance On Just One Page&#34;.&#60;br&#62;&#60;br&#62;The document itself is free but the author asks for a donation.&#60;br&#62;&#60;br&#62;&#60;a target=&#34;_blank&#34; href=&#34;http://www.thesimpledollar.com/onepage/&#34;&#62;http://www.thesimpledollar.com/onepage/&#60;/a&#62;</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better14</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better14</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>A notebook with exchangeable content?</title>
  <description>&#60;i&#62; Sunday, May 17, 2009, 10:33 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Do you use a notebook like a Moleskine or a ring folder to jot down your notes?&#60;br&#62;I own two notebooks similar to a Moleskine, one for game ideas and notes and the other one for personal stuff.&#60;br&#62;&#60;br&#62;In the past I used to have a ring folder but those have some disadvantages:&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; they are thick,&#60;/li&#62;&#60;li&#62; you can&#39;t write on the left side because of the metal rings that keep your sheets of paper,&#60;/li&#62;&#60;li&#62; the pages always move a little bit.&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;Recently I read on &#60;a target=&#34;_blank&#34; href=&#34;http://www.imgriff.com&#34;&#62;http://www.imgriff.com&#60;/a&#62; about the advantages of a real Moleskine. But the smartest thing was mentioned in one of the comments to this specific blog post.&#60;br&#62;&#60;br&#62;&#60;a target=&#34;_blank&#34; href=&#34;http://www.myx17.com&#34;&#62;http://www.myx17.com&#60;/a&#62; is a site where you can buy a note book that allows you to use different fill-ins and that does not have metal rings inside.&#60;br&#62;Just jump to the site and have a look - the idea is just great!&#60;br&#62;&#60;br&#62;A friend of mine is going to buy one and I&#39;ll have a detailed look at it - but I&#39;m already pretty sure I&#39;m going to buy me one anyway &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better13</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better13</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Getting to work by bike</title>
  <description>&#60;i&#62; Tuesday, March 10, 2009, 9:00 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Just wanted to tell you that in 2008 I took the bike on 141 days to drive into the office! So more than 2/3 of my working days last year I used my bicycle!&#60;br&#62;&#60;br&#62;Makes me a bit proud as I am just a couch potato &#60;img src=&#34;../_frame/icon_smile.gif&#34; border=&#34;0&#34;&#62;</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better12</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better12</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Basics</title>
  <description>&#60;i&#62; Last update Tuesday, March 10, 2009, 9:00 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;On &#60;a target=&#34;_blank&#34; href=&#34;http://www.imgriff.com&#34;&#62;www.imgriff.com&#60;/a&#62; there is a series about basics: &#60;a target=&#34;_blank&#34; href=&#34;http://imgriff.com/serien/das-kleine-einmaleins/&#34;&#62;http://imgriff.com/serien/das-kleine-einmaleins/&#60;/a&#62; (in german).&#60;br&#62;&#60;br&#62;I will summarize them here in english in short paragraphs for you and me in the following weeks.</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better11</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better11</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Everything gets a timestamp</title>
  <description>Every note that you make (on a piece of paper, in your moleskine, in your software tool, PIM, mobile phone) gets a timestamp.&#60;br&#62;Many times you won&#39;t need it but in those rare cases you will be lucky that you wrote it down.&#60;br&#62;So just get used to it.</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better10</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better10</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>The famous 2 minute rule</title>
  <description>Whatever is on your todo list or needs to be done and takes only two minutes: do it &#60;b&#62;now&#60;/b&#62;!&#60;br&#62;Watering your flowers, answering an email (a short answer!) - do it immediately. Don&#39;t waste time to put it on a todo list or schedule it. Just get it done immediately and forget it.&#60;br&#62;&#60;br&#62;That also implies that you should take your time for all things that take longer. Plan them, find time slots when you can do those tasks without being disturbed or distracted. This helps you to stay focused.</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better09</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better09</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Do similar jobs together</title>
  <description>Do phone call after phone call, email reply after email reply. Simply try to batch process tasks that are nearly identical.&#60;br&#62;That should help you to stay more focused and get faster on each single task.</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better08</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better08</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Quiet, please!</title>
  <description>Switch off all disturbing noises that you can control (don&#39;t try to stop the caterpillar in front of your house, except when your name&#39;s Arthur Dent!).&#60;br&#62;Whenever you need all your concentration switch off your mobile phone and normal phone, your &#34;you have mail&#34; tone, your bell at the front door and other disturbing noises.&#60;br&#62;If it doesn&#39;t disturb you let the music play - at least you can control the kind of music and the volume.</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better07</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better07</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Singletasking</title>
  <description>Negotiating a contract with your mobile phone in your left hand, doing online banking with your right hand, use eye contact with an office mate to agree on a meeting date - that&#39;s busy. But is it productive?&#60;br&#62;&#60;br&#62;If you&#39;re trying to get a job done that needs all of your concentration - then do only this one job.&#60;br&#62;&#60;br&#62;Multitasking at work is a myth. Of course you can put a chewing gum into your mouth while reading emails but trying to work on two jobs that both require your full concentration? Come on. That will never work.&#60;br&#62;&#60;br&#62;Oh, and while we&#39;re at it: to get a difficult single task done well, read the paragraph above this one once more.</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better06</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better06</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Salami tactics</title>
  <description>&#34;How do you eat an elephant?&#34;&#60;br&#62;&#34;Piece by piece.&#34;&#60;br&#62;&#60;br&#62;If there is a huge overwhelming project ahead of you how can you deal with it? Right, piece by piece (or to stay with our salami, slice by slice).&#60;br&#62;Try to separate the project into many reasonable and precise steps or tasks and finish them one after the other.&#60;br&#62;This approach comes with several advantages: you&#39;ll constantly progress and you&#39;ll get faster results.&#60;br&#62;&#60;br&#62;The huge impregnable project shrunk into a pile of smaller tasks you can cope with.</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better05</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better05</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Check your mailbox(es) only three times a day</title>
  <description>I&#39;ll bet no one will notice a difference if you check your email inboxes and RSS feeds only three times a day.&#60;br&#62;Be honest: Are mails this important that you need to answer them immediately. The advantage of emails is that they are asynchronous! No one should expect that they are answered immediately.&#60;br&#62;&#60;br&#62;Of course it&#39;s a personal preference if you check your mailbox 2, 3 or 5 times a day. But try to close your webmailer, email client and RSS feed in those periods in between.&#60;br&#62;It will help you to stay more focused on your real work!</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better04</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better04</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>To be continued</title>
  <description>More to come in the next time.</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better03</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better03</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Pushups</title>
  <description>&#60;i&#62; Monday, September 08, 2008, 11:42 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Three months ago I discovered the site &#60;a target=&#34;_blank&#34; href=&#34;http://hundredpushups.com/&#34;&#62;http://hundredpushups.com/&#60;/a&#62;. There is this guy who promises that you (or me) can do 100 push ups in one go after six weeks. Muhahahahaha.&#60;br&#62;&#60;br&#62;To be perfectly honest: I am a couch potato. I did sports (skateboarding, badminton, table tennis) until I was around 20. But then university and job and all the pubs in Berlin and girl friends and such did their job: I became a lazy chair guy.&#60;br&#62;&#60;br&#62;Three years ago I started to ride to work by bike (bicycle). Unfortunately not every day (yet). But I&#39;m getting better. This year I will improve my bicycle work days and reach at least around 120 (currently I&#39;m at 90) days out of 220 working days.&#60;br&#62;&#60;br&#62;But I&#39;m drifting away &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Beginning of August I read the &#60;a target=&#34;_blank&#34; href=&#34;http://www.ludumdare.com&#34;&#62;ludum dare&#60;/a&#62; blog. It&#39;s about a 48 hour game coding contest that takes place two or three times a year. And one guy mentioned the &#60;a target=&#34;_blank&#34; href=&#34;http://hundredpushups.com/&#34;&#62;http://hundredpushups.com/&#60;/a&#62; site again. I got hooked. So I printed out the complete program and took it with me into my vacation.&#60;br&#62;&#60;br&#62;And I started. In my initial test I managed 12 push ups. Stop laughing, down to the ground and do it better!&#60;br&#62;After two weeks (you train 3 days a week and rest in between) there is another maximum test. This time I managed 30 push ups. Now I finished my third week and I&#39;m doing around 70 push ups in one training session (takes around 10 minutes). &#60;br&#62;&#60;br&#62;I doubt that I will manage 100 push ups after six week but I&#39;m pretty sure it will be more than 50.&#60;br&#62;&#60;br&#62;But I will continue the training until I can do 100 push ups. You&#39;ll see when I add the badge on my website &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Positive points are:&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; I don&#39;t need to go to a gym&#60;/li&#62;&#60;li&#62; I only train three days a week&#60;/li&#62;&#60;li&#62; Each training session takes max. 10 minutes&#60;/li&#62;&#60;li&#62; I do improve&#60;/li&#62;&#60;li&#62; I feel good &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;/li&#62;&#60;li&#62; It&#39;s fun&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;Will you give it a try?</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better02</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better02</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Getting things done and Zen to done</title>
  <description>&#60;i&#62; Monday, September 08, 2008, 11:29 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Yup - it&#39;s the famous stuff by David Allen (Link here &#60;a target=&#34;_blank&#34; href=&#34;http://www.davidco.com/&#34;&#62;http://www.davidco.com/&#60;/a&#62;).&#60;br&#62;It&#39;s pretty much all about getting organized in your life and keeping track of lists, organizing those lists and so on.&#60;br&#62;&#60;br&#62;To be honest: It&#39;s way too complicated for me to live it.&#60;br&#62;&#60;br&#62;But at my favorite &#34;Getting better&#34; website (&#60;a target=&#34;_blank&#34; href=&#34;http://www.imgriff.com&#34;&#62;www.imgriff.com&#60;/a&#62;, a german blog) I found a much simpler version: &#60;b&#62;Zen to done&#60;/b&#62;.&#60;br&#62;Here is a link to the german article of &#60;a target=&#34;_blank&#34; href=&#34;http://www.imgriff.com&#34;&#62;www.imgriff.com&#60;/a&#62;: &#60;a target=&#34;_blank&#34; href=&#34;http://imgriff.com/2008/01/09/zen-to-done-teil-1-das-ultimativ-einfache-produktivitaetssystem/&#34;&#62;http://imgriff.com/2008/01/09/zen-to-done-teil-1-das-ultimativ-einfache-produktivitaetssystem/&#60;/a&#62;&#60;br&#62;&#60;br&#62;The german link also offers a downloadable ebook version - very nice &#60;img src=&#34;../_frame/icon_smile.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;For all you english readers: the original version can be found here: &#60;a target=&#34;_blank&#34; href=&#34;http://zenhabits.net/2007/04/zen-to-done-ztd-the-ultimate-simple-productivity-system/&#34;&#62;http://zenhabits.net/2007/04/zen-to-done-ztd-the-ultimate-simple-productivity-system/&#60;/a&#62;&#60;br&#62;&#60;br&#62;Of course you don&#39;t have to follow all those guide lines. At least I don&#39;t and won&#39;t. But it&#39;s a motivating read and I think even adopting one or two habits is already an improvement. And that&#39;s what it&#39;s all about, right?</description>
  <link>http://www.haaks.net/gettingbetter/index.html#better01</link>
  <guid isPermaLink="true">http://www.haaks.net/gettingbetter/index.html#better01</guid>
  <category>Getting better - tips and links to improve one&#39;s life</category>
</item>
<item>
  <title>Coding conventions and short introduction</title>
  <description>Okay, so you want to code a game with BlitzMax?&#60;br&#62;Great choice!&#60;br&#62;&#60;br&#62;BlitzMax is a &#60;b&#62;BASIC&#60;/b&#62; like language offering object oriented (OO) extensions. Those will help you organize and simplify your code a lot compared to the &#34;old&#34; procedural versions of BlitzBasic (and other Basics).&#60;br&#62;BlitzMax offers &#60;b&#62;Types&#60;/b&#62; which is the BlitzMax name of a &#60;b&#62;class&#60;/b&#62; in other OO languages like Java or C++. It might happen during this tutorial that I mix the usage of &#60;b&#62;type&#60;/b&#62; and &#60;b&#62;class&#60;/b&#62; as they are identical and &#60;b&#62;class&#60;/b&#62; is the more often used phrase to me &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;What is a &#60;b&#62;Type&#60;/b&#62; now? It&#39;s nothing more but a template for new objects. Every object you create with that type has all the fields as the type describes.&#60;br&#62;A &#60;b&#62;Type&#60;/b&#62; in BlitzMax can also have methods which can be called for each object of that type. There are some more features of types which I&#39;ll explain later on in the tutorial.&#60;br&#62;&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; A good way to structure your code is to use a separate file in your project for each new type.&#60;/li&#62;&#60;li&#62; As already mentioned in my &#60;a href=&#34;../spaceinvaders1/index.html&#34;&#62;Space Invaders tutorial part 1&#60;/a&#62; you should write constants in capital letters.&#60;/li&#62;&#60;li&#62; Keep your naming conventions for types, methods, variables consistent. Use underlines like &#60;b&#62;my_age&#60;/b&#62; or &#60;b&#62;the_var&#60;/b&#62; or avoid them and use upper/lower case notation like &#60;b&#62;myAge&#60;/b&#62; or &#60;b&#62;theVar&#60;/b&#62;. I prefer the upper/lower case notation.&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;Oh, and before I forget: Your first command in &#60;b&#62;any&#60;/b&#62; BlitzMax game you code should be&#60;br&#62;%CODE_BEGIN% &#60;br&#62;SuperStrict&#60;br&#62;%CODE_END% &#60;br&#62;&#60;b&#62;SuperStrict&#60;/b&#62; forces you to declare all variables in your game with their type and also declare the return type of all methods and functions in your game.&#60;br&#62;Simply said it helps you to get more readable code &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Enough intro, we&#39;ll do the rest while we work through the code.&#60;br&#62;&#60;br&#62;It doesn&#39;t matter if you use the standard BlitzMax IDE or the community edition of the BlitzMax IDE or if you use &#60;a target=&#34;_blank&#34; href=&#34;http://www.blide.org/&#34;&#62;BLIde Plus&#60;/a&#62; like I do. But I will not explain how to create a project or create a new file as it&#39;s all pretty self explaining. If you don&#39;t manage to figure that out on your own you shouldn&#39;t yet consider coding your own games &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds116</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds116</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>Simple game design</title>
  <description>The idea is to create a simple version of a top down shooter which we extend later on.&#60;br&#62;So we use a simple single screen game without any scrolling maps or tiled background or such things.&#60;br&#62;The player controls a turret or a base in the center of the screen. The turret rotates following the mouse pointer and clicking the left mouse button will fire a bullet in the turret&#39;s direction.&#60;br&#62;Enemies will return in random intervals from the screen boundaries and move directly towards the player&#39;s turret. They do not fire and might require several hits before they die or explode.&#60;br&#62;As soon as an enemy touches the turret the game ends.&#60;br&#62;The enemies attack in phases. After all enemies of a phase have been destroyed the next phase starts with more enemies, harder enemies, faster enemies and so on.&#60;br&#62;&#60;br&#62;Later on we will extend the game and replace the turret with a moving player sprite, add keyboard control for movement, better room graphics, add several rooms, different weapons and what else I can come up with while coding this tutorial &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Very important: we need a nice name for the game of course! I chose &#60;b&#62;ComeGetMe&#60;/b&#62;!</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds115</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds115</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>Some thoughts about the main game loop</title>
  <description>Each game you code has some basic main loop looking like this (in pseudo language)&#60;br&#62;%CODE_BEGIN% &#60;br&#62;do&#60;br&#62;    clear screen&#60;br&#62;    update all game objects and handle game logic&#60;br&#62;    render all remaining game objects&#60;br&#62;while (forever)&#60;br&#62;%CODE_END% &#60;br&#62;Unfortunately game developer&#39;s life isn&#39;t that easy. Because different computers have different speeds (older ones are generally slower than the newest high end quad core machines) this main loop would run at different speeds too.&#60;br&#62;Your game would become unplayable on faster machines. Too bad.&#60;br&#62;&#60;br&#62;There are several approaches to solve this problem. One is called &#60;b&#62;delta timing&#60;/b&#62;. A game loop using delta timing would look similar to this one:&#60;br&#62;%CODE_BEGIN% &#60;br&#62;last_time = currentTimeInMilliSeconds()&#60;br&#62;do&#60;br&#62;    now = currentTimeInMilliSeconds()&#60;br&#62;    delta = now - last_time&#60;br&#62;    clear screen&#60;br&#62;    update all game objects and handle game logic and use delta for all calculations&#60;br&#62;    render all remaining game objects&#60;br&#62;while (forever)&#60;br&#62;%CODE_END% &#60;br&#62;You have to use the delta, which is the time that passed since the last update and rendering, for all your speed and position change calculations in the update functions of your game objects.&#60;br&#62;For example you would calculate a new position of your space ship like this:&#60;br&#62;%CODE_BEGIN%&#60;br&#62;newpos = oldpos + (speed * delta)&#60;br&#62;%CODE_END% &#60;br&#62;On a fast machine the delta will be very small and so will be the product (speed * delta). So on a fast computer your ship will move in small steps but often because your main loop is executing really quick.&#60;br&#62;On a slow machine the delta will be comparably bigger and the same for the product (speed * delta). Your ship will move in bigger steps but not as often because the main loop takes a longer time to process.&#60;br&#62;But on both machines you&#39;ll get the same distance over the same amount of time!&#60;br&#62;So this is a great working method!&#60;br&#62;&#60;br&#62;But it has two disadvantages: you update a lot on fast machines with only minimal impact on game objects (because the machines are sooo fast) and physics engines don&#39;t like it &#60;img src=&#34;../_frame/icon_sad.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;Physics engines most of the times expect to be called at certain identical time intervals, say every 20 milliseconds. This way you&#39;ll avoid too many too complicated calculations and nearly no game player would realize a difference if the physics engines were called faster.&#60;br&#62;&#60;br&#62;So people came up with another method of game loop: &#60;b&#62;fixed rate logic plus tweening&#60;/b&#62;.&#60;br&#62;What you do here is calling the update methods with a given fixed rate all the time, for example every 20 milliseconds. Of course it could happen that your game logic needs more time or the Garbage collector interrupts a bit or your game is synchronizing with the vertical monitor sync signal to avoid flickering and you don&#39;t exactly match the 20 milliseconds. So the next call to your update would be a few milliseconds too late. You would still call the update for all pending amounts of 20 milliseconds and the remainder (the tweening value) would be passed as input to all drawing methods. The drawing methods would then interpolate between last position and current position of all moving game objects and the distance travelled is dependent on the tweening value.&#60;br&#62;&#60;br&#62;So instead of having a different value each call in the update routine as in the delta timing approach we now have a different value in the drawing routines.&#60;br&#62;Visually the output is pretty much identical but the advantage of the fixed rate logic approach is indeed what the name says: your game logic is called with fixed intervals all the time.&#60;br&#62;A pseudo code game loop using fixed rate logic would look like this:&#60;br&#62;%CODE_BEGIN% &#60;br&#62;last_time = currentTimeInMilliSeconds()&#60;br&#62;do&#60;br&#62;    now = currentTimeInMilliSeconds()&#60;br&#62;    delta = now - last_time&#60;br&#62;    accumulator = accumulator + delta&#60;br&#62;    clear screen&#60;br&#62;    while accumulator &#62; fixed rate&#60;br&#62;        update all game objects and handle game logic and use fixed rate for all calculations&#60;br&#62;        accumulator = accumulator - fixed rate&#60;br&#62;    endwhile&#60;br&#62;    tween = accumulator / fixed rate&#60;br&#62;    render all remaining game objects and use the tween value for interpolation where current drawing pos = newpos * tween + oldpos * ( 1.0 - tween)&#60;br&#62;while (forever)&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;As the drawing functions do the interpolation all your moving game elements need to have two positions: the last position on screen and the new position on screen. The new position on screen is calculated in the update phase and in the drawing phase your code will have to interpolate between those two positions based on the size of the tween value. Each drawing or rendering phase will move your game elements closer to their new position that was calculated in the update phase. Finally, when the new position is reached time is up for a new update phase and we&#39;ll start all over again.&#60;br&#62;&#60;br&#62;There is a nice long thread in the BlitzMax forum &#60;a target=&#34;_blank&#34; href=&#34;http://www.blitzbasic.com/Community/posts.php?topic=83511&#34;&#62;here&#60;/a&#62; and a really good explanation of fixed rate logic in games can be found on &#60;a target=&#34;_blank&#34; href=&#34;http://gafferongames.com/game-physics/fix-your-timestep/&#34;&#62;Gaffer&#39;s Blog&#60;/a&#62;.&#60;br&#62;&#60;br&#62;For this tutorial we will use the &#60;b&#62;fixed rate logic plus tweening&#60;/b&#62; approach - mainly just because I want to give it a try &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds114</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds114</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>First approach to main loop</title>
  <description>So let&#39;s have some code now, shall we?&#60;br&#62;&#60;br&#62;I want to mention that some of the code is adopted and modified or simplified from Chroma&#39;s public domain BlitzMax framework which you can find on Google code pages &#60;a target=&#34;_blank&#34; href=&#34;http://code.google.com/p/bmax2dframework/&#34;&#62;here&#60;/a&#62;. It seems to be no longer maintained but it gave me a good starting point.&#60;br&#62;&#60;br&#62;Ok, create an empty directory for your project on your hard disk and fire up your preferred BlitzMax IDE.&#60;br&#62;&#60;br&#62;First we&#39;ll start with the main loop code base. You can just copy and paste it into a file named &#60;b&#62;ComeGetMe.bmx&#60;/b&#62;.&#60;br&#62;%CODE_BEGIN% &#60;br&#62;SuperStrict&#60;br&#62;&#60;br&#62;Import &#34;TFRLTimer.bmx&#34;&#60;br&#62;&#60;br&#62;Const GFX_WIDTH:Int = 640, GFX_HEIGHT:Int = 480&#60;br&#62;&#60;br&#62;Const UPDATE_FREQUENCY:Float = 100.0, SPIKE_SUPPRESSION:Int = 20&#60;br&#62;&#60;br&#62;Graphics GFX_WIDTH, GFX_HEIGHT, 0&#60;br&#62;&#60;br&#62;SetBlend ALPHABLEND&#60;br&#62;&#60;br&#62;Local gameTime:TFRLTimer = New TFRLTimer.CreateFRL(UPDATE_FREQUENCY, SPIKE_SUPPRESSION)     &#39;1st number is logic updates per second and 2nd number is how much spike suppression you want&#60;br&#62;&#60;br&#62;&#60;br&#62;&#39; the main loop starts here&#60;br&#62;While Not KeyDown(KEY_ESCAPE) And AppTerminate() = False&#60;br&#62;    Cls&#60;br&#62;    &#60;br&#62;&#60;br&#62;    &#39; update part of the main loop with constant speed&#60;br&#62;    Local delta:Float = gameTime.GetDelta()&#60;br&#62;    While gameTime.accumulator &#62; gameTime.logicFPS&#60;br&#62;        doGameLogic(gameTime.LogicFPS)              &#39;Update Game Logic Here&#60;br&#62;        gameTime.accumulator:-gameTime.logicFPS     &#39;update the accumulator&#60;br&#62;    Wend&#60;br&#62;    &#60;br&#62;    &#39; rendering with additional tweening    &#60;br&#62;    Local tween:Float = gameTime.GetTween()         &#39;calc the tween for smooth graphics&#60;br&#62;    doGameRender(tween)                             &#39;Render Game Here&#60;br&#62;    &#60;br&#62;    Flip 1                                          &#39; synchronize graphics buffer flipping with vsync of monitor&#60;br&#62;Wend&#60;br&#62;EndGraphics&#60;br&#62;End&#60;br&#62;&#60;br&#62;&#60;br&#62;Function DoGameLogic(fixedRate:Float)&#60;br&#62;    &#39; nothing here yet&#60;br&#62;End Function&#60;br&#62;&#60;br&#62;Function DoGameRender(tween:Float)&#60;br&#62;    &#39; nothing here yet&#60;br&#62;End Function&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;So what does that code do?&#60;br&#62;First we switch on &#34;SuperStrict&#34; as I already recommended. The second line imports another source code file named &#60;b&#62;TFRLTimer.bmx&#60;/b&#62; which we&#39;ll have a look at in a minute.&#60;br&#62;We then define constants for the screen size and the update frequency which is the fixed frame rate. So we plan to call the update functions 100 times a second which means every 10 milliseconds.&#60;br&#62;The last constant &#60;b&#62;SPIKE_SUPPRESSION&#60;/b&#62; is a cool one as it is another feature of the &#60;b&#62;TFRLTimer&#60;/b&#62; type that is defined in the &#60;b&#62;TFRLTimer.bmx&#60;/b&#62; file. It allows us to smooth the tweening value a bit to avoid spikes that may arise while other background processes on your PC start or terminate while playing the game. So the game play will appear even more smooth &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62; The number (20 in our example) just tells the type to store the last 20 values and use them for smoothing.&#60;br&#62;&#60;br&#62;We open the graphics mode with given width and height and stay in windowed mode (the 0 at the end of the &#60;b&#62;Graphics&#60;/b&#62; command). We set the active blend mode to ALPHABLEND right at the beginning because that&#39;s the blend mode we are mainly going to use in the game and it&#39;s not the default blend mode when you start a BlitzMax application so we do it right at the beginning.&#60;br&#62;&#60;br&#62;Then we create a TFRLTimer object named &#60;b&#62;gameTime&#60;/b&#62;. This object will help us to keep track of all this fixed rate logic and the tweening value and all that.&#60;br&#62;&#60;br&#62;Finally we start our main loop which we&#39;ll only leave if the player presses the Escape key or clicks on the upper right close button of our game window.&#60;br&#62;&#60;br&#62;The loop itself is pretty simple: we clear the screen first. Then we ask the &#60;b&#62;gameTime&#60;/b&#62; object how many milliseconds have passed since the last call to &#60;b&#62;GetDelta()&#60;/b&#62;. The inner while loop helps us to call all outstanding updates. The &#60;b&#62;gameTime.accumulator&#60;/b&#62; stores how many milliseconds are left as we are only interested in multiples of &#60;b&#62;gameTime.LogicFPS&#60;/b&#62; which is exactly our fixed time rate (the update frequency, here 60).&#60;br&#62;&#60;br&#62;We then need to do all drawing but we need to pass the &#60;b&#62;tween&#60;/b&#62; value into the draw methods as explained in the previous paragraph.&#60;br&#62;&#60;br&#62;The main loop finishes with a call to &#60;b&#62;Flip 1&#60;/b&#62; which switches the two drawing buffers of BlitzMax synchronized with the screen&#39;s next vertical sync (vsync) to avoid flickering.&#60;br&#62;&#60;br&#62;If the player presses Escape or clicks into the close box of our window we leave the main loop, call &#60;b&#62;EndGraphics&#60;/b&#62; to switch off BlitzMax&#39; graphics mode and terminate the game.&#60;br&#62;&#60;br&#62;I already added two empty functions &#60;b&#62;DoGameUpdate(fixedRate:Float)&#60;/b&#62; and &#60;b&#62;DoGameRender(tween:Float)&#60;/b&#62; which will contain all required calls to update and render the game objects.&#60;br&#62;&#60;br&#62;So that&#39;s the first approach of the main loop. Save the file as &#60;b&#62;ComeGetMe.bmx&#60;/b&#62; and be prepared to create the second file in a second!&#60;br&#62;</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#mainloop</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#mainloop</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>The TFRLTimer type</title>
  <description>The name &#60;b&#62;TFRLTimer&#60;/b&#62; stands for &#60;b&#62;F&#60;/b&#62;ixed &#60;b&#62;R&#60;/b&#62;ate &#60;b&#62;L&#60;/b&#62;ogic &#60;b&#62;Timer&#60;/b&#62; and the first leading &#60;b&#62;T&#60;/b&#62; just stands for a &#60;b&#62;Type&#60;/b&#62;. It&#39;s good coding practise to always start your Types with a &#60;b&#62;T&#60;/b&#62; and create a new source code file for each type.&#60;br&#62;&#60;br&#62;Shall we have a look at it?&#60;br&#62;%CODE_BEGIN% &#60;br&#62;&#39;==============================================================&#60;br&#62;&#39;===FIXED RATE LOGIC  TWEEN  DELTA SPIKE SUPPRESSION (DSS)===&#60;br&#62;&#39;==============================================================&#60;br&#62;Type TFRLTimer&#60;br&#62;    Field newTime:Float = MilliSecs()&#60;br&#62;    Field oldTime:Float = MilliSecs()&#60;br&#62;    Field delta:Float&#60;br&#62;&#60;br&#62;    Field dssOn:Int     &#39; do we use delta spike suppression?&#60;br&#62;    Field dssIndex:Int      &#39; index into DSS_Array where next delta value is written&#60;br&#62;    Field dssArray:Float[]  &#39; this array contains the delta values to smooth&#60;br&#62;    Field dssLenArray:Int   &#39; how big is the array of delta values&#60;br&#62;&#60;br&#62;    Field logicFPS:Float&#60;br&#62;    Field accumulator:Float, tween:Float&#60;br&#62;&#60;br&#62;    Function CreateFRL:TFRLTimer(logicCyclesPerSec:Float, numSamples:Int = 0)&#60;br&#62;        Local frl:TFRLTimer = New TFRLTimer&#60;br&#62;        frl.logicFPS = 1.0 / logicCyclesPerSec&#60;br&#62;        If numSamples&#60;br&#62;            frl.dssOn = True&#60;br&#62;            frl.dssArray = New Float[numSamples]&#60;br&#62;            frl.dssLenArray = numSamples&#60;br&#62;        EndIf&#60;br&#62;        Return frl&#60;br&#62;    End Function&#60;br&#62;&#60;br&#62;    Method GetDelta:Float()&#60;br&#62;        Self.newTime = MilliSecs()&#60;br&#62;        Self.delta = Float (Self.newTime - Self.oldTime) * 0.001&#60;br&#62;        Self.oldTime = Self.newTime&#60;br&#62;        &#60;br&#62;        If Self.dssOn = True&#60;br&#62;            Self.dssArray[Self.dssIndex] = Self.delta&#60;br&#62;            &#60;br&#62;            Local smoothDelta:Float = 0&#60;br&#62;            &#60;br&#62;            For Local i:Int = 0 To Self.dssLenArray - 1&#60;br&#62;                smoothDelta:+Self.dssArray[i]&#60;br&#62;            Next&#60;br&#62;            Self.delta = Float smoothDelta / dssLenArray&#60;br&#62;            &#60;br&#62;            Self.dssIndex:+1&#60;br&#62;            If Self.dssIndex &#62; dssLenArray - 1 Then Self.dssIndex = 0&#60;br&#62;        EndIf&#60;br&#62;        &#60;br&#62;        Self.accumulator:+Self.delta&#60;br&#62;        &#60;br&#62;        Return Self.delta&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;&#60;br&#62;    Method GetTween:Float()&#60;br&#62;        Return Self.accumulator / Self.logicFPS&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;&#60;br&#62;    Method ShowSpikeSuppression(x:Int, y:Int)&#60;br&#62;        DrawText &#34;Delta Spike Suppressor:&#34;, x, y&#60;br&#62;        For Local i:Int = 0 To Self.dssLenArray - 1&#60;br&#62;            DrawText Self.dssArray[i], x, y + (i + 1) * 25&#60;br&#62;        Next&#60;br&#62;        DrawText &#34;Final Delta: &#34; + Self.delta, x, y + (Self.dssLenArray + 1) * 25&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;End Type&#60;br&#62;%CODE_END% </description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds112</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds112</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>Explanation of the TFRLTimer class</title>
  <description>If the code looks just too complicated and you don&#39;t want to delve into it that&#39;s fine. Just create the file &#60;b&#62;TFRLTimer.bmx&#60;/b&#62;, copy the source code into the file and save it. It will work and you don&#39;t have to understand the source code to get a running game.&#60;br&#62;&#60;br&#62;But if you want to learn how your game system ticks and also want to know about some more BlitzMax features you should read this paragraph &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Every type declaration starts with the keyword &#60;b&#62;Type&#60;/b&#62; and the type&#39;s name and ends with the keyword &#60;b&#62;End Type&#60;/b&#62;. All code between those keywords belongs to the type.&#60;br&#62;&#60;br&#62;We start with some field declarations. You can imagine fields as properties of objects. For example every car has a color and a number of doors. So &#60;b&#62;color&#60;/b&#62; and &#60;b&#62;nrOfDoors&#60;/b&#62; would be fields of a type &#60;b&#62;TCar&#60;/b&#62;. As I already mentioned every type is mainly a template for objects. So if you create an object of type &#60;b&#62;TXYZ&#60;/b&#62; it will have all the fields that are declared in the type. And if you have two or more objects of type &#60;b&#62;TXYZ&#60;/b&#62; all of those objects have their unique values inside the fields, just like you can have a red car with three doors and a blue car with five doors.&#60;br&#62;&#60;br&#62;The fields we define for our type &#60;b&#62;TFRLTimer&#60;/b&#62; are &#60;b&#62;newTime&#60;/b&#62; and &#60;b&#62;oldTime&#60;/b&#62; to store the current time in milliseconds (set when we call &#60;b&#62;GetDelta()&#60;/b&#62;) and the last time we called &#60;b&#62;GetDelta()&#60;/b&#62;. The &#60;b&#62;delta&#60;/b&#62; field should be self explaining.&#60;br&#62;&#60;br&#62;All fields starting with &#60;b&#62;dss&#60;/b&#62; are used for smoothing the delta values. Finally we store the &#60;b&#62;accumulator&#60;/b&#62; and &#60;b&#62;tween&#60;/b&#62; values as Floats.&#60;br&#62;&#60;br&#62;Then we meet something new: a &#60;b&#62;Function&#60;/b&#62;. I already told you that methods can be called for each instance of a type. But what if you don&#39;t have an instance yet? Stuck? No. There are methods that you can send to the type directly without having an instance of that type. Those are called &#60;b&#62;Functions&#60;/b&#62;.&#60;br&#62;And one of the most used kind of function is a &#60;b&#62;Create&#60;/b&#62; function which is commonly used in BlitzMax to create instances of a given type.&#60;br&#62;%CODE_BEGIN% &#60;br&#62;Function CreateFRL:TFRLTimer(logicCyclesPerSec:Float, numSamples:Int = 0)&#60;br&#62;%CODE_END% &#60;br&#62;This function does exactly that: it will return an instance of &#60;b&#62;TFRLTimer&#60;/b&#62; which is specified as the return type of this function. So the syntax for functions is:&#60;br&#62;%CODE_BEGIN% &#60;br&#62;&#60;b&#62;Function&#60;/b&#62; NameOfYourFunction:ReturnTypeOfFunction(parameterOne:TypeOfParameterOne, ParameterTwo:TypeOfParameterTwo = DefaultValueIfNotGiven)&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;A function can have zero to many parameters, not only two as in my example. You can also give default values to parameters which will be used if you omit this parameter in the function call. Those default parameters must be used from &#60;b&#62;right to left&#60;/b&#62; in your function declaration - you cannot have a default value for the first parameter. That&#39;s because the compiler can&#39;t know if you want to use the default value or the first passed in value for the first parameter. So you can only omit parameters starting at the right end of your function declaration.&#60;br&#62;&#60;br&#62;Anyway, back to the &#60;b&#62;CreateFRL()&#60;/b&#62; function. First it creates an empty instance of a &#60;b&#62;TFRLTimer&#60;/b&#62; and then it takes the logic cycles per second and calculates the milliseconds per logic cycle and stores it in the field logicFPS.&#60;br&#62;%CODE_BEGIN% &#60;br&#62;Local frl:TFRLTimer = New TFRLTimer&#60;br&#62;frl.LogicFPS = 1.0 / logicCyclesPerSec&#60;br&#62;%CODE_END% &#60;br&#62;There&#39;s another thing to mention here: &#60;b&#62;Local&#60;/b&#62;. With this keyword you define a local variable which means this variable can only be used inside the function or method where it was defined. Outside of the function &#60;b&#62;CreateFRL()&#60;/b&#62; you cannot access the local variable &#60;b&#62;frl&#60;/b&#62; but you would get a compiler error!&#60;br&#62;&#60;br&#62;On with the remaining lines. If &#60;b&#62;numSamples&#60;/b&#62; is bigger than zero (so we passed in a value to the &#60;b&#62;CreateFRL()&#60;/b&#62; call) we store the information to use samples in &#60;b&#62;dssOn&#60;/b&#62; and store the number of entries in &#60;b&#62;dssLenArray&#60;/b&#62; and allocate an array for the values in &#60;b&#62;dssArray&#60;/b&#62;.&#60;br&#62;Whoops! Another new thing to learn: Arrays in types are not automatically allocated when you create a new type instance. You&#39;ll have to do that on your own, for example in the &#60;b&#62;Create&#60;/b&#62; function of your type.&#60;br&#62;&#60;br&#62;At the end the &#60;b&#62;CreateFRL()&#60;/b&#62; function returns the properly initialized instance of type &#60;b&#62;TFRLTimer&#60;/b&#62; to the caller.&#60;br&#62;&#60;br&#62;Next we find a method named &#60;b&#62;GetDelta()&#60;/b&#62;.&#60;br&#62;%CODE_BEGIN% &#60;br&#62;    Method GetDelta:Float()&#60;br&#62;        Self.newTime = MilliSecs()&#60;br&#62;        Self.delta = Float (Self.newTime - Self.oldTime) * 0.001&#60;br&#62;        Self.oldTime = Self.newTime&#60;br&#62;        &#60;br&#62;        If Self.dssOn = True&#60;br&#62;            Self.dssArray[Self.dssIndex] = Self.delta&#60;br&#62;            &#60;br&#62;            Local smoothDelta:Float = 0&#60;br&#62;            &#60;br&#62;            For Local i:Int = 0 To Self.dssLenArray - 1&#60;br&#62;                smoothDelta:+Self.dssArray[i]&#60;br&#62;            Next&#60;br&#62;            Self.delta = Float smoothDelta / dssLenArray&#60;br&#62;            &#60;br&#62;            Self.dssIndex:+1&#60;br&#62;            If Self.dssIndex &#62; dssLenArray - 1 Then Self.dssIndex = 0&#60;br&#62;        EndIf&#60;br&#62;        &#60;br&#62;        Self.accumulator:+Self.delta&#60;br&#62;        &#60;br&#62;        Return Self.delta&#60;br&#62;    End Method&#60;br&#62;%CODE_END% &#60;br&#62;We know that a method is bound to an instance of a type. So with every instance of &#60;b&#62;TFRLTimer&#60;/b&#62; we can call its &#60;b&#62;GetDelta()&#60;/b&#62; method.&#60;br&#62;The method returns a float value, the delta and the method takes no parameters. Look back into the &#60;a href=&#34;../Topdownshootertu/index.html#mainloop&#34;&#62;main loop&#60;/a&#62; to see where we call&#60;br&#62;%CODE_BEGIN% &#60;br&#62;gameTime.GetDelta()&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;The method calculates the &#60;b&#62;delta&#60;/b&#62; time which is the amount of milliseconds between the last and current calls to &#60;b&#62;GetDelta()&#60;/b&#62;. If &#60;b&#62;dssOn&#60;/b&#62; is true we store the current &#60;b&#62;delta&#60;/b&#62; value in the &#60;b&#62;dssArray&#60;/b&#62; and immediately calculate the smoothed delta. The &#60;b&#62;dssArray&#60;/b&#62; is a wrapping array where the index restarts at 0 when the array size limit is reached. The &#60;b&#62;accumulator&#60;/b&#62; is increased by the &#60;b&#62;delta&#60;/b&#62; value so that the &#60;b&#62;accumulator&#60;/b&#62; always contains the milliseconds since the last completed update call.&#60;br&#62;&#60;br&#62;The last method in this class/type is&#60;br&#62;%CODE_BEGIN% &#60;br&#62;    Method GetTween:Float()&#60;br&#62;        Return Self.accumulator / Self.logicFPS&#60;br&#62;    End Method&#60;br&#62;%CODE_END% &#60;br&#62;Here we simply return the &#60;b&#62;tween&#60;/b&#62; value which is the &#60;b&#62;accumulator&#60;/b&#62; divided by logicFPS.</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds111</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds111</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>First test</title>
  <description>Now that you have &#60;b&#62;ComeGetMe.bmx&#60;/b&#62; and &#60;b&#62;TFRLTimer.bmx&#60;/b&#62; stored in your project folder you should be able to compile the main file &#60;b&#62;ComeGetMe.bmx&#60;/b&#62; which will also compile &#60;b&#62;TFRLTimer.bmx&#60;/b&#62; and the result should be an executable. If you start it a simple black window should open.&#60;br&#62;Press the &#39;Escape&#39; key or use your mouse to close the window.&#60;br&#62;&#60;br&#62;Great! We now got a working code base.</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds110</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds110</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>Already the first refactoring!</title>
  <description>After reading the tutorial for several times now (proof reading while adding new content) I detected what was nagging me all the time. I didn&#39;t like the implementation of the &#60;b&#62;TFRLTimer&#60;/b&#62; class. The main class in it&#39;s main loop had constant access to some fields of the &#60;b&#62;TFRLTimer&#60;/b&#62; and even modified them!&#60;br&#62;This breaks many OO rules like &#60;i&#62;encapsulation&#60;/i&#62; and &#60;i&#62;information hiding&#60;/i&#62; of course. So I just had to refactor the class. And while I was at it I also added some FPS code to show the amount of logic update calls and render calls per second.&#60;br&#62;&#60;br&#62;Let&#39;s look at the modified main class &#60;b&#62;ComeGetMe&#60;/b&#62; and the new &#60;b&#62;TFRLTimer&#60;/b&#62; class.&#60;br&#62;&#60;br&#62;&#60;b&#62;ComeGetMe.bmx&#60;/b&#62;&#60;br&#62;%CODE_BEGIN%&#60;br&#62;SuperStrict&#60;br&#62;&#60;br&#62;Import &#34;TFRLTimer.bmx&#34;&#60;br&#62;&#60;br&#62;Const GFX_WIDTH:Int = 640, GFX_HEIGHT:Int = 480&#60;br&#62;&#60;br&#62;Const UPDATE_FREQUENCY:Float = 100.0, SPIKE_SUPPRESSION:Int = 20&#60;br&#62;&#60;br&#62;Graphics GFX_WIDTH, GFX_HEIGHT, 0&#60;br&#62;&#60;br&#62;SetBlend ALPHABLEND&#60;br&#62;&#60;br&#62;AutoMidHandle(True)&#60;br&#62;&#60;br&#62;Global gameTime:TFRLTimer = New TFRLTimer.CreateFRL(UPDATE_FREQUENCY, SPIKE_SUPPRESSION)        &#39;1st number is logic updates per second and 2nd number is how much spike suppression you want&#60;br&#62;&#60;br&#62;Global player:TPlayer = TPlayer.Create(TCoordinate.Create(GFX_WIDTH / 2, GFX_HEIGHT / 2, 0))&#60;br&#62;&#60;br&#62;&#60;br&#62;&#39; the main loop starts here&#60;br&#62;While Not KeyDown(KEY_ESCAPE) And AppTerminate() = False&#60;br&#62;    Cls&#60;br&#62;    &#60;br&#62;&#60;br&#62;    &#39; update part of the main loop with constant speed&#60;br&#62;    Local delta:Float = gameTime.ProcessTime()&#60;br&#62;    While gameTime.LogicUpdateRequired()&#60;br&#62;        DoGameLogic(gameTime.GetLogicFPS())             &#39;Update Game Logic Here&#60;br&#62;    Wend&#60;br&#62;    &#60;br&#62;    &#39; rendering with additional tweening    &#60;br&#62;    Local tween:Float = gameTime.GetTween()         &#39;calc the tween for smooth graphics&#60;br&#62;    doGameRender(tween)                             &#39;Render Game Here&#60;br&#62;    &#60;br&#62;    Flip 0                                          &#39; synchronize graphics buffer as soon as possible&#60;br&#62;Wend&#60;br&#62;EndGraphics&#60;br&#62;End&#60;br&#62;&#60;br&#62;&#60;br&#62;Function DoGameLogic(fixedRate:Float)&#60;br&#62;    &#39; nothing here yet&#60;br&#62;End Function&#60;br&#62;&#60;br&#62;Function DoGameRender(tween:Float)&#60;br&#62;    &#39; nothing here yet&#60;br&#62;    gameTime.ShowFPS(0, 0)&#60;br&#62;End Function&#60;br&#62;%CODE_END%&#60;br&#62;&#60;br&#62;So the interesting part is the modified main loop. Notice that I only call methods of the &#60;b&#62;gameTime&#60;/b&#62; object. No field of the &#60;b&#62;TFRLTimer&#60;/b&#62; is exposed to the calling class. I also renamed the method &#60;b&#62;GetDelta()&#60;/b&#62; because the method name is misleading. We don&#39;t only retrieve the delta value but the most important thing is that this method also calculates the passed time and updates a lot of internal stuff inside the &#60;b&#62;TFRLTimer&#60;/b&#62; instance. So I decided to rename this method to &#60;b&#62;ProcessTime()&#60;/b&#62; which better describes what the method really does. And as a return value we retrieve the delta time that passed since the last call to &#60;b&#62;ProcessTime()&#60;/b&#62;. Voila. Much better.&#60;br&#62;Also I don&#39;t access the accumulator field of the timer instance. Instead I encapsulated that in a method named &#60;b&#62;LogicUpdateRequired()&#60;/b&#62;. It returns true if enough time passed to at least call the update routines of the game elements once. Also all internal fields like the accumulator are updated. I also added a accessor method &#60;b&#62;GetLogicFPS()&#60;/b&#62; which only returns the field &#60;b&#62;logicFPS&#60;/b&#62; of the &#60;b&#62;TFRLTimer&#60;/b&#62; instance. But this way I can hide all information inside the class. The caller does not know if the &#60;b&#62;logicFPS&#60;/b&#62; is calculated for each call or precalculated on instance creation time.&#60;br&#62;&#60;br&#62;I also added a call to &#60;b&#62;gameTime.ShowFPS()&#60;/b&#62; in the function &#60;b&#62;DoGameRender()&#60;/b&#62;. When we compile &#60;b&#62;ComeGetMe.bmx&#60;/b&#62; we should see a black window with logic and render FPS shown at the top of the screen.&#60;br&#62;&#60;br&#62;Now finish the refactoring by looking at the refactored &#60;b&#62;TFRLTimer&#60;/b&#62; class.</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds109</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds109</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>The refactored TFRLTimer class</title>
  <description>Let&#39;s start with the complete source code for &#60;b&#62;TFRLTimer.bmx&#60;/b&#62;:&#60;br&#62;%CODE_BEGIN%&#60;br&#62;&#39;==============================================================&#60;br&#62;&#39;===FIXED RATE LOGIC  TWEEN  DELTA SPIKE SUPPRESSION (DSS)===&#60;br&#62;&#39;==============================================================&#60;br&#62;Type TFRLTimer&#60;br&#62;    Field newTime:Float = MilliSecs()&#60;br&#62;    Field oldTime:Float = MilliSecs()&#60;br&#62;    Field delta:Float&#60;br&#62;&#60;br&#62;    Field dssOn:Int     &#39; do we use delta spike suppression?&#60;br&#62;    Field dssIndex:Int      &#39; index into DSS_Array where next delta value is written&#60;br&#62;    Field dssArray:Float[]  &#39; this array contains the delta values to smooth&#60;br&#62;    Field dssLenArray:Int   &#39; how big is the array of delta values&#60;br&#62;&#60;br&#62;    Field logicFPS:Float&#60;br&#62;    Field accumulator:Float, tween:Float&#60;br&#62;    &#60;br&#62;    Field fpsAccumulator:Float&#60;br&#62;    Field updateCount:Int&#60;br&#62;    Field renderCount:Int&#60;br&#62;    Field updatesPerSecond:Int&#60;br&#62;    Field rendersPerSecond:Int&#60;br&#62;    &#60;br&#62;&#60;br&#62;    Function CreateFRL:TFRLTimer(logicCyclesPerSec:Float, numSamples:Int = 0)&#60;br&#62;        Local frl:TFRLTimer = New TFRLTimer&#60;br&#62;        frl.logicFPS = 1.0 / logicCyclesPerSec&#60;br&#62;        If numSamples&#60;br&#62;            frl.dssOn = True&#60;br&#62;            frl.dssArray = New Float[numSamples]&#60;br&#62;            frl.dssLenArray = numSamples&#60;br&#62;        EndIf&#60;br&#62;        Return frl&#60;br&#62;    End Function&#60;br&#62;&#60;br&#62;    Method ProcessTime:Float()&#60;br&#62;        Self.newTime = MilliSecs()&#60;br&#62;        Self.delta = Float (Self.newTime - Self.oldTime) * 0.001&#60;br&#62;        Self.oldTime = Self.newTime&#60;br&#62;        &#60;br&#62;        If Self.dssOn = True&#60;br&#62;            Self.dssArray[Self.dssIndex] = Self.delta&#60;br&#62;            &#60;br&#62;            Local smoothDelta:Float = 0&#60;br&#62;            &#60;br&#62;            For Local i:Int = 0 To Self.dssLenArray - 1&#60;br&#62;                smoothDelta:+Self.dssArray[i]&#60;br&#62;            Next&#60;br&#62;            Self.delta = Float smoothDelta / dssLenArray&#60;br&#62;            &#60;br&#62;            Self.dssIndex:+1&#60;br&#62;            If Self.dssIndex &#62; dssLenArray - 1 Then Self.dssIndex = 0&#60;br&#62;        EndIf&#60;br&#62;        &#60;br&#62;        Self.accumulator:+Self.delta&#60;br&#62;        &#60;br&#62;        Self.fpsAccumulator:+Self.delta&#60;br&#62;        If Self.fpsAccumulator &#62; 1.0&#60;br&#62;            Self.fpsAccumulator:-1.0&#60;br&#62;            Self.updatesPerSecond = Self.updateCount&#60;br&#62;            Self.updateCount = 0&#60;br&#62;            Self.rendersPerSecond = Self.renderCount&#60;br&#62;            Self.renderCount = 0&#60;br&#62;        End If&#60;br&#62;        &#60;br&#62;        Return Self.delta&#60;br&#62;    End Method&#60;br&#62;&#60;br&#62;    &#60;br&#62;    Method LogicUpdateRequired:Int()&#60;br&#62;        If Self.accumulator &#62; Self.logicFPS&#60;br&#62;            Self.updateCount:+1&#60;br&#62;            Self.accumulator:-Self.logicFPS&#60;br&#62;            Return True&#60;br&#62;        End If&#60;br&#62;        Return False&#60;br&#62;    End Method&#60;br&#62;&#60;br&#62;    &#60;br&#62;    Method GetLogicFPS:Float()&#60;br&#62;        Return Self.logicFPS&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    &#60;br&#62;    Method GetTween:Float()&#60;br&#62;        Self.renderCount:+1&#60;br&#62;        Return Self.accumulator / Self.logicFPS&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;&#60;br&#62;    Method ShowSpikeSuppression(x:Int, y:Int)&#60;br&#62;        DrawText &#34;Delta Spike Suppressor:&#34;, x, y&#60;br&#62;        For Local i:Int = 0 To Self.dssLenArray - 1&#60;br&#62;            DrawText Self.dssArray[i], x, y + (i + 1) * 20&#60;br&#62;        Next&#60;br&#62;        DrawText &#34;Final Delta: &#34; + Self.delta, x, y + (Self.dssLenArray + 1) * 20&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    &#60;br&#62;    Method ShowFPS(x:Int, y:Int, showUpdateFPS:Int = True, showRenderFPS:Int = True)&#60;br&#62;        Local ty = y&#60;br&#62;        &#60;br&#62;        If showUpdateFPS&#60;br&#62;            DrawText &#34;Logic FPS:  &#34; + updatesPerSecond, x, ty&#60;br&#62;            ty:+20&#60;br&#62;        End If&#60;br&#62;        If showRenderFPS&#60;br&#62;            DrawText &#34;Render FPS: &#34; + rendersPerSecond, x, ty&#60;br&#62;        End If&#60;br&#62;    End Method&#60;br&#62;End Type&#60;br&#62;&#60;br&#62;%CODE_END%&#60;br&#62;&#60;br&#62;As you can see I added some more fields to do the FPS calculation.&#60;br&#62;%CODE_BEGIN%&#60;br&#62;    Field fpsAccumulator:Float&#60;br&#62;    Field updateCount:Int&#60;br&#62;    Field renderCount:Int&#60;br&#62;    Field updatesPerSecond:Int&#60;br&#62;    Field rendersPerSecond:Int&#60;br&#62;%CODE_END%&#60;br&#62;The &#60;b&#62;fpsAccumulator&#60;/b&#62; is increased every time the method &#60;b&#62;ProcessTime()&#60;/b&#62; is called. This way we can detect when one second passed.&#60;br&#62;As I already mentioned &#60;b&#62;ProcessTime()&#60;/b&#62; is just the renamed method &#60;b&#62;GetDelta()&#60;/b&#62; with some minor enhancements.&#60;br&#62;As soon as a second is over the fields &#60;b&#62;updatesPerSecond&#60;/b&#62; and &#60;b&#62;rendersPerSecond&#60;/b&#62; are set with the current values of &#60;b&#62;updateCount&#60;/b&#62; and &#60;b&#62;renderCount&#60;/b&#62;. The two counting variables &#60;b&#62;updateCount&#60;/b&#62; and &#60;b&#62;renderCount&#60;/b&#62; are reset to zero to start again counting the update and render calls for the next second.&#60;br&#62;&#60;br&#62;&#60;b&#62;updatesPerSecond&#60;/b&#62; and &#60;b&#62;rendersPerSecond&#60;/b&#62; are shown when you call the new method &#60;b&#62;ShowFPS()&#60;/b&#62;. They keep their values for one second and then they are overwritten by the new values of &#60;b&#62;updateCount&#60;/b&#62; and &#60;b&#62;renderCount&#60;/b&#62;.&#60;br&#62;&#60;br&#62;%CODE_BEGIN%&#60;br&#62;    Method LogicUpdateRequired:Int()&#60;br&#62;        If Self.accumulator &#62; Self.logicFPS&#60;br&#62;            Self.updateCount:+1&#60;br&#62;            Self.accumulator:-Self.logicFPS&#60;br&#62;            Return True&#60;br&#62;        End If&#60;br&#62;        Return False&#60;br&#62;    End Method&#60;br&#62;%CODE_END%&#60;br&#62;&#60;br&#62;The method &#60;b&#62;LogicUpdateRequired:Int()&#60;/b&#62; is new. It is called from the main loop to detect if at least one update call is pending. If that&#39;s the case the &#60;b&#62;updateCount&#60;/b&#62; is incremented by one and the accumulator is decreased by the update time &#60;b&#62;logicFPS&#60;/b&#62;.&#60;br&#62;&#60;br&#62;The &#60;b&#62;renderCount&#60;/b&#62; is incremented in the &#60;b&#62;GetTween()&#60;/b&#62; method because this method is called for each render phase to retrieve the tween value that needs to go into every render call to tween the movement of game elements.&#60;br&#62;&#60;br&#62;That&#39;s pretty much all for the important and mentionable changes in the &#60;b&#62;TFRLTimer&#60;/b&#62; class.&#60;br&#62;&#60;br&#62;Compile the two source files and if all went well you should see a screen similar to the one below.&#60;br&#62;&#60;br&#62;Those two files can be reused as the base for all your games - consider it the beginning of a small library to help you creating your own games &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds108</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds108</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>Introducing the player - not yet!</title>
  <description>Before we start with the code for the player we&#39;ll need to think a bit about the types we are going to create:&#60;br&#62;&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; we need an old x/y position and a new x/y position for every game element&#60;/li&#62;&#60;li&#62; we need old and new angles for every game element&#60;/li&#62;&#60;li&#62; we need to copy new to old positions in a simple way&#60;/li&#62;&#60;li&#62; we need to calculate distances and angles between positions (for aiming and firing)&#60;/li&#62;&#60;li&#62; we do have game elements that share quite some functionality&#60;/li&#62;&#60;li&#62; all game elements should be forced to implement an update and a render method&#60;/li&#62;&#60;li&#62; we want to share and reuse as much code as possible. Coding by using copy and paste is bad &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;So how do we put those requirements into types?&#60;br&#62;&#60;br&#62;One approach is to have a simple class for x/y positions or coordinates and the angle. It could contain x/y position, the current angle or direction, some methods to copy coordinates and methods for angle and distance calculations.&#60;br&#62;Let&#39;s name this new class/type &#60;b&#62;TCoordinate&#60;/b&#62;.&#60;br&#62;&#60;br&#62;The second class could be called &#60;b&#62;TGameElement&#60;/b&#62; and contains old and new &#60;b&#62;TCoordinate&#60;/b&#62;s and directions and will have all methods that are shared between all different &#60;b&#62;TGameElement&#60;/b&#62;s.&#60;br&#62;&#60;br&#62;To force the programmer to implement proper update and render methods we make those methods &#60;b&#62;abstract&#60;/b&#62; and also we make the whole type &#60;b&#62;abstract&#60;/b&#62;.&#60;br&#62;That&#39;s another OO feature you&#39;ll use frequently.&#60;br&#62;&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; If a type is abstract you cannot create instances of that type. So there will never be an instance of &#60;b&#62;TGameElement&#60;/b&#62;.&#60;/li&#62;&#60;li&#62; You will have to &#60;b&#62;extend&#60;/b&#62; or &#60;b&#62;subclass&#60;/b&#62; this type and create your own derived type of &#60;b&#62;TGameElement&#60;/b&#62;. For example a type &#60;b&#62;TPlayer&#60;/b&#62; will be a subclass of &#60;b&#62;TGameElement&#60;/b&#62; and automatically inherit all fields and all methods of &#60;b&#62;TGameElement&#60;/b&#62; without writing or copying a single line of code!&#60;/li&#62;&#60;li&#62; If a method is abstract the programmer is forced to implement this method in his subclass of the abstract class (so you can only have abstract methods in abstract types).&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;So let&#39;s start with the &#60;b&#62;TCoordinate&#60;/b&#62; class.&#60;br&#62;&#60;br&#62;</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#baseclass</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#baseclass</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>TCoordinate or &#34;Where am I?&#34;</title>
  <description>The &#60;b&#62;TCoordinate&#60;/b&#62; type in it&#39;s first incarnation looks like this:&#60;br&#62;&#60;br&#62;&#60;b&#62;TCoordinate.bmx&#60;/b&#62;&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Type TCoordinate&#60;br&#62;    Field x:Float&#60;br&#62;    Field y:Float&#60;br&#62;    Field angle:Int &#39; we simplify here and just use an integer for angles between 0 and 359 degrees&#60;br&#62;    &#60;br&#62;    Function Create:TCoordinate(x:Float, y:Float, angle:Int)&#60;br&#62;        Local coord:TCoordinate = New TCoordinate&#60;br&#62;        coord.x = x&#60;br&#62;        coord.y = y&#60;br&#62;        coord.angle = angle&#60;br&#62;        Return coord&#60;br&#62;    End Function&#60;br&#62;    &#60;br&#62;    &#60;br&#62;    Function Copy:TCoordinate(original:TCoordinate)&#60;br&#62;        Local copy:TCoordinate = New TCoordinate&#60;br&#62;        copy.x = original.x&#60;br&#62;        copy.y = original.y&#60;br&#62;        copy.angle = original.angle&#60;br&#62;        Return copy&#60;br&#62;    End Function&#60;br&#62;    &#60;br&#62;    Method setPosition(x:Float, y:Float)&#60;br&#62;        Self.x = x&#60;br&#62;        Self.y = y&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Method setAngle(angle:Int)&#60;br&#62;        self.angle = angle&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Method getDistance:Float(otherPos:TCoordinate)&#60;br&#62;        Local l1:Float = Abs(Self.x - otherPos.x)&#60;br&#62;        Local l2:Float = Abs(Self.y - otherPos.y)&#60;br&#62;        Return Sqr((l1 * l1) + (l2 * l2))&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Method getAngle:Int(otherPos:TCoordinate)&#60;br&#62;         Local dx:Float = otherPos.x - Self.x&#60;br&#62;         Local dy:Float = otherPos.y - Self.y&#60;br&#62;         Return Int((ATan2(dy:Float, dx:Float) + 360) Mod 360)&#60;br&#62;    End Method&#60;br&#62;End Type&#60;br&#62;%CODE_END%</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds106</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds106</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>Explanation of the TCoordinate type</title>
  <description>The &#60;b&#62;TCoordinate&#60;/b&#62; type is not very complicated.&#60;br&#62;First we have three fields: &#60;b&#62;x&#60;/b&#62;, &#60;b&#62;y&#60;/b&#62; and &#60;b&#62;angle&#60;/b&#62;. This means that every instance of &#60;b&#62;TCoordinate&#60;/b&#62; has it&#39;s own x and y position and it&#39;s own angle it is targeting at.&#60;br&#62;&#60;br&#62;Then we find two functions that return a &#60;b&#62;TCoordinate&#60;/b&#62; type and are our two valid creator functions.&#60;br&#62;&#60;br&#62;The first function &#60;b&#62;Create:TCoordinate(x:Float, y:Float, angle:Int)&#60;/b&#62; takes the x, y and angle values we want to have in our new instance as parameters.&#60;br&#62;The line&#60;br&#62;%CODE_BEGIN%&#60;br&#62;        Local coord:TCoordinate = New TCoordinate&#60;br&#62;%CODE_END% &#60;br&#62;creates an empty &#60;b&#62;TCoordinate&#60;/b&#62; instance and stores it in the local variable &#60;b&#62;coord&#60;/b&#62;. We then fill the three fields with the parameter values and return the properly initialized instance by returning &#60;b&#62;coord&#60;/b&#62;.&#60;br&#62;&#60;br&#62;For simplification I added another function that creates a &#60;b&#62;TCoordinate&#60;/b&#62; instance. But this function doesn&#39;t take x, y and angle but another &#60;b&#62;TCoordinate&#60;/b&#62; instance that is simply copied into a new instance.&#60;br&#62;%CODE_BEGIN%&#60;br&#62;    Function Copy:TCoordinate(original:TCoordinate)&#60;br&#62;        Local copy:TCoordinate = New TCoordinate&#60;br&#62;        copy.x = original.x&#60;br&#62;        copy.y = original.y&#60;br&#62;        copy.angle = original.angle&#60;br&#62;        Return copy&#60;br&#62;    End Function&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;There are two methods &#60;b&#62;SetPosition(x:Float, y:Float)&#60;/b&#62; and &#60;b&#62;SetAngle(angle:Int)&#60;/b&#62; which allow to modify the fields of an &#60;b&#62;TCoordinate&#60;/b&#62; instance.&#60;br&#62;&#60;br&#62;And finally there are two methods that calculate the distance between two &#60;b&#62;TCoordinate&#60;/b&#62; instances (&#60;b&#62;GetDistance:Float(otherPos:TCoordinate)&#60;/b&#62;) and the angle between two  &#60;b&#62;TCoordinate&#60;/b&#62; instances (&#60;b&#62;GetAngle:Int(otherPos:TCoordinate)&#60;/b&#62;).&#60;br&#62;&#60;br&#62;That&#39;s basic math I copied from somewhere of the Internet &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Now let&#39;s move on to the next class.</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds105</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds105</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>TGameElement or &#34;Who&#39;s in the game?&#34;</title>
  <description>To share common fields and functionality I explained &#60;a href=&#34;../Topdownshootertu/index.html#baseclass&#34;&#62;here&#60;/a&#62; we&#39;ll use the class &#60;b&#62;TGameElement&#60;/b&#62;.&#60;br&#62;It&#39;s not big yet so let&#39;s look at the source:&#60;br&#62;&#60;br&#62;&#60;b&#62;TGameElement.bmx&#60;/b&#62;&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Import &#34;TCoordinate.bmx&#34;&#60;br&#62;&#60;br&#62;Type TGameElement Abstract&#60;br&#62;    Field pos:TCoordinate&#60;br&#62;    Field oldPos:TCoordinate&#60;br&#62;    Field angle:Int&#60;br&#62;    Field oldAngle:Int&#60;br&#62;    &#60;br&#62;    Method Update(fixedRate:Float) Abstract&#60;br&#62;    &#60;br&#62;    Method Render(tween:Float) Abstract&#60;br&#62;End Type&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;We need to import the file &#60;b&#62;TCoordinate.bmx&#60;/b&#62; because we use &#60;b&#62;TCoordinate&#60;/b&#62;s in our &#60;b&#62;TGameElement&#60;/b&#62; instance so we need to tell BlitzMax how a &#60;b&#62;TCoordinate&#60;/b&#62; looks like. The &#60;b&#62;Import&#60;/b&#62; statement is just some kind of hint for BlitzMax where to look for the definition of a &#60;b&#62;TCoordinate&#60;/b&#62;.&#60;br&#62;&#60;br&#62;The Type declaration line ends with the keyword &#60;b&#62;Abstract&#60;/b&#62; which tells BlitzMax two things:&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; There must never be an instance of &#60;b&#62;TGameElement&#60;/b&#62;. Only instances of non abstract subclasses are allowed!&#60;/li&#62;&#60;li&#62; This type/class may contain abstract methods which force subclasses to implement them exactly with the given parameters and return types.&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;Now let&#39;s look at the fields. Not very much surprising - we have two &#60;b&#62;TCoordinate&#60;/b&#62; fields to store the current and the last position of a game element and the same for the angle.&#60;br&#62;&#60;br&#62;Finally we define two abstract methods, &#60;b&#62;Update(fixedRate:Float)&#60;/b&#62; and &#60;b&#62;Render(tween:Float)&#60;/b&#62;. Again, there is no implementation for these methods required. We will have to implement those methods in the subclasses of &#60;b&#62;TGameElement&#60;/b&#62;.&#60;br&#62;&#60;br&#62;That does make sense because the subclasses know best what to update and what to render.&#60;br&#62;&#60;br&#62;Let&#39;s finish the first part of the tutorial by introducing the &#60;b&#62;TPlayer&#60;/b&#62; type, updating the main class &#60;b&#62;ComeGetMe&#60;/b&#62; and have the first rotating turret on screen.</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds104</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds104</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>The player - our first visible object on screen</title>
  <description>Time for the complete source code of the &#60;b&#62;TPlayer&#60;/b&#62; type.&#60;br&#62;&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Import &#34;TGameElement.bmx&#34;&#60;br&#62;Import &#34;TCoordinate.bmx&#34;&#60;br&#62;&#60;br&#62;Incbin &#34;gfx/turret.png&#34;&#60;br&#62;&#60;br&#62;Type TPlayer Extends TGameElement&#60;br&#62;    Global playerImg:TImage&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Function Create:TPlayer(pos:TCoordinate)&#60;br&#62;        Local player:TPlayer = New TPlayer&#60;br&#62;        player.pos = pos&#60;br&#62;        player.oldPos = TCoordinate.Copy(pos)&#60;br&#62;        If playerImg = Null&#60;br&#62;            playerImg = LoadImage(&#34;incbin::gfx/turret.png&#34;)&#60;br&#62;        End If&#60;br&#62;        Return player&#60;br&#62;    End Function&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Method Update(fixedRate:Float)&#60;br&#62;        Local mousePos:TCoordinate&#60;br&#62;        mousePos = TCoordinate.Create(MouseX(), MouseY(), 0)&#60;br&#62;        &#39; let&#39;s rotate to always look at the mouse&#60;br&#62;        Self.oldAngle = Self.angle&#60;br&#62;        Self.angle = pos.getAngle(mousePos)&#60;br&#62;    End Method&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Method Render(tween:Float)&#60;br&#62;        SetRotation(self.angle)&#60;br&#62;        DrawImage(playerImg, pos.x, pos.y)&#60;br&#62;        SetRotation(0)&#60;br&#62;    End Method&#60;br&#62;End Type&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;Because the &#60;b&#62;TPlayer&#60;/b&#62; uses a &#60;b&#62;TCoordinate&#60;/b&#62; for its position and inherits from (or extends) &#60;b&#62;TGameElement&#60;/b&#62; we need to import both files to tell BlitzMax what they are.&#60;br&#62;&#60;br&#62;The next line&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Incbin &#34;gfx/turret.png&#34;&#60;br&#62;%CODE_END% &#60;br&#62;shows a cool feature of BlitzMax. You can tell BlitzMax to include &#60;b&#62;any&#60;/b&#62; binary file into your executable with the command &#60;b&#62;Incbin&#60;/b&#62;. This means you do not have to release all your valuable assets like images, animation strips or sounds as separate files but you can include all of them into your game executable and distribute just that single file!&#60;br&#62;&#60;br&#62;Notice that I used a &#34;/&#34; instead of a &#34;\&#34; for the directory path. This is because BlitzMax is a multi platform solution and under MacOS and Linux the directory separator character is the &#34;/&#34;. So BlitzMax does some automatic platform dependent conversion and you can simply use the &#34;/&#34; to happily retrieve all of your files on any platform.&#60;br&#62;&#60;br&#62;To finish the long description of this single command: I told BlitzMax to load the file &#34;gfx/turret.png&#34; and store it into the executable of our game. Of course the file must be existant under the given directory and filename...&#60;br&#62;&#60;br&#62;Let&#39;s continue with the declaration of the &#60;b&#62;Tplayer&#60;/b&#62; type, making it an extension of the &#60;b&#62;TGameElement&#60;/b&#62; type. That means we need to implement the &#60;b&#62;Update()&#60;/b&#62; and &#60;b&#62;Render()&#60;/b&#62; methods later on in our type.&#60;br&#62;But first we define a global&#60;br&#62;%CODE_BEGIN%&#60;br&#62;    Global playerImg:TImage&#60;br&#62;%CODE_END% &#60;br&#62;A &#60;b&#62;Global&#60;/b&#62; is a field that is exactly the same for all instances. In other languages like C++ or Java such a variable is a &#60;b&#62;static&#60;/b&#62; variable. It belongs to the type and should only be accessed by using the type prefix (&#60;b&#62;TPlayer.playerImg&#60;/b&#62;) from outside of the type itself.&#60;br&#62;&#60;br&#62;As we reuse the image for the player every time we draw it loading and storing the image once is fine.&#60;br&#62;&#60;br&#62;Let&#39;s have a short look at the &#60;b&#62;Create&#60;/b&#62; method which is used to create a &#60;b&#62;TPlayer&#60;/b&#62; instance.&#60;br&#62;%CODE_BEGIN%&#60;br&#62;    Function Create:TPlayer(pos:TCoordinate)&#60;br&#62;        Local player:TPlayer = New TPlayer&#60;br&#62;        player.pos = pos&#60;br&#62;        player.oldPos = TCoordinate.Copy(pos)&#60;br&#62;        If playerImg = Null&#60;br&#62;            playerImg = LoadImage(&#38;#34;incbin::gfx/turret.png&#38;#34;)&#60;br&#62;        End If&#60;br&#62;        Return player&#60;br&#62;    End Function&#60;br&#62;%CODE_END%&#60;br&#62;&#60;br&#62;We want to create the player instance at the center of the screen so we let the &#60;b&#62;Create&#60;/b&#62; method take the position as a parameter. A new empty &#60;b&#62;TPlayer&#60;/b&#62; instance is created and it&#39;s fields &#60;b&#62;pos&#60;/b&#62; and &#60;b&#62;oldPos&#60;/b&#62; (inherited from &#60;b&#62;TGameElement&#60;/b&#62;) are initialized with the parameter position.&#60;br&#62;The line&#60;br&#62;%CODE_BEGIN%&#60;br&#62;        If playerImg = Null&#60;br&#62;%CODE_END%&#60;br&#62;checks if we already loaded the image. By default all fields that take a type (like &#60;b&#62;TImage&#60;/b&#62;, the BlitzMax type for images) are initialized with &#60;b&#62;Null&#60;/b&#62;. So we can compare against it.&#60;br&#62;If the image is loaded the global &#60;b&#62;playerImg&#60;/b&#62; is &#34;pointing&#34; to an image and thus no longer &#60;b&#62;Null&#60;/b&#62;.&#60;br&#62;When loading the image we need to tell BlitzMax that the image was initially &#60;b&#62;incbin&#60;/b&#62;ed and needs to be loaded from inside the executable and not from a directory. So we prefix the file path with incbin::&#60;br&#62;%CODE_BEGIN%&#60;br&#62;            playerImg = LoadImage(&#38;#34;incbin::gfx/turret.png&#38;#34;)&#60;br&#62;%CODE_END%&#60;br&#62; At the end of the &#60;b&#62;Create&#60;/b&#62; function the initialized player object is returned.&#60;br&#62;&#60;br&#62;The &#60;b&#62;Update()&#60;/b&#62; method is not very complicated to understand. Let&#39;s look at it:&#60;br&#62;%CODE_BEGIN%&#60;br&#62;    Method Update(fixedRate:Float)&#60;br&#62;        Local mousePos:TCoordinate&#60;br&#62;        mousePos = TCoordinate.Create(MouseX(), MouseY(), 0)&#60;br&#62;        &#39; let&#39;s rotate to always look at the mouse&#60;br&#62;        Self.oldAngle = Self.angle&#60;br&#62;        Self.angle = pos.getAngle(mousePos)&#60;br&#62;    End Method&#60;br&#62;%CODE_END%&#60;br&#62;We declare a local variable &#60;b&#62;mousePos&#60;/b&#62; which is a &#60;b&#62;TCoordinate&#60;/b&#62;. In the next line we create a new &#60;b&#62;TCoordinate&#60;/b&#62; that is placed on the current mouse pointer position (retrieved by calling &#60;b&#62;MouseX()&#60;/b&#62; and &#60;b&#62;MouseY()&#60;/b&#62;). We store the last &#60;b&#62;angle&#60;/b&#62; in &#60;b&#62;oldAngle&#60;/b&#62; and calculate the new angle by using the &#60;b&#62;TCoordinate&#60;/b&#62; method &#60;b&#62;getAngle()&#60;/b&#62; between the turret&#39;s position and the mouse pointer position.&#60;br&#62;&#60;br&#62;The &#60;b&#62;Render()&#60;/b&#62; method is even simpler:&#60;br&#62;%CODE_BEGIN%&#60;br&#62;    Method Render(tween:Float)&#60;br&#62;        SetRotation(self.angle)&#60;br&#62;        DrawImage(playerImg, pos.x, pos.y)&#60;br&#62;        SetRotation(0)&#60;br&#62;    End Method&#60;br&#62;%CODE_END%&#60;br&#62;With the BlitzMax &#60;b&#62;SetRotation()&#60;/b&#62; function we assure that all following drawing commands will be rotated by the given angle (&#60;b&#62;self.angle&#60;/b&#62; is the angle of the player instance).&#60;br&#62;Then we draw the image &#60;b&#62;playerImg&#60;/b&#62; at the turret&#39;s position and finally switch back to a rotation of zero to assure that all following drawing commands are not affected by our rotated drawing of the player image.&#60;br&#62;&#60;br&#62;And that was about it. We finish the first part of the tutorial with a look at the updated main loop code.&#60;br&#62;</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds103</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds103</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>The updated main file ComeGetMe.bmx</title>
  <description>%CODE_BEGIN%&#60;br&#62;SuperStrict&#60;br&#62;&#60;br&#62;Import &#34;TFRLTimer.bmx&#34;&#60;br&#62;Import &#34;TPlayer.bmx&#34;&#60;br&#62;&#60;br&#62;Const GFX_WIDTH:Int = 640, GFX_HEIGHT:Int = 480&#60;br&#62;&#60;br&#62;Const UPDATE_FREQUENCY:Float = 100.0, SPIKE_SUPPRESSION:Int = 20&#60;br&#62;&#60;br&#62;Graphics GFX_WIDTH, GFX_HEIGHT, 0&#60;br&#62;&#60;br&#62;SetBlend ALPHABLEND&#60;br&#62;&#60;br&#62;AutoMidHandle(True)&#60;br&#62;&#60;br&#62;Global gameTime:TFRLTimer = New TFRLTimer.CreateFRL(UPDATE_FREQUENCY, SPIKE_SUPPRESSION)        &#39;1st number is logic updates per second and 2nd number is how much spike suppression you want&#60;br&#62;&#60;br&#62;Global player:TPlayer = TPlayer.Create(TCoordinate.Create(GFX_WIDTH / 2, GFX_HEIGHT / 2, 0))&#60;br&#62;&#60;br&#62;&#60;br&#62;&#39; the main loop starts here&#60;br&#62;While Not KeyDown(KEY_ESCAPE) And AppTerminate() = False&#60;br&#62;    Cls&#60;br&#62;    &#60;br&#62;&#60;br&#62;    &#39; update part of the main loop with constant speed&#60;br&#62;    Local delta:Float = gameTime.ProcessTime()&#60;br&#62;    While gameTime.LogicUpdateRequired()&#60;br&#62;        DoGameLogic(gameTime.GetLogicFPS())             &#39;Update Game Logic Here&#60;br&#62;    Wend&#60;br&#62;    &#60;br&#62;    &#39; rendering with additional tweening    &#60;br&#62;    Local tween:Float = gameTime.GetTween()         &#39;calc the tween for smooth graphics&#60;br&#62;    doGameRender(tween)                             &#39;Render Game Here&#60;br&#62;    &#60;br&#62;    Flip 0                                          &#39; synchronize graphics buffer as soon as possible&#60;br&#62;Wend&#60;br&#62;EndGraphics&#60;br&#62;End&#60;br&#62;&#60;br&#62;&#60;br&#62;Function DoGameLogic(fixedRate:Float)&#60;br&#62;    player.Update(fixedRate)&#60;br&#62;End Function&#60;br&#62;&#60;br&#62;Function DoGameRender(tween:Float)&#60;br&#62;    player.Render(tween)&#60;br&#62;    gameTime.ShowFPS(0, 0)&#60;br&#62;End Function&#60;br&#62;%CODE_END% &#60;br&#62;What&#39;s new here?&#60;br&#62;We added the import of the &#60;b&#62;TPlayer&#60;/b&#62; type at the beginning of the file.&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Import &#34;TPlayer.bmx&#34;&#60;br&#62;%CODE_END%&#60;br&#62;A few lines below we added the line&#60;br&#62;%CODE_BEGIN%&#60;br&#62;AutoMidHandle(True)&#60;br&#62;%CODE_END%&#60;br&#62;&#60;br&#62;This line places the &#60;i&#62;hot spot&#60;/i&#62; of any image to it&#39;s center. The default &#60;i&#62;hot spot&#60;/i&#62; of an image is the top left corner. The &#60;i&#62;hot spot&#60;/i&#62; is used for drawing commands. When you draw an image with the &#60;b&#62;DrawImage&#60;/b&#62; command the hot pot is placed at the position you pass as the parameters of the &#60;b&#62;DrawImage&#60;/b&#62; command. Also rotating an image uses the hot spot as the rotation position. So placing it at the center of the image helps us to properly place our player at the center of the screen and smoothly rotate the player turret around it&#39;s center and not around it&#39;s top left corner.&#60;br&#62;&#60;br&#62;To access the player everywhere in our main file (and also in all other source code files) we declare a global variable for the player. It&#39;s name is &#60;b&#62;player&#60;/b&#62; and it is created by calling the &#60;b&#62;TPlayer.Create()&#60;/b&#62; function. As you can see we place the player in the middle of the screen.&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Global player:TPlayer = TPlayer.Create(TCoordinate.Create(GFX_WIDTH / 2, GFX_HEIGHT / 2, 0))&#60;br&#62;%CODE_END%&#60;br&#62;The &#60;b&#62;TPlayer.Create()&#60;/b&#62; function expects a &#60;b&#62;TCoordinate&#60;/b&#62; instance as the only parameter. Instead of creating a temporary variable for a &#60;b&#62;TCoordinate&#60;/b&#62; we just do some nested call by creating a new &#60;b&#62;TCoordinate&#60;/b&#62; instance inside the &#60;b&#62;TPlayer.Create()&#60;/b&#62; call.&#60;br&#62;BlitzMax first creates the &#60;b&#62;TCoordinate&#60;/b&#62; instance (which is the result of the &#60;b&#62;TCoordinate.Create()&#60;/b&#62; function) and passes that into the &#60;b&#62;TPlayer.Create()&#60;/b&#62; function call.&#60;br&#62;This is a bit tricky to understand at first but it&#39;s a very common way in OO world and helps you to avoid unneccessary declaration of local variables in methods and functions.&#60;br&#62;&#60;br&#62;The last thing we need to do is add the &#60;b&#62;player.Update()&#60;/b&#62; and &#60;b&#62;player.render()&#60;/b&#62; calls to the two functions &#60;b&#62;DoGameLogic()&#60;/b&#62; and &#60;b&#62;DoGameRender()&#60;/b&#62;. See the code below.&#60;br&#62;&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Function DoGameLogic(fixedRate:Float)&#60;br&#62;    player.Update(fixedRate)&#60;br&#62;End Function&#60;br&#62;&#60;br&#62;Function DoGameRender(tween:Float)&#60;br&#62;    player.Render(tween)&#60;br&#62;    gameTime.ShowFPS(0, 0)&#60;br&#62;End Function&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;And that&#39;s about it for the first part. Find the download of the source code below. And also the link to the second part where we will add bullets and enemies and some sound.&#60;br&#62;&#60;br&#62;Stay tuned!</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#tds102</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#tds102</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>Download part one</title>
  <description>You can grab the first part of the tutorial including the graphics and all the source code if you click on the button below.&#60;br&#62;&#60;br&#62;Have fun with it &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;&#60;a href=&#34;../tdstutorialpart2/index.html&#34;&#62;Part 2 of the tutorial&#60;/a&#62;</description>
  <link>http://www.haaks.net/topdownshootertu/index.html#downloadpartone</link>
  <guid isPermaLink="true">http://www.haaks.net/topdownshootertu/index.html#downloadpartone</guid>
  <category>Top down shooter tutorial with BlitzMax</category>
</item>
<item>
  <title>Welcome back to the tutorial and to TGameElements!</title>
  <description>Welcome to the second part of the tutorial.&#60;br&#62;&#60;br&#62;I will reduce the details of explanation in this second part and only mention issues that I consider worth mentioning. Code that is similar to stuff in the first part will not be explained as detailed again.&#60;br&#62;&#60;br&#62;Let&#39;s begin with enhancing the &#60;b&#62;TGameElement&#60;/b&#62; type. I&#39;ve added a function &#60;b&#62;Tween()&#60;/b&#62; that takes the old and new position of the moving game element and the current tween value and it returns the proper position for the current place to render.&#60;br&#62;Position can be any tweening value like x or y coordinate or an angle.&#60;br&#62;&#60;br&#62;I also added a boolean field &#60;b&#62;dead&#60;/b&#62; to indicate if the game element is dead or alive. Dead game elements will not be rendered but will be removed from their appropriate list (the list of all bullets or all enemies).&#60;br&#62;&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Import &#34;TCoordinate.bmx&#34;&#60;br&#62;&#60;br&#62;Type TGameElement Abstract&#60;br&#62;    Field pos:TCoordinate&#60;br&#62;    Field oldPos:TCoordinate&#60;br&#62;    Field angle:Int&#60;br&#62;    Field oldAngle:Int&#60;br&#62;    Field dead:Int = false&#60;br&#62;    &#60;br&#62;    Method Update(fixedRate:Float) Abstract&#60;br&#62;    &#60;br&#62;    Method Render(tween:Float) Abstract&#60;br&#62;    &#60;br&#62;    Function Tween:Float(oldpos:Float, newpos:Float, tween:Float)&#60;br&#62;        &#39;drawing pos = newpos * tween + oldpos * ( 1.0 - tween)&#60;br&#62;        Local tweenpos:Float&#60;br&#62;        tweenpos = newpos * tween + oldpos * (1.0 - tween)&#60;br&#62;        Return tweenpos&#60;br&#62;    End Function&#60;br&#62;End Type&#60;br&#62;%CODE_END% </description>
  <link>http://www.haaks.net/tdstutorialpart2/index.html#tds201</link>
  <guid isPermaLink="true">http://www.haaks.net/tdstutorialpart2/index.html#tds201</guid>
  <category>Top down shooter tutorial with BlitzMax, part 2</category>
</item>
<item>
  <title>TCoordinates also modified</title>
  <description>If you look at &#60;b&#62;TCoordinate&#60;/b&#62; it doesn&#39;t contain methods to set one &#60;b&#62;TCoordinate&#60;/b&#62; instance&#39;s x and y and angle identical to those of a second &#60;b&#62;TCoordinate&#60;/b&#62; instance.&#60;br&#62;I changed that with the new methods &#60;b&#62;SetPositionLike(otherPos:TCoordinate)&#60;/b&#62;, &#60;b&#62;SetAngleLike(otherPos:TCoordinate)&#60;/b&#62; and &#60;b&#62;SetLike(otherPos:TCoordinate)&#60;/b&#62;.&#60;br&#62;&#60;br&#62;Also added are two more methods:&#60;br&#62;&#60;b&#62;Normalize()&#60;/b&#62; treats a &#60;b&#62;TCoordinate&#60;/b&#62; instance as a vector and modifies x and y values so that the &#34;length&#34; of this vector is 1 (do you remember Pythagoras and his triangles? &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;). This method is helpful and required for the next method.&#60;br&#62;&#60;br&#62;&#60;b&#62;GetDirection(toPos:TCoordinate)&#60;/b&#62; returns a &#34;normalized&#34; &#60;b&#62;TCoordinate&#60;/b&#62; instance that points into the direction of the given &#60;b&#62;TCoordinate&#60;/b&#62; instance &#60;b&#62;toPos&#60;/b&#62;.&#60;br&#62;We use a direction vector to let an enemy move to the player&#39;s turret as you will see later.&#60;br&#62;&#60;br&#62;So here comes the complete new &#60;b&#62;TCoordinate&#60;/b&#62; code:&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Type TCoordinate&#60;br&#62;    Field x:Float&#60;br&#62;    Field y:Float&#60;br&#62;    Field angle:Int &#39; we simplify here and just use an integer for angles between 0 and 359 degrees&#60;br&#62;    &#60;br&#62;    Function Create:TCoordinate(x:Float, y:Float, angle:Int)&#60;br&#62;        Local coord:TCoordinate = New TCoordinate&#60;br&#62;        coord.x = x&#60;br&#62;        coord.y = y&#60;br&#62;        coord.angle = angle&#60;br&#62;        Return coord&#60;br&#62;    End Function&#60;br&#62;    &#60;br&#62;    &#60;br&#62;    Function Copy:TCoordinate(original:TCoordinate)&#60;br&#62;        Local copy:TCoordinate = New TCoordinate&#60;br&#62;        copy.x = original.x&#60;br&#62;        copy.y = original.y&#60;br&#62;        copy.angle = original.angle&#60;br&#62;        Return copy&#60;br&#62;    End Function&#60;br&#62;    &#60;br&#62;    Method SetPosition(x:Float, y:Float)&#60;br&#62;        Self.x = x&#60;br&#62;        Self.y = y&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Method SetPositionLike(otherPos:TCoordinate)&#60;br&#62;        Self.x = otherPos.x&#60;br&#62;        Self.y = otherPos.y&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Method SetAngle(angle:Int)&#60;br&#62;        self.angle = angle&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Method SetAngleLike(otherPos:TCoordinate)&#60;br&#62;        Self.angle = otherPos.angle&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Method SetLike(otherPos:TCoordinate)&#60;br&#62;        SetPositionLike(otherPos)&#60;br&#62;        SetAngleLike(otherPos)&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Method GetDistance:Float(otherPos:TCoordinate)&#60;br&#62;        Local l1:Float = Abs(Self.x - otherPos.x)&#60;br&#62;        Local l2:Float = Abs(Self.y - otherPos.y)&#60;br&#62;        Return Sqr((l1 * l1) + (l2 * l2))&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Method GetAngle:Int(otherPos:TCoordinate)&#60;br&#62;         Local dx:Float = otherPos.x - Self.x&#60;br&#62;         Local dy:Float = otherPos.y - Self.y&#60;br&#62;         Return Int((ATan2(dy:Float, dx:Float) + 360) Mod 360)&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Rem&#60;br&#62;    BBDoc: calculate a normalized direction vector pointing from self to given toPos&#60;br&#62;    EndRem&#60;br&#62;    Method GetDirection:TCoordinate(toPos:TCoordinate)&#60;br&#62;        Local xdiff:Float = toPos.x - Self.x&#60;br&#62;        Local ydiff:Float = toPos.y - Self.y&#60;br&#62;        Local angle:Int = Self.GetAngle(toPos)&#60;br&#62;        Local dir:TCoordinate = TCoordinate.Create(xdiff, ydiff, angle)&#60;br&#62;        dir.Normalize()&#60;br&#62;        Return dir&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;    Rem&#60;br&#62;    BBDoc: normalizes this vector&#60;br&#62;    endrem&#60;br&#62;    Method Normalize()&#60;br&#62;        Local magnitude:Float = Sqr(Self.x * Self.x + Self.y * Self.y)&#60;br&#62;        Self.x = Self.x / magnitude&#60;br&#62;        Self.y = Self.y / magnitude&#60;br&#62;    End Method&#60;br&#62;    &#60;br&#62;End Type&#60;br&#62;%CODE_END% </description>
  <link>http://www.haaks.net/tdstutorialpart2/index.html#tds202</link>
  <guid isPermaLink="true">http://www.haaks.net/tdstutorialpart2/index.html#tds202</guid>
  <category>Top down shooter tutorial with BlitzMax, part 2</category>
</item>
<item>
  <title>Bullets here we come</title>
  <description>It&#39;s about time to introduce some weapon stuff.&#60;br&#62;&#60;br&#62;For this we&#39;ll add a &#60;b&#62;TBullet&#60;/b&#62; type.&#60;br&#62;&#60;br&#62;It looks like this:&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Import &#34;TGameElement.bmx&#34;&#60;br&#62;Import &#34;TCoordinate.bmx&#34;&#60;br&#62;&#60;br&#62;Incbin &#34;gfx/whitecircle.png&#34;&#60;br&#62;&#60;br&#62;Type TBullet Extends TGameElement&#60;br&#62;&#60;br&#62;    Global bulletImg:TImage&#60;br&#62;    Global allBullets:TList = New TList&#60;br&#62;    Global defaultspeed:Float = 3.0 &#39; with a logical framerate of 100 and a speed of 3.0 our bullets move 300 pixel per second&#60;br&#62;    &#60;br&#62;    Field dir:TCoordinate&#60;br&#62;    Field speed:Float&#60;br&#62;    Field shotBy:Int&#60;br&#62;    &#60;br&#62;&#60;br&#62;    Function Create:TBullet(pos:TCoordinate, direction:TCoordinate, speed:Float)&#60;br&#62;        Local bullet:TBullet = New TBullet&#60;br&#62;        bullet.pos = TCoordinate.Copy(pos)&#60;br&#62;        bullet.oldPos = TCoordinate.Copy(pos)&#60;br&#62;        If bulletImg = Null&#60;br&#62;            bulletImg = LoadImage(&#34;incbin::gfx/whitecircle.png&#34;)&#60;br&#62;        End If&#60;br&#62;        bullet.angle = direction.angle&#60;br&#62;        bullet.dir = direction&#60;br&#62;        bullet.speed = speed&#60;br&#62;        allBullets.AddLast(bullet)&#60;br&#62;        Return bullet&#60;br&#62;    End Function&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Method Update(fixedRate:Float)&#60;br&#62;        &#39; move in direction dir with given bullet speed&#60;br&#62;        Self.oldPos.SetLike(Self.pos) &#39; store current pos in oldPos&#60;br&#62;        Self.pos.x:+(Self.dir.x * Self.speed)&#60;br&#62;        Self.pos.y:+(Self.dir.y * Self.speed)&#60;br&#62;        &#60;br&#62;        If (Self.pos.x &#60; 0 Or Self.pos.y &#60; 0 Or Self.pos.x &#62; GraphicsWidth()  Or Self.pos.y &#62; GraphicsHeight() or self.dead)&#60;br&#62;            &#39; delete this bullet&#60;br&#62;            allBullets.Remove(Self)&#60;br&#62;        End If&#60;br&#62;    End Method&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Method Render(tween:Float)&#60;br&#62;        SetRotation(Self.angle)&#60;br&#62;        &#39; calculate proper tween position here&#60;br&#62;        SetColor(255, 0, 0)&#60;br&#62;        DrawImage(bulletImg, TGameElement.Tween(oldpos.x, pos.x, tween), TGameElement.Tween(oldpos.y, pos.y, tween))&#60;br&#62;        SetRotation(0)&#60;br&#62;        SetColor(255, 255, 255)&#60;br&#62;    End Method&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Function UpdateAllBullets(fixedRate:Float)&#60;br&#62;        For Local bullet:TBullet = EachIn allBullets&#60;br&#62;            bullet.Update(fixedRate)&#60;br&#62;        Next&#60;br&#62;    End Function&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Function RenderAllBullets(tween:Float)&#60;br&#62;        For Local bullet:TBullet = EachIn allBullets&#60;br&#62;            bullet.Render(tween)&#60;br&#62;        Next&#60;br&#62;        &#39; DrawText &#34;Nr of bullets &#34; + allBullets.Count(), 10, 400&#60;br&#62;    End Function&#60;br&#62;End Type&#60;br&#62;%CODE_END%&#60;br&#62;&#60;br&#62;As &#60;b&#62;TBullet&#60;/b&#62; inherits from &#60;b&#62;TGameElement&#60;/b&#62; and uses &#60;b&#62;TCoordinate&#60;/b&#62;s we import those two files. And we use an image for the bullets so we &#60;b&#62;IncBin&#60;/b&#62; that.&#60;br&#62;&#60;br&#62;Every &#60;b&#62;TBullet&#60;/b&#62; instance has a direction (&#60;b&#62;dir&#60;/b&#62;) it&#39;s flying to and a speed and should know who shot it (an enemy or the player, not used yet). So those are fields.&#60;br&#62;The &#60;b&#62;bulletImg&#60;/b&#62;, the &#60;b&#62;defaultSpeed&#60;/b&#62; and the list &#60;b&#62;allBullets&#60;/b&#62; containing all &#60;b&#62;TBullet&#60;/b&#62; instances are used by all &#60;b&#62;TBullet&#60;/b&#62; instances so they are defined as &#60;b&#62;Global&#60;/b&#62;.&#60;br&#62;&#60;br&#62;The &#60;b&#62;Create&#60;/b&#62; method is not very spectacular: it takes the starting position, the direction and speed as parameters and simply initializes a new &#60;b&#62;TBullet&#60;/b&#62; instance with those values.&#60;br&#62;&#60;br&#62;Because &#60;b&#62;TBullet&#60;/b&#62; inherits from &#60;b&#62;TGameElement&#60;/b&#62; we implement an &#60;b&#62;Update&#60;/b&#62; and a &#60;b&#62;Render&#60;/b&#62; method.&#60;br&#62;An important part of the &#60;b&#62;Update&#60;/b&#62; method is the code that removes a bullet from the list of all active bullets if it leaves the screen or is marked as &#60;i&#62;dead&#60;/i&#62;.&#60;br&#62;&#60;br&#62;The &#60;b&#62;Render&#60;/b&#62; method uses the &#60;b&#62;TGameElement.Tween&#60;/b&#62; function to properly calculate the tweened coordinates where the bullet is to be drawn.&#60;br&#62;&#60;br&#62;The functions &#60;b&#62;UpdateAllBullets&#60;/b&#62; and &#60;b&#62;RenderAllBullets&#60;/b&#62; are declared as Functions so that they can be called from everywhere (for example in the main loop of our &#60;b&#62;ComeGetMe.bmx&#60;/b&#62; as we will see later.&#60;br&#62;&#60;br&#62;Not very complicated at all, right?&#60;br&#62;&#60;br&#62;So let&#39;s proceed with the enemies.</description>
  <link>http://www.haaks.net/tdstutorialpart2/index.html#tds203</link>
  <guid isPermaLink="true">http://www.haaks.net/tdstutorialpart2/index.html#tds203</guid>
  <category>Top down shooter tutorial with BlitzMax, part 2</category>
</item>
<item>
  <title>Enemies are eeeeevil!</title>
  <description>Of course they are - this is a computer game &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Code wise enemies are not very different from bullets. Strange isn&#39;t it?&#60;br&#62;&#60;br&#62;Let&#39;s get on with it.&#60;br&#62;&#60;br&#62;%CODE_BEGIN%&#60;br&#62;Import &#34;TGameElement.bmx&#34;&#60;br&#62;Import &#34;TCoordinate.bmx&#34;&#60;br&#62;Import &#34;TBullet.bmx&#34;&#60;br&#62;&#60;br&#62;Incbin &#34;gfx/soldier.png&#34;&#60;br&#62;&#60;br&#62;Type TEnemy Extends TGameElement&#60;br&#62;    Global enemyImg:TImage&#60;br&#62;    Global allEnemies:TList = New TList&#60;br&#62;    Global defaultspeed:Float = 1.0 &#39; with a logical framerate of 100 and a speed of 1.0 our enemies move 100 pixel per second&#60;br&#62;    Global frameChange:Int = 20 &#39; with a logical framerate of 100 we change the animation frame every fifth of a second&#60;br&#62;    Global frameCount:Int = 0&#60;br&#62;    Global frameInc:Int = 1&#60;br&#62;    &#60;br&#62;    Field dir:TCoordinate&#60;br&#62;    Field speed:Float&#60;br&#62;    Field frame:Int = 0 &#39; first frame of animated image that we show&#60;br&#62;&#60;br&#62;&#60;br&#62;    Function Create:TEnemy(pos:TCoordinate, direction:TCoordinate, speed:Float)&#60;br&#62;        Local enemy:TEnemy = New TEnemy&#60;br&#62;        enemy.pos = TCoordinate.Copy(pos)&#60;br&#62;        enemy.oldPos = TCoordinate.Copy(pos)&#60;br&#62;        If enemyImg = Null&#60;br&#62;            enemyImg = LoadAnimImage(&#34;incbin::gfx/soldier.png&#34;, 40, 40, 0, 3)&#60;br&#62;        End If&#60;br&#62;        enemy.angle = direction.angle&#60;br&#62;        enemy.dir = direction&#60;br&#62;        enemy.speed = speed&#60;br&#62;        allEnemies.AddLast(enemy)&#60;br&#62;        Return enemy&#60;br&#62;    End Function&#60;br&#62;&#60;br&#62;    &#60;br&#62;    Method Update(fixedRate:Float)&#60;br&#62;        &#39; move in direction dir with given enemy speed&#60;br&#62;        Self.oldPos.SetLike(Self.pos) &#39; store current pos in oldPos&#60;br&#62;        Self.pos.x:+(Self.dir.x * Self.speed)&#60;br&#62;        Self.pos.y:+(Self.dir.y * Self.speed)&#60;br&#62;        Self.frameCount:+1&#60;br&#62;        If Self.frameCount &#62; Self.frameChange&#60;br&#62;            Self.frameCount = 0&#60;br&#62;            Self.frame:+Self.frameInc&#60;br&#62;            If Self.frame &#62; 2&#60;br&#62;                Self.frame = 0&#60;br&#62;                Self.frameInc = -Self.frameInc&#60;br&#62;            End If&#60;br&#62;            If Self.frame &#60; 0&#60;br&#62;                Self.frame = 2&#60;br&#62;                Self.frameInc = -Self.frameInc&#60;br&#62;            End If&#60;br&#62;        End If&#60;br&#62;&#60;br&#62;        &#39; check for collisions with bullets&#60;br&#62;        For Local bullet:TBullet = EachIn TBullet.allBullets&#60;br&#62;            If ImagesCollide(Self.enemyImg, Self.pos.x, Self.pos.y, Self.frame, bullet.bulletImg, bullet.pos.x, bullet.pos.y, 0)&#60;br&#62;                Self.dead = True&#60;br&#62;                bullet.dead = True&#60;br&#62;            End If&#60;br&#62;        Next&#60;br&#62;        &#60;br&#62;        If (Self.pos.x &#60; 0 Or Self.pos.y &#60; 0 Or Self.pos.x &#62; GraphicsWidth() Or Self.pos.y &#62; GraphicsHeight() Or Self.dead)&#60;br&#62;            &#39; delete this enemy&#60;br&#62;            allEnemies.Remove(Self)&#60;br&#62;        End If&#60;br&#62;        &#60;br&#62;    End Method&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Method Render(tween:Float)&#60;br&#62;        SetRotation(Self.angle)&#60;br&#62;        &#39; calculate proper tween position here&#60;br&#62;        SetColor(255, 255, 255)&#60;br&#62;        DrawImage(enemyImg, TGameElement.Tween(oldpos.x, pos.x, tween), TGameElement.Tween(oldpos.y, pos.y, tween), Self.frame)&#60;br&#62;        SetRotation(0)&#60;br&#62;        SetColor(255, 255, 255)&#60;br&#62;    End Method&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Function UpdateAllEnemies(fixedRate:Float, playerPos:TCoordinate)&#60;br&#62;        If allEnemies.Count() = 0&#60;br&#62;            Local randomvalue = Rand(0, 100)&#60;br&#62;            If randomvalue &#62; 95&#60;br&#62;                Local borderPos:TCoordinate = GetRandomBorderPos()&#60;br&#62;                Local dirToPlayer:TCoordinate = borderPos.GetDirection(playerPos)&#60;br&#62;                TEnemy.Create(borderPos, dirToPlayer, defaultspeed)&#60;br&#62;            End If&#60;br&#62;        End If&#60;br&#62;&#60;br&#62;        For Local enemy:TEnemy = EachIn allEnemies&#60;br&#62;            enemy.Update(fixedRate)&#60;br&#62;        Next&#60;br&#62;    End Function&#60;br&#62;    &#60;br&#62;    Function GetRandomBorderPos:TCoordinate()&#60;br&#62;        Local border:Int = Rand(1, 4)&#60;br&#62;        Local pos:TCoordinate, xp:Int, yy:Int&#60;br&#62;        &#60;br&#62;        Select border&#60;br&#62;            Case 1 &#39;from the top&#60;br&#62;                yp = 0&#60;br&#62;                xp = Rand(0, GraphicsWidth() - 40)&#60;br&#62;            Case 2 &#39;from below&#60;br&#62;                yp = GraphicsHeight()&#60;br&#62;                xp = Rand(0, GraphicsWidth() - 40)&#60;br&#62;            Case 3 &#39; from the left&#60;br&#62;                xp = 0&#60;br&#62;                yp = Rand(0, GraphicsHeight() - 40)&#60;br&#62;            Case 4 &#39; from the right&#60;br&#62;                xp = GraphicsWidth()&#60;br&#62;                yp = Rand(0, GraphicsHeight() - 40)&#60;br&#62;        End Select&#60;br&#62;        pos = TCoordinate.Create(xp, yp, 0)&#60;br&#62;        Return pos&#60;br&#62;    End Function&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Function RenderAllEnemies(tween:Float)&#60;br&#62;        For Local enemy:TEnemy = EachIn allEnemies&#60;br&#62;            enemy.Render(tween)&#60;br&#62;        Next&#60;br&#62;        &#39; DrawText &#34;Nr of enemies &#34; + allEnemies.Count(), 10, 430&#60;br&#62;    End Function&#60;br&#62;        &#60;br&#62;End Type&#60;br&#62;%CODE_END%&#60;br&#62;&#60;br&#62;Because of inheritance and usage we import the obvious files. &#60;b&#62;TBullet.bmx&#60;/b&#62; is imported because we want to check for collisions later on so we&#39;d better know about bullets.&#60;br&#62;Similar to the &#60;b&#62;TBullet&#60;/b&#62;s we have some globals for the enemy image, the default speed and the list of all enemies on screen.&#60;br&#62;Additionally we need some globals because the enemy is an animated one and we need to store information about the number of animation frames and the step amount we&#39;ll use to find the next frame image.&#60;br&#62;Of course each instance of &#60;b&#62;TEnemy&#60;/b&#62; needs to have it&#39;s own direction, speed and the current frame that is displayed so those are fields of the type.&#60;br&#62;&#60;br&#62;Let&#39;s have a look at the functions and methods:&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; &#60;b&#62;Create:TEnemy(pos:TCoordinate, direction:TCoordinate, speed:Float)&#60;/b&#62; Nothing special here; allocating and initializing a new &#60;b&#62;TEnemy&#60;/b&#62; instance and adding it to the global list of all enemies (&#60;b&#62;allEnemies&#60;/b&#62;)&#60;/li&#62;&#60;li&#62; &#60;b&#62;Update(fixedRate:Float)&#60;/b&#62; Here we move the enemy instance based on it&#39;s speed. Then we check if the next animation frame needs to be shown. We traverse the animation array back and forth to get a proper animation sequence. Afterwards we check for collisions with bullets. To do so we get the list of all bullets and check each bullet against the current frame of our enemy using the BlitzMax builtin function &#60;b&#62;ImagesCollide()&#60;/b&#62;. If we have a collision we mark the enemy and the bullet as dead so that they will be removed in their &#60;b&#62;Update&#60;/b&#62; methods. Finally we check if the enemy left the screen or was marked as dead. If that&#39;s the case we remove it from the global list.&#60;/li&#62;&#60;li&#62; &#60;b&#62;Render(tween:Float)&#60;/b&#62; As usual: setting proper rotation of the enemy image, calculating tweened position and drawing of the current animation frame of the enemy instance. Easy going.&#60;/li&#62;&#60;li&#62; &#60;b&#62;UpdateAllEnemies(fixedRate:Float, playerPos:TCoordinate)&#60;/b&#62; The convenience function not only traverses the global list and calls &#60;b&#62;Update()&#60;/b&#62; for each enemy, it also generates a new enemy if the list of enemies is empty.&#60;/li&#62;&#60;li&#62; &#60;b&#62;GetRandomBorderPos:TCoordinate()&#60;/b&#62; This is the function that helps to find a random start position for a new enemy. First a random value between 1 and 4 is created to decide on which border of the screen the enemy shall appear. Then we randomly generate the second missing coordinate value to decide where on the selected border the enemy should appear. The randomly generated coordinate is returned.&#60;/li&#62;&#60;li&#62; &#60;b&#62;RenderAllEnemies(tween:Float)&#60;/b&#62; Call &#60;b&#62;Render()&#60;/b&#62; for all enemy instances to have them drawn.&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;So even if the &#60;b&#62;TEnemy&#60;/b&#62; is the biggest type currently it&#39;s not too complicated.&#60;br&#62;&#60;br&#62;Let&#39;s have a look at the modified &#60;b&#62;TPlayer&#60;/b&#62; where we teach the player to shoot.</description>
  <link>http://www.haaks.net/tdstutorialpart2/index.html#tds204</link>
  <guid isPermaLink="true">http://www.haaks.net/tdstutorialpart2/index.html#tds204</guid>
  <category>Top down shooter tutorial with BlitzMax, part 2</category>
</item>
<item>
  <title>Shoot &#39;em up!</title>
  <description>Let&#39;s start with the complete &#60;b&#62;TPlayer.bmx&#60;/b&#62; file:&#60;br&#62;&#60;br&#62;%CODE_BEGIN%&#60;br&#62;rem&#60;br&#62;    bbdoc: Type description&#60;br&#62;end rem&#60;br&#62;&#60;br&#62;Import &#34;TGameElement.bmx&#34;&#60;br&#62;Import &#34;TCoordinate.bmx&#34;&#60;br&#62;Import &#34;TBullet.bmx&#34;&#60;br&#62;&#60;br&#62;Incbin &#34;gfx/turret.png&#34;&#60;br&#62;&#60;br&#62;Type TPlayer Extends TGameElement&#60;br&#62;    Global playerImg:TImage&#60;br&#62;    &#60;br&#62;    Field dir:TCoordinate&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Function Create:TPlayer(pos:TCoordinate)&#60;br&#62;        Local player:TPlayer = New TPlayer&#60;br&#62;        player.pos = pos&#60;br&#62;        player.oldPos = TCoordinate.Copy(pos)&#60;br&#62;        If playerImg = Null&#60;br&#62;            playerImg = LoadImage(&#34;incbin::gfx/turret.png&#34;)&#60;br&#62;        End If&#60;br&#62;        Return player&#60;br&#62;    End Function&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Method Update(fixedRate:Float)&#60;br&#62;        Local mousePos:TCoordinate&#60;br&#62;        mousePos = TCoordinate.Create(MouseX(), MouseY(), 0)&#60;br&#62;        &#39; let&#39;s rotate to always look at the mouse&#60;br&#62;        Self.oldAngle = Self.angle&#60;br&#62;        Self.angle = pos.getAngle(mousePos)&#60;br&#62;        Self.dir = Self.pos.GetDirection(mousePos)&#60;br&#62;        If MouseHit(1)&#60;br&#62;            &#39;create a bullet&#60;br&#62;            TBullet.Create(Self.pos, TCoordinate.Copy(self.dir), TBullet.defaultspeed)&#60;br&#62;        End If&#60;br&#62;    End Method&#60;br&#62;&#60;br&#62;        &#60;br&#62;    Method Render(tween:Float)&#60;br&#62;        SetRotation(self.angle)&#60;br&#62;        DrawImage(playerImg, pos.x, pos.y)&#60;br&#62;        SetRotation(0)&#60;br&#62;        rem&#60;br&#62;        If dir &#60;&#62; Null&#60;br&#62;            DrawText (&#34;angle: &#34; + dir.angle, 0, 100)&#60;br&#62;            DrawText (&#34;x dir: &#34; + dir.x, 0, 120)&#60;br&#62;            DrawText (&#34;y dir: &#34; + dir.y, 0, 140)&#60;br&#62;        EndIf&#60;br&#62;        end rem&#60;br&#62;    End Method&#60;br&#62;End Type&#60;br&#62;%CODE_END% &#60;br&#62;What&#39;s new now?&#60;br&#62;The &#60;b&#62;Import&#60;/b&#62; of &#60;b&#62;TBullet.bmx&#60;/b&#62; is required because the player needs to know about bullets if he is ever going to shoot, right? No bullets, no shooting. Yo mama.&#60;br&#62;&#60;br&#62;A field named &#60;b&#62;dir&#60;/b&#62; is also new. It will be used to calculate the direction from the player&#39;s position to the mouse cursor position. Because that is not only the direction we&#39;re looking at but also the direction we want to shoot. And that&#39;s what the &#60;b&#62;Create&#60;/b&#62; method of the bullet needs!&#60;br&#62;&#60;br&#62;The &#60;b&#62;Update()&#60;/b&#62; method is changed of course. We&#39;re constantly tracking the current mouse position and storing it in some &#60;b&#62;TCoordinate&#60;/b&#62; instance named &#60;b&#62;mousePos&#60;/b&#62;. If the left mouse button is pressed we create a new &#60;b&#62;TBullet&#60;/b&#62; instance that moves into the direction from the player to the mouse cursor.&#60;br&#62;&#60;br&#62;The &#60;b&#62;Render()&#60;/b&#62; method didn&#39;t change at all except the new lines of code between the lines &#60;b&#62;rem&#60;/b&#62; and &#60;b&#62;end rem&#60;/b&#62;. Those were only included for debugging to keep track of the changing direction that&#39;s following the mouse cursor. You can safely ignore and delete those lines, including the &#60;b&#62;rem&#60;/b&#62; and &#60;b&#62;end rem&#60;/b&#62; lines.&#60;br&#62;&#60;br&#62;Done with the player. There&#39;s only one thing left, the updated &#60;b&#62;ComeGetMe.bmx&#60;/b&#62; that glues everything together. Let&#39;s finish it.&#60;br&#62;&#60;b&#62; TO BE CONTINUED WHEN I&#39;M AWAKE AGAIN &#60;/b&#62; &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;</description>
  <link>http://www.haaks.net/tdstutorialpart2/index.html#tds205</link>
  <guid isPermaLink="true">http://www.haaks.net/tdstutorialpart2/index.html#tds205</guid>
  <category>Top down shooter tutorial with BlitzMax, part 2</category>
</item>
<item>
  <title>All together now!</title>
  <description>&#60;b&#62;ComeGetMe.bmx&#60;/b&#62; contains a few changes to let everything work together: the player, the enemies and the bullets.&#60;br&#62;&#60;br&#62;Again, let&#39;s first look at the complete source code:&#60;br&#62;%CODE_BEGIN%&#60;br&#62;SuperStrict&#60;br&#62;&#60;br&#62;Import &#34;TFRLTimer.bmx&#34;&#60;br&#62;Import &#34;TPlayer.bmx&#34;&#60;br&#62;Import &#34;TBullet.bmx&#34;&#60;br&#62;Import &#34;TEnemy.bmx&#34;&#60;br&#62;&#60;br&#62;AppTitle = &#34;BlitzMax Top down shooter tutorial&#34;&#60;br&#62;&#60;br&#62;Const GFX_WIDTH:Int = 640, GFX_HEIGHT:Int = 480&#60;br&#62;&#60;br&#62;Const UPDATE_FREQUENCY:Float = 100.0, SPIKE_SUPPRESSION:Int = 20&#60;br&#62;&#60;br&#62;Global gameTime:TFRLTimer = New TFRLTimer.CreateFRL(UPDATE_FREQUENCY, SPIKE_SUPPRESSION)        &#39;1st number is logic updates per second and 2nd number is how much spike suppression you want&#60;br&#62;&#60;br&#62;Global player:TPlayer = TPlayer.Create(TCoordinate.Create(GFX_WIDTH / 2, GFX_HEIGHT / 2, 0))&#60;br&#62;&#60;br&#62;&#60;br&#62;Graphics GFX_WIDTH, GFX_HEIGHT, 0&#60;br&#62;&#60;br&#62;SetBlend ALPHABLEND&#60;br&#62;&#60;br&#62;AutoMidHandle(True)&#60;br&#62;&#60;br&#62;SeedRnd MilliSecs()&#60;br&#62;&#60;br&#62;&#60;br&#62;SetClsColor(200, 100, 100)&#60;br&#62;&#60;br&#62;&#39; the main loop starts here&#60;br&#62;While Not KeyDown(KEY_ESCAPE) And AppTerminate() = False&#60;br&#62;    Cls&#60;br&#62;    &#60;br&#62;&#60;br&#62;    &#39; update part of the main loop with constant speed&#60;br&#62;    Local delta:Float = gameTime.ProcessTime()&#60;br&#62;    While gameTime.LogicUpdateRequired()&#60;br&#62;        DoGameLogic(gameTime.GetLogicFPS())             &#39;Update Game Logic Here&#60;br&#62;    Wend&#60;br&#62;    &#60;br&#62;    &#39; rendering with additional tweening    &#60;br&#62;    Local tween:Float = gameTime.GetTween()         &#39;calc the tween for smooth graphics&#60;br&#62;    doGameRender(tween)                             &#39;Render Game Here&#60;br&#62;    &#60;br&#62;    Flip 0                                          &#39; synchronize graphics buffer as soon as possible&#60;br&#62;Wend&#60;br&#62;EndGraphics&#60;br&#62;End&#60;br&#62;&#60;br&#62;&#60;br&#62;Function DoGameLogic(fixedRate:Float)&#60;br&#62;    player.Update(fixedRate)&#60;br&#62;    TEnemy.UpdateAllEnemies(fixedRate, player.pos)&#60;br&#62;    TBullet.UpdateAllBullets(fixedRate)&#60;br&#62;End Function&#60;br&#62;&#60;br&#62;Function DoGameRender(tween:Float)&#60;br&#62;    player.Render(tween)&#60;br&#62;    TEnemy.RenderAllEnemies(tween)&#60;br&#62;    TBullet.RenderAllBullets(tween)&#60;br&#62;    gameTime.ShowFPS(0, 0)&#60;br&#62;End Function&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;Of course we need to update our list of &#60;b&#62;Import&#60;/b&#62;s, we add &#60;b&#62;TBullet.bmx&#60;/b&#62; and &#60;b&#62;TEnemy.bmx&#60;/b&#62;.&#60;br&#62;&#60;br&#62;The &#60;b&#62;AppTitle&#60;/b&#62; is a global variable that is used at some places internally by BlitzMax and allows us to set the name of our game into the title bar of the game&#39;s window. Cool!&#60;br&#62;%CODE_BEGIN% &#60;br&#62;AppTitle = &#34;BlitzMax Top down shooter tutorial&#34;&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;Another line is important for games:&#60;br&#62;%CODE_BEGIN% &#60;br&#62;SeedRnd MilliSecs()&#60;br&#62;%CODE_END% &#60;br&#62;The random numbers that a BlitzMax application (and any other application too) is based on a very long sequence of random values. Whenever you call &#60;b&#62;rnd()&#60;/b&#62; it returns the next value of this sequence.&#60;br&#62;The command &#60;b&#62;SeedRnd&#60;/b&#62; allows you to initialize the start position of this sequence with any value. A good one is the current time in milliseconds (&#60;b&#62;MilliSecs()&#60;/b&#62;) as it is different whenever you start the game. This makes it look like the game really behaves &#60;i&#62;randomly&#60;/i&#62;.&#60;br&#62;&#60;br&#62;The new line&#60;br&#62;%CODE_BEGIN% &#60;br&#62;SetClsColor(200, 100, 100)&#60;br&#62;%CODE_END% &#60;br&#62;is another builtin function of BlitzMax and tells BlitzMax what color to use whenever you call &#60;b&#62;Cls&#60;/b&#62; to clear (and fill) the screen. The default color is black (0,0,0) and we set it to some terrible orange/pink/whatever color to see the enemies better. Change this to a value you can bear &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;The last code change is in these two functions:&#60;br&#62;%CODE_BEGIN% &#60;br&#62;Function DoGameLogic(fixedRate:Float)&#60;br&#62;    player.Update(fixedRate)&#60;br&#62;    TEnemy.UpdateAllEnemies(fixedRate, player.pos)&#60;br&#62;    TBullet.UpdateAllBullets(fixedRate)&#60;br&#62;End Function&#60;br&#62;&#60;br&#62;Function DoGameRender(tween:Float)&#60;br&#62;    player.Render(tween)&#60;br&#62;    TEnemy.RenderAllEnemies(tween)&#60;br&#62;    TBullet.RenderAllBullets(tween)&#60;br&#62;    gameTime.ShowFPS(0, 0)&#60;br&#62;End Function&#60;br&#62;%CODE_END% &#60;br&#62;&#60;br&#62;In &#60;b&#62;DoGameLogic()&#60;/b&#62; we added the functions to update all enemies and all bullets and in &#60;b&#62;DoGameRender()&#60;/b&#62; we added the similar stuff to render all enemies and all bullets.&#60;br&#62;&#60;br&#62;And that&#39;s about it.&#60;br&#62;&#60;br&#62;What is still missing?&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; Sound. Whenever the player fires a bullet we want to hear a sound. Also some explosion or hit sound would be nice when a bullet hits an enemy.&#60;/li&#62;&#60;li&#62; Some scoring would be nice and some code to deal with something like levels where the number of approaching enemies increases, the enemies become faster and so on.&#60;/li&#62;&#60;li&#62; A game over functionality to restart the game when the player is hit by an enemy and to show the current high score for example.&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;This will come next.&#60;br&#62;&#60;br&#62;But for now you can download the second part of the tutorial with all sources and graphics we&#39;ve used so far.</description>
  <link>http://www.haaks.net/tdstutorialpart2/index.html#tds206</link>
  <guid isPermaLink="true">http://www.haaks.net/tdstutorialpart2/index.html#tds206</guid>
  <category>Top down shooter tutorial with BlitzMax, part 2</category>
</item>
<item>
  <title>Enjoy the silence!</title>
  <description>Or not &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Let&#39;s add some sound effects to the game.&#60;br&#62;&#60;br&#62;&#60;b&#62;TO BE CONTINUED WHEN TIME ALLOWS AGAIN!&#60;/b&#62;</description>
  <link>http://www.haaks.net/tdstutorialpart2/index.html#tds207</link>
  <guid isPermaLink="true">http://www.haaks.net/tdstutorialpart2/index.html#tds207</guid>
  <category>Top down shooter tutorial with BlitzMax, part 2</category>
</item>
</channel>
</rss>