<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0">
<channel>
  <title>RightAngleGames</title>
  <link>http://www.rightanglegames.com</link>
  <description>Contains information about Thomas Haaks and his games.&#60;br&#62;Deals with game programming in general and PlayBasic, BlitzMax, Game Maker 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>Sun, 6 May 2012 19:50:25 GMT</pubDate>
<item>
  <title>[Website] Changes ahead?</title>
  <description>&#60;i&#62; Sunday, May 06, 2012, 9:35 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Oh, it&#39;s this time of the year again?&#60;br&#62;&#60;br&#62;Yup, I&#39;m thinking about redoing the website (again). And I&#39;m thinking about switching to Wordpress (again).&#60;br&#62;We&#39;ll see how far I come this time. A local version of &#60;a target=&#34;_blank&#34; href=&#34;http://www.wordpress.org&#34;&#62;Wordpress&#60;/a&#62; using &#60;a target=&#34;_blank&#34; href=&#34;http://www.apachefriends.org/en/index.html&#34;&#62;XAMPP&#60;/a&#62; will be installed on my laptop and I will use that to create and fill the initial Wordpress version of my site.&#60;br&#62;&#60;br&#62;And as usual I&#39;m afraid there are several reasons against Wordpress but currently I&#39;m really annoyed about the long deployment cycle of &#60;a target=&#34;_blank&#34; href=&#34;http://www.lauyan.com&#34;&#62;TOWeb&#60;/a&#62;. For every single article you have to publish the whole site. It&#39;s optimized and only updating changed stuff but still... it lasts several minutes until it&#39;s done. And I have to start an additional application to write an article (with lots of comfort I must admit) and get it published. It would be so much easier to just use the web browser and write and publish anything just instantly...&#60;br&#62;&#60;br&#62;I&#39;ll have a go with &#60;a target=&#34;_blank&#34; href=&#34;http://www.wordpress.org&#34;&#62;Wordpress&#60;/a&#62; on my local machine and depending on the (hopefully quick) progress or not I&#39;ll might decide to make the switch. One issue will be trying to keep the old content and (if possible) some of the old static URLs...&#60;br&#62;&#60;br&#62;You and me will find out.</description>
  <link>http://www.rightanglegames.com/blog/index.html#201212</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201212</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] Another competition, maybe another game?!</title>
  <description>&#60;i&#62; Sunday, May 06, 2012, 9:27 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Over at &#60;a target=&#34;_blank&#34; href=&#34;http://www.64digits.com&#34;&#62;http://www.64digits.com&#60;/a&#62; they are having a contest which started 1st of May and ends 2nd of August. It&#39;s about creating a RPG. See &#60;a target=&#34;_blank&#34; href=&#34;http://www.64digits.com/users/index.php?userid=Toast&#38;cmd=comments&#38;id=272934&#34;&#62;here&#60;/a&#62; for details. The contest is still open for joining (you need to join the forums and announce your intent in the above topic as a comment).&#60;br&#62;&#60;br&#62;I decided to give it a try, mainly because I always wanted to code a little roguelike game and second because I needed a reason to play around with Game Maker and third because it&#39;s a family friendly time span of 3 months.&#60;br&#62;&#60;br&#62;Although I planned to give libGDX a try I couldn&#39;t motivate myself. Instead I downloaded Ludum Dare 23 entries made with Game Maker, I read my two Game Maker books, I browsed the Game Maker forums and updated my Game Maker:Studio beta every time the YoYo Games guys released a new beta.&#60;br&#62;&#60;br&#62;Sigh. Seems to me like a signal. So without further ado I decided to give in to myself and have fun with Game Maker instead of forcing me to do something I obviously try to avoid for unknown reasons &#60;img src=&#34;../_frame/icon_doubt.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;For the game graphics I have something special in my mind which fits the RPG theme and the roots of RPG: pen and paper &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;More details hopefully later!</description>
  <link>http://www.rightanglegames.com/blog/index.html#201211</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201211</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev]Ludum Dare is looong over...</title>
  <description>&#60;i&#62; Sunday, May 06, 2012, 9:22 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;...but there are 1402 games for you to play &#60;img src=&#34;../_frame/icon_eek.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;Amazing, isn&#39;t it? More than 1400 games created in one weekend! What&#39;s even better is that most of the competition entries (not the jam entries which lasted one day longer) come with full source!&#60;br&#62;So should you ever think about coding games yourself (and honestly, why shouldn&#39;t you?) there&#39;s a lot of source code to learn from &#60;a target=&#34;_blank&#34; href=&#34;http://www.ludumdare.com/compo/ludum-dare-23/?action=preview&#34;&#62;right here&#60;/a&#62;!!!&#60;br&#62;&#60;br&#62;Have fun downloading and browsing the code, learn what you can and improve your knowledge!&#60;br&#62;&#60;br&#62;Oh, and don&#39;t forget to play a game in between &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62; Many of them are really worth it!&#60;br&#62;&#60;br&#62;I downloaded several Game Maker games to learn from as I intend to give Game Maker Studio a test run. See my post above.</description>
  <link>http://www.rightanglegames.com/blog/index.html#201210</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201210</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] Ludum Dare weekend!</title>
  <description>&#60;i&#62; Tuesday, April 17, 2012, 9:35 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;The next weekend (20th to 23rd of April) is &#60;a target=&#34;_blank&#34; href=&#34;http://www.ludumdare.com&#34;&#62;Ludum Dare&#60;/a&#62; again. Create a game in 48 hours (72 hours for the jam) with a given theme all on your own.&#60;br&#62;&#60;br&#62;I&#39;m afraid I won&#39;t have enough time to join the competition. So as usual I will spend a few minutes here and there and read the blogs on the Ludum Dare website or watch some time lapse videos or live webcams &#60;img src=&#34;../_frame/icon_smile.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;On the other hand I don&#39;t put myself under too much self made stress trying to create a game under bad conditions...&#60;br&#62;&#60;br&#62;But maybe &#60;b&#62;YOU&#60;/b&#62; want to jump in? It&#39;s just a few minutes for registration and off you go!&#60;br&#62;&#60;br&#62;Have fun on the &#60;a target=&#34;_blank&#34; href=&#34;http://www.ludumdare.com&#34;&#62;Ludum Dare&#60;/a&#62; competition or have a nice weekend anyway &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Later,&#60;br&#62;Tommy</description>
  <link>http://www.rightanglegames.com/blog/index.html#201209</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201209</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] Spriter on Kickstarter and libGDX</title>
  <description>&#60;i&#62; Tuesday, April 17, 2012, 9:17 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;&#60;a target=&#34;_blank&#34; href=&#34;http://www.kickstarter.com/projects/539087245/spriter&#34;&#62;Spriter&#60;/a&#62; is a 2D animation tool. It&#39;s currently a beta version and looking for funding via &#60;a target=&#34;_blank&#34; href=&#34;http://www.kickstarter.com&#34;&#62;Kickstarter&#60;/a&#62;. Because it is such a powerful tool, a great idea and a downloadable working beta as proof of concept is also available the funding of the project is already successful (at the time of writing they achieved over 40,000$ while asking for 25,000$)!&#60;br&#62;&#60;br&#62;I became a backer a few days ago and thought about asking for a libGDX (or indeed any Java) binding. Because in general the magic behind Spriter is just XML files describing the transformation of the separate sprite graphics with some timing/frame information. Nothing every game coder could create in a few weeks except the UI tool of course. A good interface does take time (that&#39;s why they are asking for funding, doh!).&#60;br&#62;But it&#39;s not too difficult to create some code that reads and interprets the XML and draws the sprite graphics accordingly. But of course I didn&#39;t want to spend the time at all - I just want to use it &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Luckily an implementation already popped up over at the libGDX forums (&#60;a target=&#34;_blank&#34; href=&#34;http://www.badlogicgames.com/forum/viewtopic.php?f=17&#38;t=3863&#34;&#62;here&#60;/a&#62;).&#60;br&#62;I think we can assume that even enhancements and extensions of the Spriter XML format will follow in short time frames now that some base code for libGDX already exists.&#60;br&#62;&#60;br&#62;Now all I need is more spare time and I can create games with my own graphics, animations and music &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;</description>
  <link>http://www.rightanglegames.com/blog/index.html#201208</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201208</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] Music creation on the fly...</title>
  <description>&#60;i&#62; Tuesday, April 17, 2012, 8:51 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Yesterday I bought  &#60;a target=&#34;_blank&#34; href=&#34;http://www.soundtrends.com/apps/gruvtron/&#34;&#62;grüvtron&#60;/a&#62; for my Android. A simple tool to create music and to have tons of fun. I commute an hour every day so I used the time in the train and gave it a little test run. Headphones on and off we go &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;The great thing is you can record your life playing! Changing notes, chords, distortion with your fingertips and save it all as a wav file.&#60;br&#62;A few minutes ago I converted my &#34;demo&#34; track to mp3 format and here it is.&#60;br&#62;&#60;br&#62;Enjoy a bit (it&#39;s not that good but as I said: it&#39;s been fun to create &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;)...&#60;br&#62;&#60;br&#62;That sounds like a great option to create music tracks for example for Ludum Dare competition games when you&#39;re in a hurry and not talented at all, like me &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;One dollar well spent!</description>
  <link>http://www.rightanglegames.com/blog/index.html#201207</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201207</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] libGDX - how did I miss that one?</title>
  <description>&#60;i&#62; Monday, April 09, 2012, 2:59 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Just a few days ago I talked with a friend about &#60;a target=&#34;_blank&#34; href=&#34;http://code.google.com/p/libgdx/&#34;&#62;libGDX&#60;/a&#62;. My memories were &#34;some Android lib for Java, also running on the desktop&#34;. But now I own an Android cell phone, I love coding games in Java and sharing the same code base for desktop and Android sounds cool (isn&#39;t that the reason why I looked at GameMaker:Studio? &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;).&#60;br&#62;&#60;br&#62;Additionally I started to follow Mario Zechner, the creator of libGDX, on Twitter. And just recently he announced that libGDX can now also create HTML5 output!&#60;br&#62;&#60;br&#62;So &#60;a target=&#34;_blank&#34; href=&#34;http://code.google.com/p/libgdx/&#34;&#62;libGDX&#60;/a&#62; offers all the features I want to have plus the coding power of Java! But libGDX contains even more:&#60;br&#62;&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; a 2D scene graph,&#60;/li&#62;&#60;li&#62; UI elements for game related GUIs (plus support for TWL and Nifty),&#60;/li&#62;&#60;li&#62; particle stuff,&#60;/li&#62;&#60;li&#62; tweening functionality,&#60;/li&#62;&#60;li&#62; 3D stuff, should I ever want to code a 3D game,&#60;/li&#62;&#60;li&#62; physics engine (Box2D) support,&#60;/li&#62;&#60;li&#62; device abstraction for settings, files and input handling&#60;/li&#62;&#60;li&#62; and more things I simply forgot &#60;img src=&#34;../_frame/icon_lol.gif&#34; border=&#34;0&#34;&#62;&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;I&#39;ll have a look at &#60;a target=&#34;_blank&#34; href=&#34;http://code.google.com/p/libgdx/&#34;&#62;libGDX&#60;/a&#62; over the next days or weeks and keep you posted! My trial project will be a port of &#60;a href=&#34;../10seconds/index.html&#34;&#62;10 seconds&#60;/a&#62; to libGDX!</description>
  <link>http://www.rightanglegames.com/blog/index.html#201206</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201206</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] GameMaker:Studio and testing on Android</title>
  <description>&#60;i&#62; Monday, March 12, 2012, 9:22 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;It works! It simply works!&#60;br&#62;&#60;br&#62;So it took me 2 minutes to configure GameMaker:Studio to use my installed Android SDK, my Java JDK and to generate a keystore file for my GameMaker games.&#60;br&#62;&#60;br&#62;Afterwards I created a little test game (just some bouncing apples in a room enclosed with walls) and hit the &#34;&#60;b&#62;Run&#60;/b&#62;&#34; button. GameMaker:Studio started compiling and deployed the game to my Android phone which was running with USB debugging enabled and connected via cable.&#60;br&#62;&#60;br&#62;Just seconds later I could &#34;play&#34; this little test game. Even changing orientation of my phone worked.&#60;br&#62;&#60;br&#62;Now that&#39;s what I call a great beta test &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Hopefully the &#60;a target=&#34;_blank&#34; href=&#34;http://www.yoyogames.com&#34;&#62;YoYo Games&#60;/a&#62; guys decide to offer some discount for early adopters - otherwise I&#39;ll have to wait a bit longer until I can spend the 200$ for the Android module...&#60;br&#62;&#60;br&#62;But honestly, this is a pretty cool 2D cross platform development tool. Hats off, &#60;a target=&#34;_blank&#34; href=&#34;http://www.yoyogames.com&#34;&#62;YoYo Games&#60;/a&#62;!</description>
  <link>http://www.rightanglegames.com/blog/index.html#201205</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201205</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Real life] Is this site dead or what???</title>
  <description>&#60;i&#62; Sunday, March 11, 2012, 8:04 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Nope, obviously it&#39;s not. But to be honest, real life kept me busy over the last few months and still does. And some things are simply more important than updating a website &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;But today I spent some time and wrote a few things up. Hopefully you won&#39;t have to wait this long until the next update!&#60;br&#62;&#60;br&#62;Have fun,&#60;br&#62;Tommy</description>
  <link>http://www.rightanglegames.com/blog/index.html#201204</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201204</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] Unity for iOS and Android - free for a while</title>
  <description>&#60;i&#62; Sunday, March 11, 2012, 8:04 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;If you want to develop games for Windows, Mac, Web, iOS and Android for free you couldn&#39;t do better than to jump over to &#60;a target=&#34;_blank&#34; href=&#34;http://unity3d.com/&#34;&#62;http://unity3d.com/&#60;/a&#62; and get the free version of Unity (including Windows, Mac and Web) and get the base modules for iOS and Android for free!!!&#60;br&#62;But hurry up, the offer ends at April, 8.&#60;br&#62;&#60;br&#62;Here is the direct link to the Unity store: &#60;a target=&#34;_blank&#34; href=&#34;https://store.unity3d.com/index.html&#34;&#62;https://store.unity3d.com/index.html&#60;/a&#62;. Just select the free Unity version plus the two modules and check out. A registration email containing the serial number will be sent to you.&#60;br&#62;&#60;br&#62;Have fun,&#60;br&#62;Tommy</description>
  <link>http://www.rightanglegames.com/blog/index.html#201203</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201203</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] GameMaker stuff</title>
  <description>&#60;i&#62; Sunday, March 11, 2012, 8:03 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Last year I told you that I bought GameMaker:HTML to create HTML5 games. I still haven&#39;t used it properly but it&#39;s on my hard disk &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;Recently I got an email invitation to the beta test for GameMaker:Studio.&#60;br&#62;Basically GameMaker:Studio is the generic version of GameMaker:HTML and it allows you to generate Windows and Mac executables plus HTML5, iOS and Android games if you buy the proper modules.&#60;br&#62;GameMaker:Studio without modules will cost 99$ and each module will cost 200$ (which is a bit too expensive if you&#39;d ask me).&#60;br&#62;&#60;br&#62;Luckily all purchasers of the GameMaker:HTML version (currently available for 99$ too) will get GameMaker:Studio plus the HTML5 module for free.&#60;br&#62;So if you purchase GameMaker:HTML now you&#39;ll get the improved version for free plus Mac export (Windows and HTML is already included in GameMaker:HTML).&#60;br&#62;&#60;br&#62;So currently I&#39;m trying to test the Android code generation which is enabled for a limited period in the GameMaker:Studio beta (but apk generation is not so you have to use debug tools, a wire connected Android phone and so on).&#60;br&#62;&#60;br&#62;Sounds like a simple (but not cheap) approach to get cross platform 2D game development with a really sophisticated game dev oriented IDE.&#60;br&#62;&#60;br&#62;Let&#39;s see if they keep their pricing ideas &#60;img src=&#34;../_frame/icon_doubt.gif&#34; border=&#34;0&#34;&#62;</description>
  <link>http://www.rightanglegames.com/blog/index.html#201202</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201202</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>[Game Dev] Slick development</title>
  <description>&#60;i&#62; Sunday, March 11, 2012, 7:43 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Kev Glass has moved the Slick source repository over to &#60;a target=&#34;_blank&#34; href=&#34;http://www.bitbucket.org&#34;&#62;http://www.bitbucket.org&#60;/a&#62; and passed the development responsibility over to several guys that want to help improve &#60;a target=&#34;_blank&#34; href=&#34;http://slick.cokeandcode.com/&#34;&#62;Slick&#60;/a&#62;.&#60;br&#62;&#60;br&#62;After some organizing and hickups the team has now started working on fixing bugs and adding features into a develoment branch on bitbucket. The plan is to regularly update the master/default branch with the stable results from the development branch. Currently scheduled time frame is once a month. We&#39;ll see how that plan works out &#60;img src=&#34;../_frame/icon_wink.gif&#34; border=&#34;0&#34;&#62;</description>
  <link>http://www.rightanglegames.com/blog/index.html#201201</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#201201</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;li&#62; &#60;a target=&#34;_blank&#34; href=&#34;https://github.com/Gornova/MarteEngine&#34;&#62;Marte Engine&#60;/a&#62;, a Flashpunk and Game Maker inspired extension library for Slick where I am a co-developer&#60;/li&#62;&#60;/ul&#62;&#60;br&#62;</description>
  <link>http://www.rightanglegames.com/blog/index.html#bv000055</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#bv000055</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>Twitter</title>
  <description>%TWITTER% </description>
  <link>http://www.rightanglegames.com/blog/index.html#bv000064</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#bv000064</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>Other game developers</title>
  <description>&#60;ul id=&#34;s2h&#34;&#62;&#60;li&#62; &#60;a target=&#34;_blank&#34; href=&#34;http://www.cokeandcode.com&#34;&#62;Kevin Glass (Slick)&#60;/a&#62;&#60;/li&#62;&#60;li&#62; &#60;a target=&#34;_blank&#34; href=&#34;http://randomtower.blogspot.com&#34;&#62;Gornova&#39;s blog&#60;/a&#62;&#60;/li&#62;&#60;li&#62; &#60;a target=&#34;_blank&#34; href=&#34;http://games.code4life.de/&#34;&#62;TheMatrix154&#60;/a&#62;&#60;/li&#62;&#60;li&#62; &#60;a target=&#34;_blank&#34; href=&#34;http://www.angryoctopus.co.nz&#34;&#62;Angry Octopus&#60;/a&#62;&#60;/li&#62;&#60;li&#62; &#60;a target=&#34;_blank&#34; href=&#34;http://www.anotherearlymorning.com&#34;&#62;Another early morning&#60;/a&#62;&#60;/li&#62;&#60;/ul&#62;</description>
  <link>http://www.rightanglegames.com/blog/index.html#bv000031</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#bv000031</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>Blog Archives</title>
  <description>&#60;a href=&#34;../blogarchive2011/index.html&#34;&#62;Blog Archive 2011&#60;/a&#62;&#60;br&#62;&#60;a href=&#34;../home1/index.html&#34;&#62;Blog Archive 2010&#60;/a&#62;&#60;br&#62;&#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.rightanglegames.com/blog/index.html#bv000001</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/blog/index.html#bv000008</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/blog/index.html#bv000005</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/blog/index.html#bv000003</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/blog/index.html#bv000003</guid>
  <category>What&#39;s going on?</category>
</item>
<item>
  <title>This year I made 151!</title>
  <description>&#60;i&#62; Tuesday, December 28, 2010, 10:42 PM &#60;/i&#62;&#60;br&#62;&#60;br&#62;Oh boy, one year gone and no other posts on this topic. Sigh. Am I not improving? Sure I am. But it was all private stuff that I don&#39;t want to post here &#60;img src=&#34;../_frame/icon_cool.gif&#34; border=&#34;0&#34;&#62;&#60;br&#62;&#60;br&#62;Instead you can read about my 2010 &#34;ride my bike to work&#34; record: It&#39;s 151 days! Given the tough last winter and the early winter this year it&#39;s not too bad! And I had a longer vacation this year so there&#39;s no reason to moan about.&#60;br&#62;&#60;br&#62;But I think I will try to get back to my 2009 record in 2011. Let&#39;s see if I can manage that!</description>
  <link>http://www.rightanglegames.com/gettingbetter/index.html#bv000018</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/gettingbetter/index.html#bv000018</guid>
  <category>Getting better - tips and links to improve one&#39;s life</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.rightanglegames.com/gettingbetter/index.html#bv000017</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#bv000016</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better15</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better14</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better13</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better12</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better11</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better10</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better09</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better08</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better07</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better06</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better05</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better04</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better03</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better02</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/gettingbetter/index.html#better01</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds116</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds115</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds114</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#mainloop</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds112</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds111</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds110</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds109</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds108</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#baseclass</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds106</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds105</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds104</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds103</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#tds102</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/topdownshootertu/index.html#downloadpartone</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/tdstutorialpart2/index.html#tds201</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/tdstutorialpart2/index.html#tds202</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/tdstutorialpart2/index.html#tds203</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/tdstutorialpart2/index.html#tds204</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/tdstutorialpart2/index.html#tds205</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/tdstutorialpart2/index.html#tds206</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/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.rightanglegames.com/tdstutorialpart2/index.html#tds207</link>
  <guid isPermaLink="true">http://www.rightanglegames.com/tdstutorialpart2/index.html#tds207</guid>
  <category>Top down shooter tutorial with BlitzMax, part 2</category>
</item>
</channel>
</rss>
