<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5955792218658139168</id><updated>2012-02-16T07:28:03.757-08:00</updated><category term='roguelike'/><category term='mrpas'/><category term='platfomer'/><category term='platform hack'/><category term='bosses'/><category term='xna'/><category term='cover art'/><category term='world map'/><category term='platformer'/><category term='grapple hook'/><category term='dbp'/><category term='minimaps'/><category term='platormer'/><category term='acknowledgements'/><category term='boss fights'/><category term='gamedev'/><category term='xblig'/><category term='super metroid'/><category term='optimization'/><category term='trailer'/><category term='maze generation'/><category term='design'/><category term='xbox'/><category term='sprites'/><category term='zombie bash'/><title type='text'>Platform Hack</title><subtitle type='html'>Platform Hack is a game in development using XNA, for release on XBox 360 Indie Game Channel.  This blog will explore various concepts and algorithms used to build the game.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>38</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-5882080397657723953</id><published>2012-01-25T10:36:00.001-08:00</published><updated>2012-01-25T10:37:27.424-08:00</updated><title type='text'>Whats next for Platform Hack?</title><content type='html'>&lt;br /&gt;This site has been quiet for a while, but it doesn't mean Platform Hack development has ceased. &amp;nbsp;An update of the game is in the works! &lt;br /&gt;&lt;br /&gt;With Platform Hack 2.0, we're looking to make some big improvements to the game. &amp;nbsp;Lots of the frustration with the later levels will be cut down. &amp;nbsp;Some of the abilities will be tweaked and re-balanced. &amp;nbsp;No more dead-end advancement (you'll be able to beat every level with any set of skills). &amp;nbsp;Tons of little bugs will be fixed. &amp;nbsp;And best of all, we'll be releasing for both PC and XBox Live!&lt;br /&gt;&lt;br /&gt;Stay tuned for more updates in the near future!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-5882080397657723953?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/5882080397657723953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2012/01/whats-next-for-platform-hack.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5882080397657723953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5882080397657723953'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2012/01/whats-next-for-platform-hack.html' title='Whats next for Platform Hack?'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-588813041753061685</id><published>2011-10-24T14:43:00.000-07:00</published><updated>2011-10-24T14:43:51.402-07:00</updated><title type='text'>Tough Jumps!</title><content type='html'>Some people have mentioned they got frustrated with various jumps in the game.  I decided to put up a video that shows how to beat these jumps, with a various mix of skills.  In general, Wall Jump + Grapple Hook is all you need to get around the game world.  Triple Jump makes things a bit easier.  You don't ever actually need Power Jump, though it makes both of these keys trivial.&lt;br /&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/dlXnN0D6r3U" width="560"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-588813041753061685?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/588813041753061685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/10/some-people-have-mentioned-they-got.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/588813041753061685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/588813041753061685'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/10/some-people-have-mentioned-they-got.html' title='Tough Jumps!'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/dlXnN0D6r3U/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-4257645912342568746</id><published>2011-10-24T14:38:00.000-07:00</published><updated>2011-10-24T14:39:10.817-07:00</updated><title type='text'>Reviews</title><content type='html'>Reviews are coming in for Platform Hack. &amp;nbsp;Not all are glowing, or even positive, but hey, that's what you get for releasing something out into the wide world! &amp;nbsp;Thanks for spending your time to review my game!&lt;br /&gt;&lt;br /&gt;I was surprised by how hard most people found the game. Although I was happy that at least two reviewers completed the game before posting their writeups. &amp;nbsp;For those who got frustrated on tough jumps, maybe I'll post some videos on how to beat those spots. &amp;nbsp;I assure, the entire game can be beaten, although certain skills may be necessary.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;"As with most of my Indie purchases, this was an impulse buy. After all, priced at a dollar, even if it’s bad, you’re still getting your money’s worth. Thankfully, Platform Hack is not bad, it’s actually pretty fun. It has a good mix of RPG, action and platforming. It’s a decent length, with a wide variety of levels and enemies. Overall, it’s a pretty dang good deal for 80 Microsoft points."&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="http://gamepadsdown.com/2011/10/20/indier-than-thou-platform-hack/"&gt;-Gamepads Down&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;"'Platform Hack' is a 2D hack 'n slash RPG platformer. It has it's own unique look with hand drawn artwork/features as wells as a some very involved gameplay mechanics... &amp;nbsp;I actually found myself cussing a times due to the difficulty of the levels, and the boss battles. It is all managable, but it definitely got a bit nerve racking at times."&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="http://otakudgamereviews.blogspot.com/2011/10/platform-hack-xblig-2d-hack-n-slashrpg.html#more"&gt;-OtakuDante's Gaming Inferno&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;"So when a title pops up offering platforming, shooting/fighting all in one package my brain says give it a try and spend the MS Points"&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="http://eff-bee-eye.de/2011/10/24/platform-hack-review-xbox-indie-games-80-msft-points/"&gt;-Eff Bee Eye&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;"The craziest thing about this review is that I can’t answer why I played all the way through it. &amp;nbsp;I could name many better games that I didn’t put this much time into. &amp;nbsp;There is at least some quality to [Platform] Hack, &amp;nbsp;but I am a pretty big sucker for level-ups."&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="http://www.extraguy.com/2011/10/platform-hack-review-hack-and-trash/"&gt;-Extra Guy&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;"Once you get to the actual game, it’s a hacky-slashy platformer. &amp;nbsp;I never would have guessed by the name."&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href="http://indiegamerchick.com/2011/10/22/platform-hack/"&gt;-Indie Gamer Chick&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-4257645912342568746?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/4257645912342568746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/10/reviews.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4257645912342568746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4257645912342568746'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/10/reviews.html' title='Reviews'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-4208204638376977591</id><published>2011-10-19T07:59:00.000-07:00</published><updated>2011-10-19T07:59:52.715-07:00</updated><title type='text'>Platform Hack Released!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-yF8CCotRdLo/Tp7lbmMVTEI/AAAAAAAAEak/CxIZpSS7YoA/s1600/PHRainbow.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-yF8CCotRdLo/Tp7lbmMVTEI/AAAAAAAAEak/CxIZpSS7YoA/s1600/PHRainbow.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Platform Hack is out on XBox Live! &amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://marketplace.xbox.com/en-US/Product/Platform-Hack/66acd000-77fe-1000-9115-d802585509a3"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;http://marketplace.xbox.com/en-US/Product/Platform-Hack&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Check it out now!&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Free Trail&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;$1 for the Full Game&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-4208204638376977591?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/4208204638376977591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/10/platform-hack-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4208204638376977591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4208204638376977591'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/10/platform-hack-released.html' title='Platform Hack Released!'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-yF8CCotRdLo/Tp7lbmMVTEI/AAAAAAAAEak/CxIZpSS7YoA/s72-c/PHRainbow.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-1488567155564039738</id><published>2011-09-26T15:59:00.000-07:00</published><updated>2011-09-26T15:59:55.477-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='trailer'/><category scheme='http://www.blogger.com/atom/ns#' term='xblig'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='xbox'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Platform Hack Trailer</title><content type='html'>&lt;iframe width="640" height="360" src="http://www.youtube.com/embed/1Rh_rZ05jI8?rel=0" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-1488567155564039738?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/1488567155564039738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/09/platform-hack-trailer.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1488567155564039738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1488567155564039738'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/09/platform-hack-trailer.html' title='Platform Hack Trailer'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/1Rh_rZ05jI8/default.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-9133775695864426033</id><published>2011-09-06T18:55:00.000-07:00</published><updated>2011-09-06T18:56:00.531-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gamedev'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='cover art'/><title type='text'>Cover Art!</title><content type='html'>The cover art for Platform Hack is complete and it looks great!&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-VIJEbS7-UTY/TmbOUl98InI/AAAAAAAAEXg/gEyqbLZUOcA/s1600/PlatformHackEditSmall.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-VIJEbS7-UTY/TmbOUl98InI/AAAAAAAAEXg/gEyqbLZUOcA/s1600/PlatformHackEditSmall.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Thanks to Mike D and Ena M for the great work!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In other (related) news, there have been some holdups with the playtest. &amp;nbsp;Some of the new features I built (namely the Dragon Breath) run much too slowly on the XBox. &amp;nbsp;So its back to the drawing board to increase the optimization.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's a pretty busy month for me with other things going on, but I still hope to get the playtest out soon!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-9133775695864426033?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/9133775695864426033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/09/cover-art.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/9133775695864426033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/9133775695864426033'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/09/cover-art.html' title='Cover Art!'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-VIJEbS7-UTY/TmbOUl98InI/AAAAAAAAEXg/gEyqbLZUOcA/s72-c/PlatformHackEditSmall.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-1285049248241768632</id><published>2011-08-18T20:35:00.000-07:00</published><updated>2011-08-18T20:35:43.234-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='boss fights'/><category scheme='http://www.blogger.com/atom/ns#' term='gamedev'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><title type='text'>Last Boss Woot Woot</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;Scripting done. &amp;nbsp;Just need to tune him now ;)&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-oQsAjRpP3m0/Tk3Z0ycF2hI/AAAAAAAAEVo/HYQHbPILmvc/s1600/RobotBoss.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="358" src="http://3.bp.blogspot.com/-oQsAjRpP3m0/Tk3Z0ycF2hI/AAAAAAAAEVo/HYQHbPILmvc/s640/RobotBoss.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-1285049248241768632?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/1285049248241768632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/08/last-boss-woot-woot.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1285049248241768632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1285049248241768632'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/08/last-boss-woot-woot.html' title='Last Boss Woot Woot'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-oQsAjRpP3m0/Tk3Z0ycF2hI/AAAAAAAAEVo/HYQHbPILmvc/s72-c/RobotBoss.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-5250679578536299624</id><published>2011-08-14T21:57:00.000-07:00</published><updated>2011-08-14T21:57:32.877-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Powers Preview</title><content type='html'>&lt;b&gt;Power-Ups&lt;/b&gt; are coming together! &amp;nbsp;The powers are selected when a player gains a new level, and are split into three "trees" - Attack, Defend, Explore. &amp;nbsp;Here's the menu to select the powers:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-9EASrGFc62M/Tkimj67iZHI/AAAAAAAAEVE/JgvDU69NnD4/s1600/Menu.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="369" src="http://1.bp.blogspot.com/-9EASrGFc62M/Tkimj67iZHI/AAAAAAAAEVE/JgvDU69NnD4/s640/Menu.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Attack &lt;/b&gt;will contain upgrades to the sword and gun, as well as a new attack called "Power Beam". &amp;nbsp;This shoots out a beam of pure power in a short player-directed burst.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-xjYD0Ore5nU/TkimjLYQ6EI/AAAAAAAAEU4/cCMrcYZzW34/s1600/Beam.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="252" src="http://1.bp.blogspot.com/-xjYD0Ore5nU/TkimjLYQ6EI/AAAAAAAAEU4/cCMrcYZzW34/s400/Beam.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-9VbpDM56AAo/TkimkTQ_ToI/AAAAAAAAEVQ/bX-c-68pE_w/s1600/Sword.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="255" src="http://2.bp.blogspot.com/-9VbpDM56AAo/TkimkTQ_ToI/AAAAAAAAEVQ/bX-c-68pE_w/s400/Sword.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ctMStJ_evI0/TkimjmodiXI/AAAAAAAAEVA/j-UVoueA8lk/s1600/Gun.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="197" src="http://2.bp.blogspot.com/-ctMStJ_evI0/TkimjmodiXI/AAAAAAAAEVA/j-UVoueA8lk/s400/Gun.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Defend&lt;/b&gt; contains upgrades to health (double health, quad health), as well as a spherical Shield that will protect the player from attacks. &amp;nbsp;At higher levels, the shield will even do damage to enemies in range!&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-9rMpv19UPwY/TkimkHGq6UI/AAAAAAAAEVM/FeixYHT-3QM/s1600/Shield.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="234" src="http://4.bp.blogspot.com/-9rMpv19UPwY/TkimkHGq6UI/AAAAAAAAEVM/FeixYHT-3QM/s320/Shield.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The &lt;b&gt;Explore&lt;/b&gt; tree contains all the jump upgrades (double, triple, wall), the grappling hook and a new ability, called "Power Jump". &amp;nbsp;This is basically a jet pack, that lets the player "fly" anywhere in the map for short bursts.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-lHuw8mST2Bc/TkimjS018gI/AAAAAAAAEU8/fgx4xwhQ1bc/s1600/Grapple.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="272" src="http://1.bp.blogspot.com/-lHuw8mST2Bc/TkimjS018gI/AAAAAAAAEU8/fgx4xwhQ1bc/s400/Grapple.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-_5P7TNls0fc/Tkimj4ra8VI/AAAAAAAAEVI/v7EJiHJC9Ug/s1600/PowerJump.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://4.bp.blogspot.com/-_5P7TNls0fc/Tkimj4ra8VI/AAAAAAAAEVI/v7EJiHJC9Ug/s400/PowerJump.jpg" width="306" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;All powers are limited by a "mana" meter that will slowly refill over time. &amp;nbsp;Stronger powers (Power Jump, Power Beam), will drain the mana meter faster, so watch out.&lt;br /&gt;&lt;br /&gt;I'm thinking the powers will be a lot of fun, an the three different trees will give players different ways to play the game. &amp;nbsp;Of course, by the end game you'll have all the powers. &amp;nbsp;One of the keys will be tuning the enemies and maps so the game is still a challenge with the full arsenal!&lt;br /&gt;&lt;br /&gt;Still some more backend coding to wrap up, one last boss fight, then putting it all together. &amp;nbsp;Hoping to have a playtest available for both PC and XBox AppHub first week of September!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-5250679578536299624?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/5250679578536299624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/08/powers-preview.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5250679578536299624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5250679578536299624'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/08/powers-preview.html' title='Powers Preview'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-9EASrGFc62M/Tkimj67iZHI/AAAAAAAAEVE/JgvDU69NnD4/s72-c/Menu.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-2198050218820932500</id><published>2011-08-04T20:55:00.000-07:00</published><updated>2011-08-04T20:55:15.657-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='world map'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Script and Maps and Such</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;Added two new features.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;1. Scripting window.&lt;/b&gt; &amp;nbsp;This is for conveying story to the player. &amp;nbsp;When the player runs over a trigger, it pops up a "dialog" window that can be read (press A) or bypassed (press B). &amp;nbsp;Poor man's cut-scene!&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-tA-hbPm1JoI/TjtpS684xVI/AAAAAAAAEUg/T5RcH6rjA9s/s1600/ScriptWindow.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="360" src="http://4.bp.blogspot.com/-tA-hbPm1JoI/TjtpS684xVI/AAAAAAAAEUg/T5RcH6rjA9s/s640/ScriptWindow.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;b&gt;2. World Map.&lt;/b&gt; &amp;nbsp;The map will be used to select the level as you progress through the game world. &amp;nbsp;I found some great brushes on deviantart that were used to make the map:&amp;nbsp;&lt;a href="http://calthyechild.deviantart.com/art/Tolkien-style-Map-Brushes-138796530"&gt;http://calthyechild.deviantart.com/art/Tolkien-style-Map-Brushes-138796530&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-cSwsHoeFQww/TjtoOhQBI4I/AAAAAAAAEUc/WN6W2-x1UzA/s1600/WorldMap.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="362" src="http://1.bp.blogspot.com/-cSwsHoeFQww/TjtoOhQBI4I/AAAAAAAAEUc/WN6W2-x1UzA/s640/WorldMap.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The game is coming together quickly. &amp;nbsp;One more boss and the level-up / power system. &lt;br /&gt;&lt;br /&gt;Then its on to fleshing out all the levels and polishing till it shines!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-2198050218820932500?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/2198050218820932500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/08/script-and-maps-and-such.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/2198050218820932500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/2198050218820932500'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/08/script-and-maps-and-such.html' title='Script and Maps and Such'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-tA-hbPm1JoI/TjtpS684xVI/AAAAAAAAEUg/T5RcH6rjA9s/s72-c/ScriptWindow.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-6387889667269726472</id><published>2011-07-30T20:01:00.000-07:00</published><updated>2011-07-30T20:01:48.280-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='boss fights'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Boss Fights Delivered</title><content type='html'>End result of a day of programming, two new boss fights! &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Maru5Ix-QBU/TjTFUnvekLI/AAAAAAAAEUI/qsUVCEMqwww/s1600/DragonBossSS.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-Maru5Ix-QBU/TjTFUnvekLI/AAAAAAAAEUI/qsUVCEMqwww/s1600/DragonBossSS.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The mummy boss chases after the player and melees them on the ground. &amp;nbsp;If the player is off the ground, the mummy will cast a spell which will launch the player into the air.&lt;br /&gt;&lt;br /&gt;The dragon boss emerges from a random side of the screen and breathes fire. &amp;nbsp;Afterwards, he's vulnerable for a short time. &amp;nbsp;In between attacks, fire blocks fall from the ceiling to crush the player.&lt;br /&gt;&lt;br /&gt;Lots of fun programming behind these guys, mostly abstracting all the code written for the spider boss, and cleaning up code for "beams" - which are basically a list of vectors that can be used for collision or "drawing" lines with particle effects. &lt;br /&gt;&lt;br /&gt;&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/C96DWiZz3fg" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Next steps - a world map, and some scripting for dialog/story!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-6387889667269726472?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/6387889667269726472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/07/boss-fights-delivered.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6387889667269726472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6387889667269726472'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/07/boss-fights-delivered.html' title='Boss Fights Delivered'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-Maru5Ix-QBU/TjTFUnvekLI/AAAAAAAAEUI/qsUVCEMqwww/s72-c/DragonBossSS.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-5679296263341470960</id><published>2011-07-29T15:23:00.001-07:00</published><updated>2011-07-29T15:23:28.347-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='bosses'/><title type='text'>New Boss Design</title><content type='html'>The design doc for two new bosses! &amp;nbsp;Dragon and Mummy!&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-4Q28b8yG4QI/TjMyz4jD7RI/AAAAAAAAET8/Fssd9-G8cBM/s1600/bossPlan.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-4Q28b8yG4QI/TjMyz4jD7RI/AAAAAAAAET8/Fssd9-G8cBM/s1600/bossPlan.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-5679296263341470960?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/5679296263341470960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/07/new-boss-design.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5679296263341470960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5679296263341470960'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/07/new-boss-design.html' title='New Boss Design'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-4Q28b8yG4QI/TjMyz4jD7RI/AAAAAAAAET8/Fssd9-G8cBM/s72-c/bossPlan.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-1253512395467940758</id><published>2011-07-21T23:17:00.000-07:00</published><updated>2011-07-21T23:17:19.067-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gamedev'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><title type='text'>New Worlds!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;Desert:&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-fw5af-0M4oA/TikVkgjZbAI/AAAAAAAAESs/6zvYMEeSC3k/s1600/Desert.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="360" src="http://4.bp.blogspot.com/-fw5af-0M4oA/TikVkgjZbAI/AAAAAAAAESs/6zvYMEeSC3k/s640/Desert.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Mountain:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-ZI2rGQY58PI/TikVk53fqNI/AAAAAAAAESw/Xx624RUaKtQ/s1600/Mountain.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="360" src="http://3.bp.blogspot.com/-ZI2rGQY58PI/TikVk53fqNI/AAAAAAAAESw/Xx624RUaKtQ/s640/Mountain.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Wasteland:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-7S_DI_sbjsQ/TikVlKc7eII/AAAAAAAAES0/z4WxEWIWm54/s1600/Wasteland.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="358" src="http://3.bp.blogspot.com/-7S_DI_sbjsQ/TikVlKc7eII/AAAAAAAAES0/z4WxEWIWm54/s640/Wasteland.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-1253512395467940758?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/1253512395467940758/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/07/new-worlds.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1253512395467940758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1253512395467940758'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/07/new-worlds.html' title='New Worlds!'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-fw5af-0M4oA/TikVkgjZbAI/AAAAAAAAESs/6zvYMEeSC3k/s72-c/Desert.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-3271537102368096862</id><published>2011-07-20T22:16:00.000-07:00</published><updated>2011-07-20T22:16:11.897-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='sprites'/><title type='text'>New Baddies</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-oLzAfcuKJ4w/Tie2A1nkWPI/AAAAAAAAESg/oiIH7Ch8PGM/s1600/MonstersColored.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://3.bp.blogspot.com/-oLzAfcuKJ4w/Tie2A1nkWPI/AAAAAAAAESg/oiIH7Ch8PGM/s640/MonstersColored.jpg" width="555" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-3271537102368096862?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/3271537102368096862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/07/new-baddies.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/3271537102368096862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/3271537102368096862'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/07/new-baddies.html' title='New Baddies'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-oLzAfcuKJ4w/Tie2A1nkWPI/AAAAAAAAESg/oiIH7Ch8PGM/s72-c/MonstersColored.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-4423229014425803012</id><published>2011-06-14T14:54:00.000-07:00</published><updated>2011-06-14T14:54:16.206-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='acknowledgements'/><category scheme='http://www.blogger.com/atom/ns#' term='gamedev'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><title type='text'>Acknowledgements</title><content type='html'>&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;People:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Ena M&lt;/b&gt; - &lt;a href="http://behindtheveil.deviantart.com/"&gt;http://behindtheveil.deviantart.com/&lt;/a&gt;&lt;br /&gt;Ena is an amazing artist and she dashed off the character sprites in Platform Hack without breaking a sweat.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;b&gt;JoeRoh &lt;/b&gt;- &lt;a href="http://seedroh.blogspot.com/"&gt;http://seedroh.blogspot.com/&lt;/a&gt;&lt;br /&gt;Joe came in at the 11th hour and saved my butt - adding polish to a ton of art assets, as well as some great playtest advice. &amp;nbsp;Joe is an aspiring game designer with his own blog as well.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;b&gt;Anna D&lt;/b&gt; - &lt;a href="http://www.annadonlan.com/"&gt;http://www.annadonlan.com/&lt;/a&gt;&lt;br /&gt;Anna drew some phenomenal logos for both Daydalus Studio and Platform Hack. &amp;nbsp;She's also a talented photographer.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Visual:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Spiral Graphics Forest Tileset&lt;/b&gt; - &lt;a href="http://blog.spiralgraphics.biz/2011/01/mystery-forest-tile-set.html"&gt;http://blog.spiralgraphics.biz/2011/01/mystery-forest-tile-set.html&lt;/a&gt;&lt;br /&gt;The tileset used in game was modified from a sample tileset found here.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;b&gt;Spriters Resource&lt;/b&gt; - &lt;a href="http://www.spriters-resource.com/"&gt;http://www.spriters-resource.com/&lt;/a&gt;&lt;br /&gt;Didn't directly use any of these assets, but the various animations in the spritesheets of classic games were big inspiration.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;b&gt;Steampunk Font&lt;/b&gt; - &lt;a href="http://hannarb.deviantart.com/art/Steampunk-Font-148871949"&gt;http://hannarb.deviantart.com/art/Steampunk-Font-148871949&lt;/a&gt;&lt;br /&gt;Font used on the menus and popups. &lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Sound:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;nosoap radio&lt;/b&gt; - &lt;a href="http://www.nosoapradio.us/"&gt;http://www.nosoapradio.us/&lt;/a&gt;&lt;br /&gt;Some great video game music available here, completly free. &lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;b&gt;bfxr &lt;/b&gt;- &lt;a href="http://www.bfxr.net/"&gt;http://www.bfxr.net/&lt;/a&gt;&lt;br /&gt;Generate 8-bit sounds in the browser, then save to WAV.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;b&gt;soundbible &lt;/b&gt;- &lt;a href="http://soundbible.com/"&gt;http://soundbible.com/&lt;/a&gt;&lt;br /&gt;Lots of public domain and "open source" sound files here to use. &amp;nbsp;Anything from gun shots to bird calls.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Code:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;MRPAS &lt;/b&gt;- &lt;a href="http://www.umbrarumregnum.net/downloads/mrpas"&gt;http://www.umbrarumregnum.net/downloads/mrpas&lt;/a&gt;&lt;br /&gt;Algorithm used for the Fog of War in minimaps&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Platformer Starter Kit&lt;/b&gt; - &lt;a href="http://create.msdn.com/en-US/education/catalog/sample/platformer"&gt;http://create.msdn.com/en-US/education/catalog/sample/platformer&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;b&gt;Game State Management&lt;/b&gt; -&lt;a href="http://create.msdn.com/en-US/education/catalog/sample/game_state_management"&gt; http://create.msdn.com/en-US/education/catalog/sample/game_state_management&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;b&gt;Particle Effects&lt;/b&gt; - &lt;a href="http://create.msdn.com/en-US/education/catalog/sample/particle"&gt;http://create.msdn.com/en-US/education/catalog/sample/particle&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;b&gt;Collision Detection with Rotation&lt;/b&gt; - &lt;a href="http://create.msdn.com/en-US/education/catalog/tutorial/collision_2d_perpixel_transformed"&gt;http://create.msdn.com/en-US/education/catalog/tutorial/collision_2d_perpixel_transformed&lt;/a&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Tools:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Audacity &lt;/b&gt;- &lt;a href="http://audacity.sourceforge.net/"&gt;http://audacity.sourceforge.net&lt;/a&gt;&lt;br /&gt;Audacity is an open source sound editing suite. &amp;nbsp;It can be used to record and edit sound, and export to WAV or MP3. &amp;nbsp;I used this to record various sound effects, change the pitch or length of others, and noise.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Gimp&lt;/b&gt; - &lt;a href="http://www.gimp.org/"&gt;http://www.gimp.org/&lt;/a&gt;&lt;br /&gt;Open source Photoshop. &amp;nbsp;Used to edit pretty much all visual assets in the game, from the sprites, in-game objects, HUD and background art. &amp;nbsp;The two biggest features are the ability to work with the Alpha (transparent) layer, and split images into Grids (which is essential for lining up textures in spritesheets / animations)&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;b&gt;Camstudio &lt;/b&gt;- &lt;a href="http://camstudio.org/"&gt;http://camstudio.org/&lt;/a&gt;&lt;br /&gt;Similar to FRAPs, used to record video for playtests and trailer.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-4423229014425803012?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/4423229014425803012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/06/acknowledgements.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4423229014425803012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4423229014425803012'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/06/acknowledgements.html' title='Acknowledgements'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-7959843976434878764</id><published>2011-06-14T11:59:00.000-07:00</published><updated>2011-06-14T11:59:19.934-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gamedev'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Platform Hack Post-Mortem</title><content type='html'>&lt;span class="Apple-style-span" style="font-size: 32px; font-weight: bold;"&gt;Things That Worked&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-kKKMrXVBIKQ/Tfeuoygb5ZI/AAAAAAAAEIA/u3JGcRzevy0/s1600/PH1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/-kKKMrXVBIKQ/Tfeuoygb5ZI/AAAAAAAAEIA/u3JGcRzevy0/s400/PH1.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-size: 24px; font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;h2&gt;Stick with the Design&lt;/h2&gt;A clear design for Platform hack was laid out at the beginning: a mash-up of Metroid (platform jumping, exploratory powerups) with dynamic world creation of Roguelikes.  This was followed through from the start.  It helped to not have to change genres or styles halfway through, and the core gameplay feels very similar to what I had in mind.&lt;br /&gt;&lt;h2&gt;Prototype, Prototype, Prototype&lt;/h2&gt;Breaking the challenges of the game into smaller problems, and then getting those working in isolated environments was key.  The main issues - grappling hook, double/wall jump, traps, melee / ranged combat, level design - were all handled in a "sandbox" project.  This way I didn't have to worry about breaking the game to try out a new feature, I could hardcode physics constants or whatever until the feature worked how I wanted it.  *then* port it over to the game project.&lt;br /&gt;&lt;h2&gt;Don't Reinvent the Wheel &lt;/h2&gt;Platform Hack borrowed from a lot of great sources, both for code and art.  The samples on App Hub were essential, especially the Platformer starter kit, which included the core code for tile-based levels, basic physics (jumping, gravity), sprite-based animation, and collision detection.  Other samples were useful as well - Game State Management, Pixel-Based collision with rotation.  For the sprites, I ended up using sample spritesheets and having my artist base all the animations (run, jump, attack, die) on those models.&lt;br /&gt;&lt;h2&gt;Limit Features...For Now&lt;/h2&gt;The original plan for platform hack had dozens of procedurally generated levels, 4 huge boss fights, an overarching story, and a leveling system that let the player specialize in different types of powers.  Those plans are still on the table for the final release, but about a month out from the deadline, I realized I wasn't going to hit all those marks, and set my sights for a much smaller goal - a stable game with polished art and gameplay.  In the end, I was able to deliver by the deadline.&lt;br /&gt;&lt;h1&gt;Things that Caused Problems&lt;/h1&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-8lFusgIybCE/Tfeuskb7F3I/AAAAAAAAEIE/RXfHaDP95SM/s1600/PH2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="168" src="http://3.bp.blogspot.com/-8lFusgIybCE/Tfeuskb7F3I/AAAAAAAAEIE/RXfHaDP95SM/s640/PH2.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2&gt;Collision Detection&lt;/h2&gt;Pixel based collision detection can make you want to tear your eyes out.  When it doesn't work, it’s very hard to figure out why (you can't step into and iterate through the 10000 item color array to see a certain pixel isn't set to alpha), especially if you are using matrix math for rotation and translation.  One thing I ended up doing was creating a TestPixel object, which would basically flip on if it was "collided" with.  This let me see a path of where swords, bullets and enemies passed through.  Unfortunately, this was very slow (1 fps) and didn't always work.  At the end of the day, I removed most of the per-pixel collision, and only used it where absolutely necessary.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Procedural Level Generation&lt;/h2&gt;I created a project that would use the Angband algorithms to generate a map, and throw in various enemies, traps and platforms.  However, I still had to manually go through the text files and make sure there were no inescapable dead ends or unreachable keys.  The tough part of procedural level generation is making sure the "maze" can be beaten, once you start adding in locked doors.  The early levels also needed additional manual intervention, to give the whole thing a bit more flow and gradually increase the learning curve.  As soon as the player uncovers a new trick (jumping boots, grappling hook), you want to give them the opportunity to use it, which you have to manually design.  this is why I'm thinking, even in the final game, the procedural levels will only end up being 50%.  Stages where you uncover a new item, or fight a scripted boss fight, will need to be hand-crafted.&lt;br /&gt;&lt;h2&gt;Loading Assets on Xbox&lt;/h2&gt;The scripted boss fight was fun to put together, but not the most elegant solution.  The first build I ended up with dozens of 1500x1500 images that not only had to be loaded into Texture2D objects, but also read into Color arrays for pixel-based collision.  Needless to say, this caused some OutOfMemory exceptions when attempted on the XBox.  The solution was reduce the size of the image files (to 800 x 600), and then build a manifest loader that would reuse certain textures for various animation frames (the idle frame is used in almost every animation), and also only generate the Color[] on frames that needed collision.&lt;br /&gt;&lt;h2&gt;Animation State Machines&lt;/h2&gt;This is something I'm still dealing with.  Animation is one big state machine - trying to map both the player input + the world controls into a believable animation for the player to be in.  For instance, if the player is swinging his sword and then jumps, do you continue to play the first ground swing animation?  or switch over mid-swing to the jump-swing animation?  What if you can't transition halfway between animations and have to start at the beginning?  This "transition" issue was a headache to get right.  In the end, I decided that animations must be played from start to finish, and you can't start a new action while you are in the middle of one (aka start shooting while rolling, roll while swinging, etc).  Of course, the button press will usually still be registered once the animation is over and you'd start the new action immediately.  The more complex your animation state machine, the harder this problem becomes.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: 32px; font-weight: bold;"&gt;Lessons Learned&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-96uwfolh3LY/TfeuynFr7dI/AAAAAAAAEII/ljd4ZT0g7z0/s1600/PH3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="292" src="http://2.bp.blogspot.com/-96uwfolh3LY/TfeuynFr7dI/AAAAAAAAEII/ljd4ZT0g7z0/s640/PH3.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-size: 24px; font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;h2&gt;Get It Working First&lt;/h2&gt;Work on the hard items early rather than low hanging fruit.  You never know how long it will take to figure out an architecture problem (loading assets, collision detection, etc).  But its usually more predictable how long it will take to import new art, or tweak small cosmetic bugs.  Leave that polish for the end, get the hard stuff working as early as possible.&lt;br /&gt;&lt;h2&gt;Art / Sound = Morale boost&lt;/h2&gt;It's a huge morale boost when you see your crappy programmer art "skinned" with graphics that look good.&lt;br /&gt;&lt;h2&gt;80/20 rule &lt;/h2&gt;There's always that last 20 percent you want to get done. &amp;nbsp;But leave 20% of your time for pure polish, not dev.&lt;br /&gt;&lt;h2&gt;Lots of builds / releases.&lt;/h2&gt;Don't leave stuff in an uncompelled / untested state at the end of the day.  During crunch time, do a daily play test.  make a list of everything wrong.  fix what you can.  increment the build number.  repeat.&lt;br /&gt;&lt;h2&gt;Make what you can / borrow what you can't.&lt;/h2&gt;I knew I'd never be able to make original music or draw convincing sprites, so I either found good assets online (free music) or got a friend to draw me sprites.  Other stuff that was less important (sound effects, in-game items) I mocked up myself using various free tools.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-7959843976434878764?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/7959843976434878764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/06/platform-hack-post-mortem.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/7959843976434878764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/7959843976434878764'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/06/platform-hack-post-mortem.html' title='Platform Hack Post-Mortem'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-kKKMrXVBIKQ/Tfeuoygb5ZI/AAAAAAAAEIA/u3JGcRzevy0/s72-c/PH1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-6562938139251324809</id><published>2011-06-13T07:24:00.000-07:00</published><updated>2011-06-13T07:24:58.980-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>What's next for Platform Hack?</title><content type='html'>The game has been submitted to Dream Build Play!  It should be showing up on the &lt;a href="https://www.dreambuildplay.com/Main/Gallery.aspx"&gt;list of entries&lt;/a&gt; shortly.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-m2eKt2gW5C8/TfYc6pQ8DtI/AAAAAAAAEH8/mcA_5x18Yq4/s1600/PHIcon.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="256" width="256" src="http://3.bp.blogspot.com/-m2eKt2gW5C8/TfYc6pQ8DtI/AAAAAAAAEH8/mcA_5x18Yq4/s400/PHIcon.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So what's next for Platform Hack?  The build submitted to DBP was a subset of what I originally envisioned.  What I'd like to do is continue working on the game, primarily creating content, for the rest of the summer.  The game would go into Peer Review late summer, and hopefully be released on XBox Live in September.&lt;br /&gt;&lt;br /&gt;Here are the features I'd like to complete for the full release:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;4 Total worlds, with unique tilesets, enemies and boss fights (Forest, Mountain, Desert, Wasteland/Factory)&lt;br /&gt;&lt;li&gt;Leveling skill-tree and powers (Attack, Defend, Explore)&lt;br /&gt;&lt;li&gt;Procedural level generation (for 50% of levels)&lt;br /&gt;&lt;li&gt;Some form of narrative story that links the "quest" together&lt;br /&gt;&lt;li&gt;Infinite mode (similar to roguelikes, where you can continue to "dig" down into the dungeon, and everything scales accordingly)&lt;br /&gt;&lt;li&gt;Overall polish of menus, HUD, etc&lt;/ul&gt;&lt;br /&gt;The only tough programming challenge is getting the procedural levels dynamic and toned enough that they can be used.  Right now I can randomly place enemies and traps, but they aren't set up in a way that makes the overall map feel both coherent and challenging.  We'll see if it's doable.&lt;br /&gt;&lt;br /&gt;Everything else is mostly content generation, which is slow and steady, but is well within reach for the summer.&lt;br /&gt;&lt;br /&gt;Next, I'll be doing a post-mortem of the DBP process, a list of acknowledgements for the game, and a breakdown of the various tools used during development.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-6562938139251324809?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/6562938139251324809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/06/game-has-been-submitted-to-dream-build.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6562938139251324809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6562938139251324809'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/06/game-has-been-submitted-to-dream-build.html' title='What&apos;s next for Platform Hack?'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-m2eKt2gW5C8/TfYc6pQ8DtI/AAAAAAAAEH8/mcA_5x18Yq4/s72-c/PHIcon.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-6311533263215342926</id><published>2011-06-11T04:53:00.001-07:00</published><updated>2011-06-11T04:53:47.027-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='dbp'/><title type='text'>Testing...</title><content type='html'>New build up on &lt;a href="http://forums.create.msdn.com/forums/t/83995.aspx"&gt;App Hub!&lt;/a&gt;  Give it a go -&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-6311533263215342926?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/6311533263215342926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/06/testing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6311533263215342926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6311533263215342926'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/06/testing.html' title='Testing...'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-4352749704960561025</id><published>2011-06-09T13:06:00.001-07:00</published><updated>2011-06-09T13:06:48.903-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='dbp'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Platform Hack Trailer</title><content type='html'>&lt;iframe width="640" height="390" src="http://www.youtube.com/embed/CSbzCoRfqY4" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;The finishing touches are being put in place!  Here's the trailer for the game.  A new playtest will be up this evening on App Hub.  I'll also be laying out the plan for the game post-DBP.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-4352749704960561025?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/4352749704960561025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/06/platform-hack-trailer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4352749704960561025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4352749704960561025'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/06/platform-hack-trailer.html' title='Platform Hack Trailer'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/CSbzCoRfqY4/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-1094088061277850667</id><published>2011-06-05T14:57:00.000-07:00</published><updated>2011-06-05T14:58:06.392-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Taking Shape...</title><content type='html'>&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/j-ez4nediV4" width="425"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Latest build - beta 1.1.  A new playtest is out on App Hub:&amp;nbsp;&lt;a href="http://catalog.create.msdn.com/en-US/GameDetails.aspx?catalogEntryId=a834c0cf-2f3a-47ff-aca2-f36e58cf6a57&amp;amp;type=1"&gt;App Hub Playtest - Platform Hack&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Big thanks to everyone who has helped out so far.  Anna D, Ena M, and Joe Roh!  Without you guys this thing would not be possible!&lt;br /&gt;&lt;br /&gt;Only 9 days left and still lots left to do -&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-1094088061277850667?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/1094088061277850667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/06/taking-shape.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1094088061277850667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1094088061277850667'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/06/taking-shape.html' title='Taking Shape...'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/j-ez4nediV4/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-5326090178397386859</id><published>2011-06-02T22:10:00.000-07:00</published><updated>2011-06-02T22:10:27.785-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='platormer'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='dbp'/><title type='text'>Playtest!</title><content type='html'>We are in playtest!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://catalog.create.msdn.com/en-US/GameDetails.aspx?catalogEntryId=ad4f5d9e-3ab8-49f0-9e96-616c741bab07&amp;amp;type=1"&gt;App Hub Playtest - Platform Hack&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-9GboZp1xc2k/Tehsl2igBdI/AAAAAAAAEHk/at2k8Rq5foQ/s1600/Boxart.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://3.bp.blogspot.com/-9GboZp1xc2k/Tehsl2igBdI/AAAAAAAAEHk/at2k8Rq5foQ/s400/Boxart.jpg" width="332" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-5326090178397386859?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/5326090178397386859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/06/playtest.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5326090178397386859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5326090178397386859'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/06/playtest.html' title='Playtest!'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-9GboZp1xc2k/Tehsl2igBdI/AAAAAAAAEHk/at2k8Rq5foQ/s72-c/Boxart.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-2159876128947053425</id><published>2011-05-29T18:02:00.000-07:00</published><updated>2011-05-29T18:02:09.415-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='dbp'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Crunch Time</title><content type='html'>&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/S_vQVRs78zA" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Things are coming together.  I've built some full levels with enemies, keys, locked doors and chests.  &lt;br /&gt;&lt;br /&gt;The XP system is also in place, so killing enemies will get XP for both the main player (HitPoints) as well as weapon (Sword, Gun) power.&lt;br /&gt;&lt;br /&gt;The game still needs tons of balance, not only with the XP and advancement system, but also the level design.&lt;br /&gt;&lt;br /&gt;And of course the graphics are pretty blugh.&lt;br /&gt;&lt;br /&gt;Hopefully I can have a playable build (that works on the XBox) in App Hub playtest by the first of June!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-2159876128947053425?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/2159876128947053425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/05/crunch-time.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/2159876128947053425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/2159876128947053425'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/05/crunch-time.html' title='Crunch Time'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/S_vQVRs78zA/default.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-4834578483054161602</id><published>2011-05-26T07:39:00.000-07:00</published><updated>2011-05-26T07:39:58.615-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='dbp'/><title type='text'>We have HUD!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-mNDev0ebx6c/Td5lx4DVnMI/AAAAAAAAEG8/BKcBztb75kg/s1600/HudSS.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="227" width="400" src="http://1.bp.blogspot.com/-mNDev0ebx6c/Td5lx4DVnMI/AAAAAAAAEG8/BKcBztb75kg/s400/HudSS.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;We have a rough HUD, with Health and XP Bar, Items, and Mini Map! &lt;br /&gt;&lt;br /&gt;Now just need to wire up everything in the game to the HUD (character level, leveling up weapons, etc).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-4834578483054161602?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/4834578483054161602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/05/we-have-hud.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4834578483054161602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4834578483054161602'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/05/we-have-hud.html' title='We have HUD!'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-mNDev0ebx6c/Td5lx4DVnMI/AAAAAAAAEG8/BKcBztb75kg/s72-c/HudSS.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-5369157123659367386</id><published>2011-05-19T21:00:00.000-07:00</published><updated>2011-05-19T21:00:53.102-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='dbp'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>New Enemies, Miniboss</title><content type='html'>&lt;iframe width="425" height="349" src="http://www.youtube.com/embed/S0-KUiPMqfI" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;The latest build has some new enemies.  In the forest, there will be 5 standard enemies:&lt;br /&gt;&lt;br /&gt;1. Spider - paces back and forth between walls / ledges.  Hits with touch.&lt;br /&gt;2. Jumping Spider - Moves towards player, constantly jumping.  Like the flying turtles in mario.&lt;br /&gt;3. Throwing Bandit - Paces.  Throws a dagger.&lt;br /&gt;4. Slashing Bandit - Paces.  Slashes his sword if you get too close.&lt;br /&gt;5. Flying Birds.  These "home" in on the player.  I'm thinking of having these continually spawn from "nests" that must be destroyed.&lt;br /&gt;&lt;br /&gt;I also added the miniboss that was alluded to in the previous post.  The mini boss is the bandit king, and will "drop" the pistol when he's killed (probably early on in the game, lvl 2 or 3).&lt;br /&gt;&lt;br /&gt;Basically, he'll try to maximize his distance between himself and the player, and if he has an open shot for half a second he'll start firing.  The only way to beat him is to corner him and bash him down with a sword.&lt;br /&gt;&lt;br /&gt;Next step is designing the HUD!&lt;br /&gt;&lt;br /&gt;I'm still unsure whether I'll get the lvl/power up system working for DBP.  Procedural levels are also looking doubtful for the DBP build, especially since the worst case scenario would be if the judges got a non-functional map and couldn't play.  It's probably better to invest dev time in polishing the pure gameplay, animations and graphics.&lt;br /&gt;&lt;br /&gt;Thats it for now!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-5369157123659367386?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/5369157123659367386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/05/new-enemies-miniboss.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5369157123659367386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5369157123659367386'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/05/new-enemies-miniboss.html' title='New Enemies, Miniboss'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/S0-KUiPMqfI/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-8073220861480822980</id><published>2011-05-14T20:21:00.000-07:00</published><updated>2011-05-14T20:21:39.880-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='dbp'/><title type='text'>Update - Boss Fight</title><content type='html'>So the goal for today was to get a basic boss fight up and running.  Here was the "design document":&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/-9rPGwBDThj0/Tc9GP3GhSNI/AAAAAAAAD_8/-OqIsm7_pVA/s1600/spiderPlan.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="299" src="http://2.bp.blogspot.com/-9rPGwBDThj0/Tc9GP3GhSNI/AAAAAAAAD_8/-OqIsm7_pVA/s400/spiderPlan.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Here's the end result:&lt;br /&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="390" src="http://www.youtube.com/embed/AJzYjYL8VgA" width="480"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;Lots of work still to do polishing everything up, but the boss can kill the player...and the player can kill the boss.&lt;br /&gt;&lt;br /&gt;Also, got 4 directional parallax scrolling working, and locked doors with collectible keys. &lt;br /&gt;&lt;br /&gt;The mini-boss (Bandit King) will be next. &lt;br /&gt;&lt;br /&gt;Only 1 month left!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-8073220861480822980?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/8073220861480822980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/05/update-boss-fight.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/8073220861480822980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/8073220861480822980'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/05/update-boss-fight.html' title='Update - Boss Fight'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-9rPGwBDThj0/Tc9GP3GhSNI/AAAAAAAAD_8/-OqIsm7_pVA/s72-c/spiderPlan.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-6223913565477908304</id><published>2011-05-09T07:20:00.000-07:00</published><updated>2011-05-09T07:20:40.028-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xblig'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='dbp'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Platform Hack Alpha Progress</title><content type='html'>The build is coming together. Here's a quick playthrough I put together that shows the latest features.&lt;br /&gt;&lt;br /&gt;&lt;iframe width="425" height="349" src="http://www.youtube.com/embed/k5s8mBReIRM" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-6223913565477908304?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/6223913565477908304/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/05/platform-hack-alpha-progress.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6223913565477908304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6223913565477908304'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/05/platform-hack-alpha-progress.html' title='Platform Hack Alpha Progress'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/k5s8mBReIRM/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-365214861962788390</id><published>2011-04-13T13:37:00.000-07:00</published><updated>2011-04-13T13:37:49.572-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grapple hook'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Grapple Hook Revisited</title><content type='html'>There was a request to go into some more detail for the grapple hook.  &lt;a href="http://platformhack.blogspot.com/2010/12/platform-physics-grapple-hook.html"&gt;Original Post&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-6GKTU7cX4i4/TaYECvJlylI/AAAAAAAAD-4/i8AxDM4-uPo/s1600/PlatformerGrapple.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="408" src="http://2.bp.blogspot.com/-6GKTU7cX4i4/TaYECvJlylI/AAAAAAAAD-4/i8AxDM4-uPo/s640/PlatformerGrapple.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So what I've done is taken a fresh copy of the &lt;a href="http://create.msdn.com/en-US/education/catalog/sample/platformer"&gt;Platformer 4.0 solution&lt;/a&gt; and added only the Grapple Hook stuff.  The ZIP of the solution is attached below.&lt;br /&gt;&lt;br /&gt;Basically, there are 3 new classes and some changes to Player.cs&lt;br /&gt;&lt;br /&gt;The three new classes are in the GrappleHook Folder:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Collision.cs&lt;/b&gt; - This contains the core functions used "under the hood".&lt;br /&gt;&lt;b&gt;DrawPrimitives.cs&lt;/b&gt; - This class contains some functions used to draw various shapes.  The main method used is DrawLine2.&lt;br /&gt;&lt;b&gt;Grapple.cs&lt;/b&gt; - This class contains the guts of the grapple hook logic outlined in the initial blog post&lt;br /&gt;&lt;br /&gt;Changes to &lt;b&gt;Player.cs&lt;/b&gt;:&lt;br /&gt;There are some new member variables and a few methods.  I tried to comment everything that was new with "GRAPPLE HOOK"&lt;br /&gt;&lt;br /&gt;I also added WhitePixel.bmp to the Content/Sprites/Test folder.  This is used to draw the line.  (Also removed the music to cut down the size of the zip)&lt;br /&gt;&lt;br /&gt;A few changes to the logic and style of the Grapple Hook:&lt;br /&gt;1. The grapple hook "rope" will now shoot out 500 pixels at a rate of 2000, which is pretty much instant.&lt;br /&gt;&lt;br /&gt;2. The grapple hook will stay extended as long as you hold the button (instead of collapsing back to 0).  This makes it easier to attach.&lt;br /&gt;&lt;br /&gt;3. You can't shoot the grapple hook if isOnGround = true.  This makes use a little more natural and prevents the odd bug where you would attach and then the grapple curve would force you under the world or the tile below you.&lt;br /&gt;&lt;br /&gt;4. The swing itself is slightly slower (using 2000 as the gravity constant).  &lt;br /&gt;&lt;br /&gt;Places for Improvement:&lt;br /&gt;1. Some games have the grapple hook continually "shrink" while it is attached (Hook Champ, etc).  This gives the player the feel that the grapple is "elastic".  You could implement this by moving the player slighly "up" the rope every tick, and then re-calculating the Swing Curve.  The hard part is getting the velocities right so the swing is smooth, since we're not using actual angular velocities / momentum, but the path of the pendulum curve.&lt;br /&gt;&lt;br /&gt;2. Prevent the Grapple hook from attaching to horizontal walls.  This would require a change to the GrappleCollision function (and the getLineCollision function), to only attach if the Grapple "hook" is colliding through the lower X plane, instead of the Y plane.&lt;br /&gt;&lt;br /&gt;3. Better formulas for angular velocities entering and exiting the swing.  Right now I'm using some cheap hacks (delta position -&amp;gt; velocity) to determine the initial and launch velocities when starting or exiting the grapple swing.  Some real physics might make it feel a little smoother.&lt;br /&gt;&lt;br /&gt;Download:&amp;nbsp;&lt;a href="http://daydalus.net/GameDev/GrappleExample.zip"&gt;GrappleExample.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-365214861962788390?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/365214861962788390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/04/grapple-hook-revisited.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/365214861962788390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/365214861962788390'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/04/grapple-hook-revisited.html' title='Grapple Hook Revisited'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-6GKTU7cX4i4/TaYECvJlylI/AAAAAAAAD-4/i8AxDM4-uPo/s72-c/PlatformerGrapple.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-3352521806440840780</id><published>2011-04-11T21:31:00.000-07:00</published><updated>2011-04-11T21:31:33.280-07:00</updated><title type='text'>Playtest</title><content type='html'>A new version of Zombie Bash is in playtest.&lt;br /&gt;&lt;br /&gt;I was hoping to get it to market sooner, but I figured you might as well do the thing right the first time, even if it takes a long time (The Blizzard philosophy).  And its amazing how time consuming it is programming High Score screens to work just right...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://catalog.create.msdn.com/en-US/GameDetails.aspx?catalogEntryId=414b660d-183a-4ea5-9286-4fd3c0f69495&amp;amp;type=1"&gt;Zombie Bash Playtest&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-3352521806440840780?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/3352521806440840780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/04/playtest.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/3352521806440840780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/3352521806440840780'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/04/playtest.html' title='Playtest'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-3942184213186987062</id><published>2011-04-07T10:29:00.000-07:00</published><updated>2011-04-07T10:29:56.663-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gamedev'/><category scheme='http://www.blogger.com/atom/ns#' term='platform hack'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><title type='text'>It's a Trap!</title><content type='html'>Traps are essential for 2D games.  They present a challenge for a player that can only be defeated by timing and patience, rather than reliance on gunpower.&lt;br /&gt;&lt;br /&gt;I decided to build 3 different types of traps for Platform Hack.  Moving Blocks, Spinning Blades, and Flame Turrets.  Each of these uses slightly different technology to work, but since they were similar enough I crammed all the functionality into a single class, called Trap.&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/LkgcqawSAfY" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;Moving Block&lt;/b&gt; is the simplest type.  Its basically just a moving tile that hurts the player on collision.  Some games have blocks that "crush" the player, and can also provide solid collision from the other directions (top, sides).  I decided against this type of falling block, since it would require implement a "crushing" system of player damage.  Instead, if you touch the block from any direction, the player will be damaged.  Good level design (encasing the falling block inside Impassible tiles) can be used in conjunction with the trap type to good effect.&lt;br /&gt;&lt;br /&gt;The Collision is pretty simple:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[case TrapType.MovingBlock: if (p.BoundingRectangle.Intersects(BoundingRectangle)) {  if (Collision.IntersectPixels(BoundingRectangle, ColorArray, p.BoundingRectangle, p.ColorArray))  {   return true;  } }]]&gt;&lt;/script&gt;&lt;br /&gt; &lt;br /&gt;The Update function contains the only interesting piece of logic, using Linear Interpolation to smoothly move up and then slam down as a funtion of the entire TrapTimer&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[//move the block from current position to End Position and back, depending on the timer;private void UpdateMovingBlock(){ //the initial movement is quick (15% of time), the reset is slower (85% of time). float timePercent = (float)trapTimer.TotalSeconds / timer; float multiple; timePercent = 1 - timePercent; if (timePercent &lt;= .15) {   multiple = (float)(1f / .15f);  //Lerp between the Start and the End   Position = new Vector2(MathHelper.Lerp(StartPosition.X, EndPosition.X, timePercent * multiple), MathHelper.Lerp(StartPosition.Y, EndPosition.Y, timePercent * multiple)); } else {  //Get the amount multiple   multiple = (float)(1f / .85f);  //Lerp between the End and the Start  Position = new Vector2(MathHelper.Lerp(EndPosition.X, StartPosition.X, timePercent * multiple), MathHelper.Lerp(EndPosition.Y, StartPosition.Y, timePercent * multiple)); }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;Spinning Blade&lt;/b&gt; is the next type of trap.  &lt;br /&gt;&lt;br /&gt;This uses slightly more advanced collision and update logic.  Given the same TrapTimer, we do a full rotation of both the texture, and the Rotation Matrix thats use for pixel-based collision detection:&lt;br /&gt;&lt;br /&gt;Update:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[ private void UpdateSpinningBlades(){ //Lerp between 0 and 2Pi rads float timePercent = (float)trapTimer.TotalSeconds / timer; rotation = MathHelper.Lerp(0, (float)Math.PI * 2, timePercent); rotationMatrix = Matrix.CreateTranslation(new Vector3(-Origin, 0.0f)) * Matrix.CreateRotationZ(rotation) * Matrix.CreateTranslation(new Vector3(Position, 0f));}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Collision:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[case TrapType.SpinningBlades:  if (p.BoundingRectangle.Intersects(BoundingRectangle)) {  Matrix playerMatrix = Matrix.CreateTranslation(new Vector3(-p.Origin, 0.0f)) * Matrix.CreateTranslation(new Vector3(p.Position, 0.0f));  if (Collision.IntersectPixels(rotationMatrix,300,50, ColorArray,   playerMatrix,96,96, p.ColorArray))  {   return true;  } } break;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Draw:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[ spriteBatch.Draw(Texture, Position, null, Color.White, rotation, Origin, 1f, SpriteEffects.None, 0.0f); ]]&gt;&lt;/script&gt;&lt;br /&gt; &lt;br /&gt;One of the "gotchas" of Translation matrices in XNA (or I guess any graphics framework), is being sure to multiple by a translation of the negative origin.  &lt;em&gt;Matrix.CreateTranslation(new Vector3(-p.Origin, 0.0f))&lt;/em&gt;  This is needed whenever the texture is rendered using an origin.  You need to adjust the Translation Matrix in the same way, so that the collision detection is "synched" with the drawn texture.&lt;br /&gt;&lt;br /&gt;The collision detection with rotation is right out of the XNA tutorial found &lt;a href="http://create.msdn.com/en-US/education/catalog/tutorial/collision_2d_perpixel_transformed"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Lastly, the most complex type of trap is the &lt;b&gt;Flame Turret&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;The Flame Turret is using both Beam collision and the particle system for effect.&lt;br /&gt;&lt;br /&gt;Beam Collision:&lt;br /&gt;&lt;br /&gt;The benefit of using beam collision is if you have something like bullets that travel quickly.  If the bullet moves 30 pixels in a single update, is has the chance to pass right through an enemy without causing collision.  a Beam object can be used to represent a "line segment" in order to do collision.  Of course, you can always Draw the single dot as the bullet, it just uses the Beam object to do the collision.&lt;br /&gt;&lt;br /&gt;Here's my Beam struct:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[ public struct CollisionBeam{ public Vector2 A; public Vector2 B; public List&lt;Vector2&gt; beamCoords; //derived list of coordinates that occur between A and B public CollisionBeam(Vector2 A, Vector2 B) {  this.A = A;  this.B = B;  beamCoords = Collision.getLineVectors(A, B); }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;There are two vectors, A and B.  There is also a list of coordinates between the beams, which can be calculated with the following method.  Note: this may not be an optimal method, comments welcome.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[public static List&lt;Vector2&gt; getLineVectors(Vector2 A, Vector2 B){ List&lt;Vector2&gt; retval = new List&lt;Vector2&gt;(); Vector2 slope = B - A; slope.Normalize(); Vector2 coord; Vector2 roundedCoord; if (A.X &lt;= B.X) {  coord = A;  roundedCoord = new Vector2((float)Math.Round((decimal)coord.X), (float)Math.Round((decimal)coord.Y));  while (coord.X &lt; B.X)  {   retval.Add(roundedCoord);   coord += slope;   roundedCoord = new Vector2((float)Math.Round((decimal)coord.X), (float)Math.Round((decimal)coord.Y));  } } else {  coord = B;  roundedCoord = new Vector2((float)Math.Round((decimal)coord.X), (float)Math.Round((decimal)coord.Y));  while (coord.X &lt; A.X)  {   retval.Add(roundedCoord);   coord -= slope;   roundedCoord = new Vector2((float)Math.Round((decimal)coord.X), (float)Math.Round((decimal)coord.Y));  } } return retval;}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;A beam can represent either a bullet moving quickly across the screen, or a burst of flame shooting out of a trap turret.  &lt;br /&gt;&lt;br /&gt;We can determine if the beam hits a player (or enemy) using the following collision detection method (again, possibly not optimal):&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[public static bool IntersectPixelBeam(CollisionBeam beam, Rectangle rec, Color[] data){ // Find the bounds of the rectangle intersection int top; int bottom; int left; int right; //orient beam left to right; if (beam.A.X &lt;= beam.B.X) {  left = Math.Max(rec.Left, (int)beam.A.X);  right = Math.Min(rec.Right, (int)beam.B.X); } else {  left = Math.Max(rec.Left, (int)beam.B.X);  right = Math.Min(rec.Right, (int)beam.A.X); } if (beam.A.Y &lt;= beam.B.Y) {  top = Math.Max(rec.Top, (int)beam.A.Y);  bottom = Math.Min(rec.Bottom, (int)beam.B.Y); } else {  top = Math.Max(rec.Top, (int)beam.B.Y);  bottom = Math.Min(rec.Bottom, (int)beam.A.Y); } // Check every point within the intersection bounds for (int y = top; y &lt;= bottom; y++) {  for (int x = left; x &lt;= right; x++)  {   // Get the color of both pixels at this point   Color colorA = data[(x - rec.Left) + (y - rec.Top) * rec.Width];   //see if x,y lies along the beam   Color colorB;   if (beam.beamCoords.Contains(new Vector2(x, y)))   {    colorB = Color.Black;   }   else   {    colorB = Color.Transparent;   }   // If both pixels are not completely transparent,   if (colorA.A != 0 &amp;&amp; colorB.A != 0)   {    // then an intersection has been found    return true;   }  } } return false;}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The last piece of the puzzle is a method to get a bounding rectangle around the beam.  You *always* need to do bounding rectangle collision before pixel-based collision.  &lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[//returns a rectangle that bounds the line (used for Beam Collision)public static Rectangle getLineBoundingRectangle(Vector2 A, Vector2 B){ Rectangle rec; if (A.X &lt;= B.X) {  if (A.Y &lt;= B.Y) //A = top Left  {   rec = new Rectangle((int)A.X, (int)A.Y, (int)(B.X - A.X), (int)(B.Y - A.Y));  }  else //A = bottom left  {   rec = new Rectangle((int)A.X, (int)B.Y, (int)(B.X - A.X), (int)(A.Y - B.Y));  } } else {  if (A.Y &lt;= B.Y) //A = top right  {   rec = new Rectangle((int)B.X, (int)A.Y, (int)(A.X - B.X), (int)(B.Y - A.Y));  }  else //A = bottom right  {   rec = new Rectangle((int)B.X, (int)B.Y, (int)(A.X - B.X), (int)(A.Y - B.Y));  } } //add some buffer space rec.Width += 1; rec.Height += 1; return rec;}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;We can check for collision between the player and the beam in the following way:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[//check for collision with player if (particleBeams[i].BoundingRectangle.Intersects(player.BoundingRectangle)){ if (Collision.IntersectPixelBeam(particleBeams[i].beam, player.BoundingRectangle, player.ColorArray)) {  player.Hit(gameTime); }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Finally, we want our Flame Turret to look cool.  This can be done using Particle Effects.  &lt;br /&gt;&lt;br /&gt;The particle engine I've used is heavily modified from the &lt;a href="http://create.msdn.com/en-US/education/catalog/sample/particle"&gt;Particle Sample&lt;/a&gt;.  The details are a topic for another post.&lt;br /&gt;&lt;br /&gt;But briefly, we spawn fire particles along the length of the beam:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: js" type="syntaxhighlighter"&gt;&lt;![CDATA[public void spawnFireBeam(CollisionBeam beam, int count){ List&lt;Vector2&gt; lineVectors = Collision.getLineVectors(beam.A,beam.B); float ratio = lineVectors.Count / count; int step = (int)Math.Floor(ratio);   for(int i=0;i&lt;count;i++) {  if(i * step &lt; lineVectors.Count)   fire.AddParticles(lineVectors[i * step]); }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;That's pretty much it for simple traps.  With good art and creative level design, you can turn these three features into some pretty dastardly challenges for the player.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-3942184213186987062?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/3942184213186987062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/04/its-trap.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/3942184213186987062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/3942184213186987062'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/04/its-trap.html' title='It&apos;s a Trap!'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/LkgcqawSAfY/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-3239430902865332184</id><published>2011-03-21T11:51:00.000-07:00</published><updated>2011-03-21T11:51:31.645-07:00</updated><title type='text'>Web 2.0 Stuff</title><content type='html'>My game - Zombie Bash - is currently in Playtest for XBox Live Indie Games: &lt;a href="http://forums.create.msdn.com/forums/t/78185.aspx"&gt;http://forums.create.msdn.com/forums/t/78185.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Also, I caved and created a twitter account. &amp;nbsp;I figure its really the only way to spread the news about the games I'm building outside the small group of people I know in RL who would care ;)&lt;br /&gt;&lt;br /&gt;Follow me at @daydalus!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-3239430902865332184?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/3239430902865332184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/03/web-20-stuff.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/3239430902865332184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/3239430902865332184'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/03/web-20-stuff.html' title='Web 2.0 Stuff'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-6847971388404303428</id><published>2011-03-04T11:45:00.001-08:00</published><updated>2011-03-04T11:45:59.654-08:00</updated><title type='text'>Our Hero!</title><content type='html'>We have the first test sprites of our hero in action!&lt;br /&gt;&lt;br /&gt;&lt;iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/kX57nX9s9Ks" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-6847971388404303428?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/6847971388404303428/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/03/our-hero.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6847971388404303428'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/6847971388404303428'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/03/our-hero.html' title='Our Hero!'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/kX57nX9s9Ks/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-8713158233444547212</id><published>2011-02-24T12:28:00.000-08:00</published><updated>2011-02-24T12:28:19.263-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zombie bash'/><category scheme='http://www.blogger.com/atom/ns#' term='optimization'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><title type='text'>Optimization!</title><content type='html'>I finally got around to purchasing the &lt;a href="http://create.msdn.com/en-US/home/membership/"&gt;Creators Club Membership&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The main benefit is I can deploy the games I make to XBox 360, and after Peer Review, have them show up on the XBox Live Indie Games channel.&lt;br /&gt;&lt;br /&gt;The set-up and deployment process was pretty painless, but once I loaded up Zombie Bash, I noticed something bad.  &lt;br /&gt;&lt;br /&gt;The game was incredibly slow!  I'd be surprised if I was getting 1 frame per second, especially when the level first started and a bunch of enemies spawned.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-0m0NSy1Gui0/TWa_Jt54ZCI/AAAAAAAAD9E/xfMNlSl39PQ/s1600/ZombieBashEnemies.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="184" width="400" src="http://3.bp.blogspot.com/-0m0NSy1Gui0/TWa_Jt54ZCI/AAAAAAAAD9E/xfMNlSl39PQ/s400/ZombieBashEnemies.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The game ran fine on the computer, but the XBox has much weaker hardware.  Also, the way XBox environment works under the hood (like disk IO) is different as well.&lt;br /&gt;&lt;br /&gt;After doing some research and reading the forums, I came away with some suggestions to try:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1. Run the &lt;a href="http://msdn.microsoft.com/en-us/library/bb198208.aspx"&gt;Xbox Remote Performance Monitor&lt;/a&gt; when the game is running on Xbox.&lt;/strong&gt;&lt;br /&gt; This is provided with the XNA Game Studio under Tools.  I was able to get it up and running and look at some of the results in real-time.  Unfortunately, the specifics that are profiled were a bit too low level to be of much help.  I could tell that the Garbage Collection on the XBox wasn't keeping up with all the objects I was spawning, but why?  &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2. Run a .NET CLR profiler as you run the game on the computer.&lt;/strong&gt;&lt;br /&gt; I was able to download the Open Source tool &lt;a href="http://code.google.com/p/slimtune/"&gt;SlimTune&lt;/a&gt; and configure it to profile my game.  This turned out to be a lot of help.  SlimTune actually attached to the CLR and uses Reflection to determine which methods are using the most processing time.  This quickly points out the functions and calls that are slowing down the game.  (Note: This program can often crash when testing XNA games, however it will still save the profiling to a file).  &lt;br /&gt; &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-VbKOQu2YMh0/TWa_JZ2oS4I/AAAAAAAAD88/7OtP2CuUYs0/s1600/SlimTune.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="139" width="400" src="http://2.bp.blogspot.com/-VbKOQu2YMh0/TWa_JZ2oS4I/AAAAAAAAD88/7OtP2CuUYs0/s400/SlimTune.jpg" /&gt;&lt;/a&gt;&lt;/div&gt; &lt;br /&gt; Which leads us to point number 3 -&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;3. Look for instances in the code where expensive operations are being done in real-time.&lt;/strong&gt;&lt;br /&gt; The number one difference between programming games and regular business apps - the same game code runs dozens (hopefully 60+) times a second.  If there are any expensive operation in any of the loops, even if they occur once or twice (aka - loading assets), they can slow the entire thing down and lead to a bad gaming experience.&lt;br /&gt; &lt;br /&gt; This was the culprit.  Every time a new Enemy spawned, I was loading all its sprite textures from disk.  This had been fine in the sample code, because the enemies were spawned once when the level was loaded.  But Zombie Bash has Enemy Spawners, and dozens of enemies can pop out every few seconds.  While the computer can easily handle that kind of disk IO, the XBox was choking.&lt;br /&gt; &lt;br /&gt; There were a few other objects (weapons, particles) where the same thing was being done - realtime loading of texture assets into the newly instantiated object.&lt;br /&gt; &lt;br /&gt; What I did was create a Loader class that is run once when the game first starts.  This goes through and reads all the textures, and also calculates the required bounding boxes and Color arrays needed for collision.  It then holds on to them in memory for whatever object needs them down the line (Enemies, Weapons, etc).  It remains to be seen if this will lead to issues if the game gets sufficiently large (hundreds of enemies, etc)&lt;br /&gt; &lt;br /&gt;&lt;em&gt;Load them (textures and animations) once and save them for later!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: js"&gt;&lt;![CDATA[private void LoadEnemyTextures(){ EnemyTextureDic = new Dictionary&lt;string,EnemyTextures&gt;(); for (int i = 1; i &lt; 5; i++) {    EnemyTextures temp = new EnemyTextures();  temp.RunTexture = content.Load&lt;Texture2D&gt;(spriteSet + "/" + i + "/" + "Run");  temp.IdleTexture = content.Load&lt;Texture2D&gt;(spriteSet + "/" + i + "/" + "Idle");  temp.DieTexture = content.Load&lt;Texture2D&gt;(spriteSet + "/" + i + "/" + "Die");  temp.DieGunTexture = content.Load&lt;Texture2D&gt;(spriteSet + "/" + i + "/" + "DieGun");  temp.DieBladeTexture = content.Load&lt;Texture2D&gt;(spriteSet + "/" + i + "/" + "DieBlade");  temp.DieExplodeTexture = content.Load&lt;Texture2D&gt;(spriteSet + "/" + i + "/" + "DieExplode");  temp.HitTexture = content.Load&lt;Texture2D&gt;(spriteSet + "/" + i + "/" + "Hit");  temp.Attack1Texture = content.Load&lt;Texture2D&gt;(spriteSet + "/" + i + "/" + "Attack1");  temp.WhitePixelTexture = WhitePixelTexture;  temp.RunAnimation = new Animation(temp.RunTexture, .1f, true);  temp.IdleAnimation = new Animation(temp.IdleTexture, .15f, true);  temp.DieAnimation = new Animation(temp.DieTexture, .15f, false);  temp.DieGunAnimation = new Animation(temp.DieGunTexture, .15f, false);  temp.DieBladeAnimation = new Animation(temp.DieBladeTexture, .15f, false);  temp.DieExplodeAnimation = new Animation(temp.DieExplodeTexture, .15f, false);  temp.HitAnimation = new Animation(temp.HitTexture, .15f, false);  temp.AttackAnimation = new Animation(temp.Attack1Texture, .15f, true);    EnemyTextureDic.Add(i.ToString(), temp); }}]]&gt;&lt;/script&gt;&lt;br /&gt;  &lt;br /&gt; A similar approach was taken for the particle system.  Each individual particle was calculating its own Sin and Cos curves when initialized in order to follow curved paths.  By moving those calculations to the parent class, and simply passing in a pre-initialized Curve object to each individual particle, the particle system was greatly improved!&lt;br /&gt; &lt;br /&gt;&lt;em&gt; This is incredibly expensive to do 50 times at once!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: js"&gt;&lt;![CDATA[ public Curve setCurveSine(){ Curve c = new Curve(); CurveKey ck; //iterate over 0 to 2Pi and use Sine function to generate points on curve for (double i = 0; i &lt; Math.PI * 24; i += Math.PI / 4) {  ck = new CurveKey((float)i, (float)Math.Sin(i));  ck.Continuity = CurveContinuity.Step;  c.Keys.Add(ck); } return c;}]]&gt;&lt;/script&gt;&lt;br /&gt; &lt;br /&gt;&lt;strong&gt;To sum up:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;-The XBox is much weaker than a computer&lt;br /&gt;-Make sure you don't load or calculate anything expensive during the game loop.  Do it before!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-8713158233444547212?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/8713158233444547212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/02/optimization.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/8713158233444547212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/8713158233444547212'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/02/optimization.html' title='Optimization!'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-0m0NSy1Gui0/TWa_Jt54ZCI/AAAAAAAAD9E/xfMNlSl39PQ/s72-c/ZombieBashEnemies.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-256955911422148142</id><published>2011-01-25T07:33:00.000-08:00</published><updated>2011-01-25T07:33:28.413-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='roguelike'/><title type='text'>For the Love Of...</title><content type='html'>Great write-up on the appeal of Rogue-likes: &lt;a href="http://www.gearfuse.com/unevenly-distributed-how-i-learned-to-stop-worrying-and-love-the/"&gt;http://www.gearfuse.com/unevenly-distributed-how-i-learned-to-stop-worrying-and-love-the/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-256955911422148142?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/256955911422148142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/01/for-love-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/256955911422148142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/256955911422148142'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/01/for-love-of.html' title='For the Love Of...'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-2744844303058368749</id><published>2011-01-18T16:55:00.000-08:00</published><updated>2011-01-18T16:55:12.207-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mrpas'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='minimaps'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Mini-Maps</title><content type='html'>For games with complex level design, mini-maps are essential. Especially in games like Super Metroid where the focus of the gameplay is more on backtracking and using your new abilities than pure exploration, the many map is very important tool.&lt;br /&gt;&lt;br /&gt;For Platform Hack, I'm planning on two different "mini" maps.  One map will be accessible from the pause menu, and will show the entire level, along with special icons for the player, doors, chests, etc.  The other map will be a true mini-map, in the upper-right corner of the HUD, showing only a tiny portion of the current level.&lt;br /&gt;&lt;br /&gt;&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/CsyVq3hw7BA?fs=1&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/CsyVq3hw7BA?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Originally I intended to draw a pixel directly on the screen to correspond with each tile in the level, but that turned out to be too slow.&lt;br /&gt;&lt;br /&gt;Instead, what we can do it create a Texture2D object on the fly and display it on the screen.  If we need to crop (for the small mini-map in the corner), we can calculate coordinates to center on the player, and then specify the sourceRectange parameter of SpriteBatch.Draw.&lt;br /&gt;&lt;br /&gt;To build a Texture2D in XNA, we first have to set the size.  Then we load in an Color array to specify the individual color of the pixels:&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: js"&gt;&lt;![CDATA[ private Color[] getColorArray(){ int mapHeight = lev.tiles.GetLength(1); int mapWidth = lev.tiles.GetLength(0); Color[] colorArray = new Color[mapWidth * mapHeight]; for(int i=0;i&lt;lev.tiles.GetLength(0);i++) {  for(int j=0;j&lt;lev.tiles.GetLength(1);j++)  {   if (fow.mazeFog[i, j] == '?')   {    colorArray[(j * mapWidth) + i] = Color.DarkGray;   }   //Rectangle rec = getMapBlock(i, j, scale, TopLeftPixel);   else if (lev.tiles[i, j].Collision == TileCollision.Impassable)   {    colorArray[(j * mapWidth) + i] = Color.Black;   }   else   {    colorArray[(j * mapWidth) + i] = Color.Transparent;   }  } } int x = lev.Player.BoundingRectangle.X / Tile.Width; int y = lev.Player.BoundingRectangle.Y / Tile.Height; colorArray[(y * mapWidth) + x] = Color.Red; return colorArray;  }   MapTexture = new Texture2D(spriteBatch.GraphicsDevice, mapWidth, mapHeight); Color[] colArray = getColorArray(); MapTexture.SetData&lt;Color&gt;(colArray);]]&gt;&lt;/script&gt;&lt;br /&gt;  &lt;br /&gt;Drawing the full map is pretty straightforward:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;spriteBatch.Draw(MapTexture,TopLeftPixel, null, Color.White,0,new Vector2(0,0),this.scale,SpriteEffects.None,0);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If we want to have a cropped version of the mini-map, we can use a function to determine the cropping rectangle, centered on the player position:&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: js"&gt;&lt;![CDATA[ private Rectangle getPlayerCenteredMapRec(int scale){ int mapHeight = 150 / scale; int mapWidth = 150 / scale; int mapHeightHalf = mapHeight / 2; int mapWidthHalf = mapWidth / 2; int playerX = lev.Player.BoundingRectangle.X / Tile.Width; int playerY = lev.Player.BoundingRectangle.Y / Tile.Height; int left; int top; if (playerX &gt; mapWidthHalf) {  left = playerX - mapWidthHalf; } else {  left = 0; } if (playerY &gt; mapHeightHalf) {  top = playerY - mapHeightHalf; } else {  top = 0; } if (playerX &gt;= (lev.tiles.GetLength(0) - mapWidthHalf)) {  left = left + (lev.tiles.GetLength(0) - mapWidthHalf - playerX); } if (playerY &gt;= (lev.tiles.GetLength(1) - mapHeightHalf)) {  top = top + (lev.tiles.GetLength(0) - mapHeightHalf - playerY); } Rectangle rec = new Rectangle(left, top, mapWidth, mapHeight); return rec;}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Then we can draw with these params in the Draw function:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;spriteBatch.Draw(MapTexture, TopLeftPixel, getPlayerCenteredMapRec(this.scale), Color.White, 0, new Vector2(0, 0), this.scale,SpriteEffects.None, 0);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;One important feature of mini-maps is the Fog of War.  We don't want to reveal the entire map to the player from the beginning.  Instead, we want to hide parts of it and reveal more as the player explores.  Uncovering new sections of the map is one of the fun parts of games with complex level design.&lt;br /&gt;&lt;br /&gt;To implement Fog of War, we store an extra 2D character array that determines which tiles in the map have been revealed.  As shown above in the GetColorArray() function, sections that are not yet revealed (char '?') are drawn Gray.&lt;br /&gt;&lt;br /&gt;The Fog of War char[,] array starts out completely filled with "unknown" tiles - '?'.  Each time we draw, we make a call to update the Fog Of War, determine what tiles the player can see, and switch those tiles over to '.'.  &lt;br /&gt;&lt;br /&gt;I'm using an open source algorithm called MRPAS to determine what the player can see from his position.  Full source available here: &lt;a href="http://www.umbrarumregnum.net/downloads/mrpas"&gt;http://www.umbrarumregnum.net/downloads/mrpas&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The code itself is somewhat complex, but essentially it draws lines out from the player until it hits an obstacle.  One nice feature of the algorithm is you can specify to "light walls", which means the wall tiles themselves will be revealed in the Fog Of War, and therefore show up in the minimap.&lt;br /&gt;&lt;br /&gt;&lt;script type="syntaxhighlighter" class="brush: js"&gt;&lt;![CDATA[ public void updateMazeFog(int x, int y){ MRPASHelper.computeFov(ref MazeMap, x, y, 0, true); char[,] tempFogMap = MazeMap.getFogMap();  //now merge the tempFogMap onto the existing fogMap for (int i = 0; i &lt; mazeHeight; i++) {  for (int j = 0; j &lt; mazeWidth; j++)  {   if (mazeFog[i, j] == '?' &amp;&amp; tempFogMap[i, j] == '.')   {    mazeFog[i, j] = '.';   }  } }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;I was a little worried that the whole thing would run slow, since we're doing a dozen nested loops on nxn mazes every Draw cycle, as well as running the MRPAS algorithm.  However, it runs without hiccup.  If performance started to become an issue (potentially on massive maps), you could simply keep track of which tiles the player has occupied.  If we've already been to this tile, don't run the Fog of War / MRPAS algorithm.  Similarly, only recalculate the Color[] for the actual mini-map tile if the player changes tiles.&lt;br /&gt;&lt;br /&gt;Next time I'm going to look into everything related to enemies - path finding, line of sight, rudimentary AI, attacking, etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-2744844303058368749?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/2744844303058368749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/01/mini-maps.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/2744844303058368749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/2744844303058368749'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/01/mini-maps.html' title='Mini-Maps'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-9222680880060466700</id><published>2011-01-10T21:53:00.000-08:00</published><updated>2011-01-10T21:53:49.509-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maze generation'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Building Mazes</title><content type='html'>Happy New Year!&lt;br /&gt;&lt;br /&gt;From NetHack to Civilization to Diablo to MineCraft, lots of games have used procedural algorithms to generate semi-randomized levels.  For a one man shop like myself, its a way to generate lots of gameplay without a ton of gruntwork. &lt;br /&gt;&lt;br /&gt;So how to go you about building mazes?&lt;br /&gt;&lt;br /&gt;One site that really helped me out was &lt;a href="http://pcg.wikidot.com/"&gt;PCG.Wikidog.com&lt;/a&gt; - Procedural Content Generation.  It contains algorithms for some of the classic roguelikes, including Angband.   &lt;br /&gt;&lt;br /&gt;A maze itself can be generated with a pretty simple iterative or recursive algorithm.  The psuedocode is as follows:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1. Start out with a 2D array of size nxn.&lt;br /&gt;&lt;br /&gt;2. Fill each cell in the grid with character '?' (undefined)&lt;br /&gt;&lt;br /&gt;3. Carve out a random cell.&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;a. Define function Carve: make the input cell empty '.'&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;b. Make the surrounding four cells "maybe" ','.&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;c. Add these surrounding cells to a coordinate list called Frontier&lt;br /&gt;&lt;br /&gt;4. Iterate or Recurse through the Frontier list until it is empty.  &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;a. pick a random cell from Frontier.  You can use weighted algorithms to pick near the front or back of the list, which lead to different styles of maze (tight and claustrophic vs long empty passages)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;b. Run function Check on the random cell.  Define check (Note, this is the most complex part of the algorithm, so you may need to follow along the actual code below)&lt;br /&gt;  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;i. get the EdgeState of the cell - sum up the cells surroundind the current cell.  Empty to the north = 1, south = 2, west = 4, east = 8.&lt;br /&gt;  &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ii. If we're not up against the side of the map, set the diagonal spaces adjacent to the input space as empty, and return false.  Otherwise return true.  This basically makes the maze have corners.&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;c. If Check was true, Cave out the cell.  Otherwise Harden the cell - turn it into a wall '#'&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;d. Remove this cell from the Frontier list.&lt;br /&gt;&lt;br /&gt;5. Once the Frontier list is emtpy, go through the entire map and change "maybe" cells ',' into empty cells '.' .  Turn unknown '?' cells into walls '#'&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Full Code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;private char[,] maze; //field&lt;br /&gt;private List&lt;Coord&gt; frontier;&lt;br /&gt;&lt;br /&gt;private int height;&lt;br /&gt;private int width;&lt;br /&gt;&lt;br /&gt;private void BuildMaze()&lt;br /&gt;{&lt;br /&gt; maze = new char[height, width];&lt;br /&gt;&lt;br /&gt; //traverse the maze and fill in unknown blocks&lt;br /&gt; for (int i = 0; i &lt; height; i++)&lt;br /&gt; {&lt;br /&gt;  for (int j = 0; j &lt; width; j++)&lt;br /&gt;  {&lt;br /&gt;   maze[i, j] = '?';&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; //carve out a random spot&lt;br /&gt; Carve(r.Next(width-1),r.Next(height-1));&lt;br /&gt;&lt;br /&gt; while (frontier.Count &gt; 0)&lt;br /&gt; {&lt;br /&gt;  double pos = Math.Pow(r.NextDouble(), Math.Pow(Math.E, branchrate));&lt;br /&gt;  int index = (int)(pos * frontier.Count);&lt;br /&gt;  Coord c = frontier[index];&lt;br /&gt;  if (Check(c.x, c.y))&lt;br /&gt;   Carve(c.x, c.y);&lt;br /&gt;  else&lt;br /&gt;   Harden(c.x, c.y);&lt;br /&gt;  frontier.Remove(c);&lt;br /&gt;    &lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; for (int i = 0; i &lt; height; i++)&lt;br /&gt; {&lt;br /&gt;  for (int j = 0; j &lt;width; j++)&lt;br /&gt;  {&lt;br /&gt;&lt;br /&gt;   if (maze[i, j] == ',')&lt;br /&gt;    maze[i, j] = '.';&lt;br /&gt;&lt;br /&gt;   if (maze[i, j] == '?')&lt;br /&gt;    maze[i, j] = '#';&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt; // make the x,y space open, and add the surrounding spaces to the frontier list&lt;br /&gt;private void Carve(int x, int y)&lt;br /&gt;{&lt;br /&gt; &lt;br /&gt; maze[y,x] = '.';&lt;br /&gt; if (y &gt; 0)&lt;br /&gt; {&lt;br /&gt;  if (maze[y - 1,x ] == '?')&lt;br /&gt;  {&lt;br /&gt;   maze[ y - 1,x] = ',';&lt;br /&gt;   frontier.Add(new Coord(x, y - 1));&lt;br /&gt;  }   &lt;br /&gt; }&lt;br /&gt; if (y &lt; height - 1)&lt;br /&gt; {&lt;br /&gt;  if (maze[y + 1,x] == '?')&lt;br /&gt;  {&lt;br /&gt;   maze[y+ 1,x ] = ',';&lt;br /&gt;   frontier.Add(new Coord(x, y + 1));&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; if (x &gt; 0)&lt;br /&gt; {&lt;br /&gt;  if (maze[y,x - 1] == '?')&lt;br /&gt;  {&lt;br /&gt;   maze[y,x - 1] = ',';&lt;br /&gt;   frontier.Add(new Coord(x - 1, y));&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; if (x &lt; width - 1)&lt;br /&gt; {&lt;br /&gt;  if (maze[y,x + 1] == '?')&lt;br /&gt;  {&lt;br /&gt;   maze[y,x + 1] = ',';&lt;br /&gt;   frontier.Add(new Coord(x + 1, y));&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; //shuffle frontier?&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void Harden(int x, int y)&lt;br /&gt;{&lt;br /&gt; maze[y,x] = '#';&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private bool Check(int x, int y)&lt;br /&gt;{&lt;br /&gt; int edgestate = 0;&lt;br /&gt; if (y &gt; 0)&lt;br /&gt; {&lt;br /&gt;  if (maze[y - 1,x ] == '.')&lt;br /&gt;   edgestate += 1;&lt;br /&gt; }&lt;br /&gt; if (y &lt; height - 1)&lt;br /&gt; {&lt;br /&gt;  if (maze[ y + 1,x] == '.')&lt;br /&gt;   edgestate += 2;&lt;br /&gt; }&lt;br /&gt; if (x &gt; 0)&lt;br /&gt; {&lt;br /&gt;  if (maze[y,x - 1] == '.')&lt;br /&gt;   edgestate += 4;&lt;br /&gt; }&lt;br /&gt; if (x &lt; width - 1)&lt;br /&gt; {&lt;br /&gt;  if (maze[y,x + 1] == '.')&lt;br /&gt;   edgestate += 8;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; if (this.noDiagonals)&lt;br /&gt; {&lt;br /&gt;  if (edgestate == 1)&lt;br /&gt;  {&lt;br /&gt;   if (y &lt; height - 1)&lt;br /&gt;   {&lt;br /&gt;    if (x &gt; 0)&lt;br /&gt;    {&lt;br /&gt;     if (maze[ y + 1,x - 1] == '.')&lt;br /&gt;      return false;&lt;br /&gt;    }&lt;br /&gt;    if (x &lt; width - 1)&lt;br /&gt;    {&lt;br /&gt;     if (maze[y + 1,x + 1 ] == '.')&lt;br /&gt;      return false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;   return true;&lt;br /&gt;  }&lt;br /&gt;  else if (edgestate == 2)&lt;br /&gt;  {&lt;br /&gt;   if (y &gt; 0)&lt;br /&gt;   {&lt;br /&gt;    if (x &gt; 0)&lt;br /&gt;    {&lt;br /&gt;     if (maze[y - 1,x - 1 ] == '.')&lt;br /&gt;      return false;&lt;br /&gt;    }&lt;br /&gt;    if (x &lt; width - 1)&lt;br /&gt;    {&lt;br /&gt;     if (maze[ y - 1,x + 1] == '.')&lt;br /&gt;      return false;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   return true;&lt;br /&gt;  }&lt;br /&gt;  else if (edgestate == 4)&lt;br /&gt;  {&lt;br /&gt;   if (x &lt; width - 1)&lt;br /&gt;   {&lt;br /&gt;    if (y &gt; 0)&lt;br /&gt;    {&lt;br /&gt;     if (maze[y - 1,x + 1 ] == '.')&lt;br /&gt;      return false;&lt;br /&gt;    }&lt;br /&gt;    if (y &lt; height - 1)&lt;br /&gt;    {&lt;br /&gt;     if (maze[ y + 1,x + 1] == '.')&lt;br /&gt;      return false;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   return true;&lt;br /&gt;  }&lt;br /&gt;  else if (edgestate == 8)&lt;br /&gt;  {&lt;br /&gt;   if (x &gt; 0)&lt;br /&gt;   {&lt;br /&gt;    if (y &gt; 0)&lt;br /&gt;    {&lt;br /&gt;     if (maze[y - 1,x - 1 ] == '.')&lt;br /&gt;      return false;&lt;br /&gt;    }&lt;br /&gt;    if (y &lt; height - 1)&lt;br /&gt;    {&lt;br /&gt;     if (maze[y + 1,x - 1 ] == '.')&lt;br /&gt;      return false;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   return true;&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;  return false;&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  if (edgestate == 1 || edgestate == 2 || edgestate == 4 || edgestate == 8)&lt;br /&gt;   return true;&lt;br /&gt;  else&lt;br /&gt;   return false;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;And that's it.You end up with something like this:&lt;pre&gt;.#.##.#.#.#....#.#.#&lt;br /&gt;....#.#.#.#.##.#....&lt;br /&gt;###.#...#...####.###&lt;br /&gt;#...###...#..#.#.#..&lt;br /&gt;..#.#.##.#####.....#&lt;br /&gt;###.#.#........###..&lt;br /&gt;.#..#.##.#####...###&lt;br /&gt;.#.##..#.....#.####.&lt;br /&gt;....#.##.#######..#.&lt;br /&gt;#.###.#...#...###...&lt;br /&gt;&lt;/pre&gt;The trouble is that the passageways are only a single tile wide or tall, which would make it very hard for our hero to navigate the game world, since he's two tiles tall!  So we can scale the maze, simply by take a tile and copying it to 3 tiles to the east, south and south east.  This doubles the size of the board.  We can continue to double until the maze feels right - for my game it's a factor of 2, which is 4 times the size.You end up with something like this:&lt;pre&gt;....########....####........####....####........########....####....########....&lt;br /&gt;....########....####........####....####........########....####....########....&lt;br /&gt;....########....####........####....####........########....####....########....&lt;br /&gt;....########....####........####....####........########....####....########....&lt;br /&gt;........................########....########........####....####........####....&lt;br /&gt;........................########....########........####....####........####....&lt;br /&gt;........................########....########........####....####........####....&lt;br /&gt;........................########....########........####....####........####....&lt;br /&gt;####################....................########............########....####....&lt;br /&gt;####################....................########............########....####....&lt;br /&gt;####################....................########............########....####....&lt;br /&gt;####################....................########............########....####....&lt;br /&gt;........................################################....########............&lt;br /&gt;........................################################....########............&lt;br /&gt;........................################################....########............&lt;br /&gt;........................################################....########............&lt;br /&gt;################....########....####....####....####............####....########&lt;br /&gt;################....########....####....####....####............####....########&lt;br /&gt;################....########....####....####....####............####....########&lt;br /&gt;################....########....####....####....####............####....########&lt;br /&gt;&lt;/pre&gt;The world is still pretty boring, so one thing we can do is generate "rooms".  These are large areas of empty space that we can later populate with platforms, elevators, traps and enemies.  Generating rooms is pretty easy.  Prior to building the map, select a few cells and expand them by random dimensions, changing them to type the "maybe" type ','  We don't want to completely empty them out, so the maze algorithm will still work.So now we have something like this.  Better, but still not a game world:&lt;pre&gt;....................########............########....####....####....####....####&lt;br /&gt;########....####................############........................####........&lt;br /&gt;########....####................############........................####........&lt;br /&gt;########....####................############........................####........&lt;br /&gt;########....####................############........................####........&lt;br /&gt;....####....####....####....########............################............####&lt;br /&gt;....####....####....####....########............################............####&lt;br /&gt;....####....####....####....########............################............####&lt;br /&gt;....####....####....####....########............################............####&lt;br /&gt;....####################....################................####....####........&lt;br /&gt;....####################....################................####....####........&lt;br /&gt;....####################....################................####....####........&lt;br /&gt;....####################....################................####....####........&lt;br /&gt;....########............................####....................................&lt;br /&gt;....########............................####....................................&lt;br /&gt;....########............................####....................................&lt;br /&gt;....########............................####....................................&lt;br /&gt;........########....########....############....................................&lt;br /&gt;........########....########....############....................................&lt;br /&gt;........########....########....############....................................&lt;br /&gt;........########....########....############....................................&lt;br /&gt;&lt;/pre&gt;The next step is to place special characters.  These are tiles that will represent platforms, traps, enemies, elevators, items, powerups, etc.  Once we have our fully scaled map, we can traverse through and check for certain patterns in which to place our special tile.  For example, to place a platform '-', we want to be in a large empty room.  So before we place a platform, check to see that the 5 spaces above and below are empty:&lt;pre&gt;........................####............&lt;br /&gt;........................####............&lt;br /&gt;........................####............&lt;br /&gt;........................####.......A....&lt;br /&gt;....####................####....########&lt;br /&gt;....####..............-.####....########&lt;br /&gt;....####................####....########&lt;br /&gt;....####................####....########&lt;br /&gt;############............####............&lt;br /&gt;############........-...####............&lt;br /&gt;############...-........####............&lt;br /&gt;############............####............&lt;br /&gt;......................-.........####....&lt;br /&gt;................................####..-.&lt;br /&gt;................................####....&lt;br /&gt;..A......A...-..................####....&lt;br /&gt;############....-...........########....&lt;br /&gt;############................########....&lt;br /&gt;############................########....&lt;br /&gt;############................########....&lt;br /&gt;&lt;/pre&gt;Lastly, we want to add some challenge and progression to our maps.  We can do this with locked doors and keys.  The easiest way is to generate lots of smaller maps, place a random key 'K' inside, enclose the entire thing with a wall and a single locked door as the exit 'D'.  Connect all the smaller maps together, and we have a maze that requires some thinking to complete!&lt;pre&gt;############################################################&lt;br /&gt;#..................#............####...#............####...#&lt;br /&gt;#....K.............#.....K......####...#.....K......####...#&lt;br /&gt;#.A........A.......#..A.........####...#..A.........####...#&lt;br /&gt;################...#########...........#########...........#&lt;br /&gt;################.-.#########...........#########...........#&lt;br /&gt;################...#########.-.........#########.-.........#&lt;br /&gt;################...#########...........#########...........#&lt;br /&gt;#..................D............####...D............####...#&lt;br /&gt;#..................#............####...#............####...#&lt;br /&gt;#..................#............####...#............####...#&lt;br /&gt;#.A.............A..#...A........####...#...A........####...#&lt;br /&gt;########....################....################....########&lt;br /&gt;########....################....################....########&lt;br /&gt;########....################.-..################.-..########&lt;br /&gt;########....################....################....########&lt;br /&gt;#..................#...................#...................#&lt;br /&gt;#..................#...................#...................#&lt;br /&gt;#..................#...................#...................#&lt;br /&gt;############################################################&lt;br /&gt;&lt;/pre&gt;The fun thing about maze generation is that the possibilities are endless.  You can instantly generate a new world to explore and jump around in.&lt;br&gt;&lt;br&gt;&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/dQ23F8OV83o?fs=1&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/dQ23F8OV83o?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br&gt;&lt;br /&gt;Next time I'm going to look into minimaps, and "fog of war".  We don't want to be able to spoil the entire maze in one glance!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-9222680880060466700?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/9222680880060466700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2011/01/building-mazes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/9222680880060466700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/9222680880060466700'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2011/01/building-mazes.html' title='Building Mazes'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-1424873145458656757</id><published>2010-12-29T08:30:00.000-08:00</published><updated>2010-12-29T08:30:09.331-08:00</updated><title type='text'>Platform Physics: Grapple Hook</title><content type='html'>One of the best upgrades in Super Metroid is the grapple beam.  It gives you the ability the explore much more of the world, and avoid dozens of annoying enemies on the way.  It's even useful for shocking to death a boss.  So I knew I wanted a swinging grapple hook in Platform Hack.&lt;br /&gt;&lt;br /&gt;&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/w2014Bw6SFs?fs=1&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/w2014Bw6SFs?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Not only is the grapple hook fun to use in game, its an interesting challenge to implement in code.  There are essentially three main parts:&lt;br /&gt;&lt;br /&gt;1. The "rope" needs to shoot out from the player and catch on some surface of the world.  This can either be special tiles, or any sort of tile, though in some games this may lead to exploits.&lt;br /&gt;2. Once attached, the player swings in motion similar to a pendulum.&lt;br /&gt;3. When you release, you swing in the direction you were traveling, potentially covering gaps.  The player can also re-attach the grapple, and swing horizontally ala Tarzan.&lt;br /&gt;&lt;br /&gt;Similar to the jump logic, the first thing I did was create a data structure to hold all the variables we need to keep track of during the grapple swing:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;public struct GrappleStruct&lt;br /&gt;{&lt;br /&gt; public int mode;   //0=shooting, 1=attached&lt;br /&gt; public SwingCurveStruct swingCurve;&lt;br /&gt; public Vector2 position; //position of "hook"&lt;br /&gt; public TimeSpan GrappleTimer;&lt;br /&gt;&lt;br /&gt; public Vector2 launchVector;&lt;br /&gt; public Vector2 FireVector;&lt;br /&gt; public float RopeLength;&lt;br /&gt; public float fireSpeed;&lt;br /&gt; public Vector2 aimVector;&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;public struct SwingCurveStruct&lt;br /&gt;{&lt;br /&gt; public Curve YCurve;&lt;br /&gt; public Curve XCurve;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;SwingCurveStruct is also a data type that comes in handy - it holds two Curve objects.  The Curve class allows you to interpolate over a curve given a set of discrete points.  So instead of defining complex movement purely by physics formulas, you can numerically determine a few key points along the curve, plug them into a Curve class and then approximate the curve easily.  We use a SwingCurveStruct to hold the points in the swing itself.&lt;br /&gt;&lt;br /&gt;GrappleTimer tracks how much time the player has been "attached" to the grapple, so we can evaluate the correct position in the swing.&lt;br /&gt;&lt;br /&gt;launchVector defines the vector when the player releases from the grapple hook, and lets the player "fling" up in the air.&lt;br /&gt;&lt;br /&gt;FireVector is the direction the player is shooting the grapple hook.  Right now the "rope" only goes in an upward 45 degrees for ease of use, however this value could be set by the player.  &lt;br /&gt;&lt;br /&gt;The RopeLength and fireSpeed define how far and how fast the rope itself can shoot out.  These values are set when the grapple struct is first created.  Longer and faster ropes make it much easier to attach to surfaces, and vice-versa.&lt;br /&gt;&lt;br /&gt;The bulk of the logic for the grapple is done in the DoGrapple function:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;public bool DoGrapple(bool artifactPushed, GameTime gameTime, ref Vector2 position, ref Vector2 Force1Vector, ref Vector2 velocity, Level level, SpriteEffects flip)&lt;br /&gt;{&lt;br /&gt; float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;&lt;br /&gt; bool isSwinging = false;&lt;br /&gt;&lt;br /&gt; if (artifactPushed)&lt;br /&gt; {&lt;br /&gt;  if (playerGrappleStruct.mode == 0)&lt;br /&gt;  {&lt;br /&gt;   if (playerGrappleStruct.FireVector.X == 0 &amp;&amp; playerGrappleStruct.FireVector.Y == 0)&lt;br /&gt;   {&lt;br /&gt;    if (playerGrappleStruct.aimVector.X == 0 &amp;&amp; playerGrappleStruct.aimVector.Y == 0)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;     if (flip == SpriteEffects.FlipHorizontally)&lt;br /&gt;     {&lt;br /&gt;      playerGrappleStruct.FireVector = new Vector2(1f, -1f);&lt;br /&gt;     }&lt;br /&gt;     else&lt;br /&gt;     {&lt;br /&gt;      playerGrappleStruct.FireVector = new Vector2(-1f, -1f);&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;     playerGrappleStruct.FireVector = new Vector2(playerGrappleStruct.aimVector.X, playerGrappleStruct.aimVector.Y);&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   playerGrappleStruct.position += (playerGrappleStruct.FireVector * elapsed * playerGrappleStruct.fireSpeed) + (velocity * elapsed);&lt;br /&gt;   if (Helper.getDistance(position, playerGrappleStruct.position) &gt; playerGrappleStruct.RopeLength)&lt;br /&gt;   {&lt;br /&gt;    playerGrappleStruct.position = position + new Vector2(0, -25);&lt;br /&gt;   }&lt;br /&gt;   GrappleCollision(level,position,velocity);&lt;br /&gt;&lt;br /&gt;   isSwinging = false;&lt;br /&gt;  }&lt;br /&gt;  if (playerGrappleStruct.mode == 1)&lt;br /&gt;  {&lt;br /&gt;   playerGrappleStruct.GrappleTimer += gameTime.ElapsedGameTime;&lt;br /&gt;   float maxTime = playerGrappleStruct.swingCurve.XCurve.Keys[playerGrappleStruct.swingCurve.XCurve.Keys.Count - 1].Position;&lt;br /&gt;   float newPositionX = playerGrappleStruct.swingCurve.XCurve.Evaluate((float)playerGrappleStruct.GrappleTimer.TotalSeconds % maxTime);&lt;br /&gt;   float newPositionY = playerGrappleStruct.swingCurve.YCurve.Evaluate((float)playerGrappleStruct.GrappleTimer.TotalSeconds % maxTime);&lt;br /&gt;   playerGrappleStruct.launchVector = setSwingVelocity(new Vector2(newPositionX, newPositionY), position, (float)gameTime.ElapsedGameTime.TotalSeconds);&lt;br /&gt;&lt;br /&gt;   playerGrappleStruct.LaunchTimer = TimeSpan.FromSeconds(1);&lt;br /&gt;   playerGrappleStruct.launchCurve = setLaunchCurveStruct(playerGrappleStruct.launchVector);&lt;br /&gt;   position.X = newPositionX;&lt;br /&gt;   position.Y = newPositionY;&lt;br /&gt;   isSwinging = true;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt; {&lt;br /&gt;  if (playerGrappleStruct.mode == 1)&lt;br /&gt;  {&lt;br /&gt;   playerGrappleStruct.mode = 0;&lt;br /&gt;   Force1Vector = playerGrappleStruct.launchVector;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  //reset the rope;&lt;br /&gt;  playerGrappleStruct.position = position + new Vector2(0, -25);&lt;br /&gt;  playerGrappleStruct.FireVector = new Vector2(0f, 0f);&lt;br /&gt;&lt;br /&gt;  isSwinging = false;&lt;br /&gt; }&lt;br /&gt; return isSwinging;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The function has three main sections, corresponding to the three parts listed above.&lt;br /&gt;&lt;br /&gt;1. If we're shooting the grapple hook (artifactPressed) and in mode 0, then increment the location of the "hook" and check if we've collided with any surfaces.&lt;br /&gt;&lt;br /&gt;We use the GrappleCollide function to check:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;private void GrappleCollision(Level level, Vector2 position, Vector2 velocity)&lt;br /&gt;{&lt;br /&gt; Vector2 temp;&lt;br /&gt;&lt;br /&gt; if (Collision.getLineCollision(position + new Vector2(0, -25), playerGrappleStruct.position, level, out temp))&lt;br /&gt; {&lt;br /&gt;  if ((position.Y - 25) &gt; temp.Y &amp;&amp; Math.Abs(position.X - temp.X) &gt; 50) //make sure we only grappling to points above us&lt;br /&gt;  {&lt;br /&gt;   playerGrappleStruct.position = temp;&lt;br /&gt;   playerGrappleStruct.mode = 1;&lt;br /&gt;   playerGrappleStruct.swingCurve = setGrappleSwingCurve(playerGrappleStruct.position, position + new Vector2(0, -25), velocity);&lt;br /&gt;   playerGrappleStruct.GrappleTimer = TimeSpan.FromSeconds(0f);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;getLineCollision essentially gets a list of all tiles that are overlapped by a line connecting the player to the hook.  We then traverse this list, moving outward from the player, and if we hit an Impassable or Platform tile, we return true, we're connected.&lt;br /&gt;&lt;br /&gt;Once we're connected, we change to mode 1 and we have to calculate the swing curve:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt; /*&lt;br /&gt; * given the initial force vector (x, y), and the angle of attachment, calculate the swing curve of the grapple, using pendulum physics&lt;br /&gt; * pendulum forumula&lt;br /&gt; *&lt;br /&gt; * O'' = -g/R sin O&lt;br /&gt; * angular acceleration = - gravity / length of rope * sin angle&lt;br /&gt; * angle (O=vertical)&lt;br /&gt; * */&lt;br /&gt;private  SwingCurveStruct setGrappleSwingCurve(Vector2 origin, Vector2 playerPosition, Vector2 initVelocity)&lt;br /&gt;{&lt;br /&gt; //length of rope&lt;br /&gt; float length = (float)Math.Sqrt(Math.Pow((origin.X - playerPosition.X), 2) + Math.Pow((origin.Y - playerPosition.Y), 2));&lt;br /&gt;&lt;br /&gt; Vector2 slope = (playerPosition - origin);&lt;br /&gt; slope.Normalize();&lt;br /&gt; slope = new Vector2(slope.X, slope.Y * -1);&lt;br /&gt;&lt;br /&gt; //get start angle&lt;br /&gt; float angleStart = (float)(Math.Atan2((double)slope.Y, (double)slope.X));&lt;br /&gt;&lt;br /&gt; float initVelocityRadians = getInitVelocity(length, origin, playerPosition, initVelocity);&lt;br /&gt;&lt;br /&gt; float time = 0f;&lt;br /&gt; float angleAcc = 0f;&lt;br /&gt; float angleVel = initVelocityRadians;&lt;br /&gt; float curAngle = angleStart;&lt;br /&gt;&lt;br /&gt; SwingCurveStruct retval = new SwingCurveStruct();&lt;br /&gt; retval.XCurve = new Curve();&lt;br /&gt; retval.YCurve = new Curve();&lt;br /&gt; retval = addCurvePosition(retval, time, origin, length, curAngle);&lt;br /&gt;&lt;br /&gt; //iterate through and set curve keys&lt;br /&gt; for (float f = time; f &lt; 20f; f += .1f)&lt;br /&gt; {&lt;br /&gt;  angleAcc = -(GravityAcceleration / length) * (float)Math.Sin(curAngle + (float)Math.PI / 2);&lt;br /&gt;  angleVel += angleAcc * .1f;&lt;br /&gt;  curAngle += angleVel * .1f;&lt;br /&gt;  retval = addCurvePosition(retval, f, origin, length, curAngle);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return retval;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;This function uses the formula for a pendulum to create Curve objects that the player will move on while attached.  Here's a great site that walked me through pendulum physics: &lt;a href="http://www.myphysicslab.com/pendulum1.html"&gt;http://www.myphysicslab.com/pendulum1.html&lt;/a&gt;&lt;br&gt;First, we have to determine the initial angle the player is attached: &lt;pre class="brush:csharp"&gt;float angleStart = (float)(Math.Atan2((double)slope.Y, (double)slope.X));&lt;br /&gt;&lt;/pre&gt;Next, we set an initial velocity.  This basically gives the player a little more momentum in the swing if they are moving when they attach, and makes "Tarzan" swings a little more powerful.&lt;pre class="brush:csharp"&gt; private float getInitVelocity(float length, Vector2 origin, Vector2 playerPosition, Vector2 initVelocity)&lt;br /&gt;{&lt;br /&gt; //pythagorean?&lt;br /&gt; float velocityDist = (float)Math.Sqrt((initVelocity.X * initVelocity.X) + (initVelocity.Y * initVelocity.Y));&lt;br /&gt; float cosx = Math.Abs((length * length + length * length - velocityDist * velocityDist) / (2 * length * length));&lt;br /&gt; float initVelocityRadians = (float)Math.Acos(cosx);&lt;br /&gt; if (float.IsNaN(initVelocityRadians))&lt;br /&gt;  initVelocityRadians = 0f;&lt;br /&gt;&lt;br /&gt; //unit circle goes counter clockwise, so if we are swinging the otherway, then multiple by -1&lt;br /&gt; if (initVelocity.X &lt; 0)&lt;br /&gt;  initVelocityRadians *= -1;&lt;br /&gt;&lt;br /&gt; return initVelocityRadians;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Last, we just need to iterate the points of a pendulum into the Curve structs,  The pendulum takes the following forumla: &lt;pre class="brush:csharp"&gt;angleAcc = -(GravityAcceleration / length) * (float)Math.Sin(curAngle + (float)Math.PI / 2);&lt;br /&gt;&lt;/pre&gt;Once we have the angular acceleration, we can determine the angular velocity, and thus the current position in radians.  From there, we can easily calculate the current position along the circumference of a circle (the "hook" being the origin).&lt;pre class="brush:csharp"&gt;//gets the x,y vector at the end of the pendulum, given origin, length and radians&lt;br /&gt;private Vector2 getCurvePosition(Vector2 origin, float length, float radians)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt; return new Vector2((float)(origin.X + length * Math.Cos(radians)), (float)(origin.Y + length * (float)Math.Sin(radians) * -1));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;em&gt;Note: the swing algorithm breaks down if the player attaches to a surface at less than the horizontal plane.  This is because the swing follows the path of a pendulum, and if the angle is greater than the horizontal, the rope will be "stiff", and the player could even use it as a sort of stilt.  If you want full elastic grapple hooks, some different physics logic is needed&lt;/em&gt;&lt;br&gt;2. Once we are attached, we just need to determine our current position on the swing curve. &lt;pre class="brush:csharp"&gt;float newPositionX = playerGrappleStruct.swingCurve.XCurve.Evaluate((float)playerGrappleStruct.GrappleTimer.TotalSeconds % maxTime);&lt;br /&gt;float newPositionY = playerGrappleStruct.swingCurve.YCurve.Evaluate((float)playerGrappleStruct.GrappleTimer.TotalSeconds % maxTime);&lt;br /&gt;&lt;/pre&gt;&lt;em&gt;Note: We're also doing a special collision check at this point to make sure the player can't swing through walls.  Because we aren't adjusting the player velocity, and instead directly updating the player position, there is the chance that the player could move so fast they could warp through walls (given a long enough rope, or a strong enough GravityAcceleration).  So lots of tweaking/testing is needed to find the right balance.&lt;/em&gt;&lt;br&gt;3. Once the player lets go (artifactPushed == false), we need to apply the launch velocity.  We actually set the launch velocity while we are connected with the following function:&lt;pre class="brush:csharp"&gt;private Vector2 setSwingVelocity(Vector2 position1, Vector2 position2, float timeDiff)&lt;br /&gt;{&lt;br /&gt; return (position1 - position2) * (float)(1.0 / timeDiff) * 20;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We find the difference in position during the swing, then multiply by 20.  The 20 is an arbitrary value, and can be adjusted to set how much the player "flings" after they release the grapple hook.  This is another case where if you use realistic physics, the gameplay isn't as fun as using exaggerated calculations.&lt;br /&gt;&lt;br /&gt;Last, we apply gravity as normal.  The launch vector is saved in Force1Vector, and is applied along with the other vectors.&lt;br /&gt;&lt;br /&gt;So that's the basic grapple hook, probably the most difficult "movement tool" being implement in Platform Hack.  Next time, it's onto something completely different - procedural maze generation!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-1424873145458656757?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/1424873145458656757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2010/12/platform-physics-grapple-hook.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1424873145458656757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/1424873145458656757'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2010/12/platform-physics-grapple-hook.html' title='Platform Physics: Grapple Hook'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-5881839315575090339</id><published>2010-12-28T06:48:00.000-08:00</published><updated>2010-12-28T06:53:38.739-08:00</updated><title type='text'>Platform Physics: Jumping</title><content type='html'>Ever since Super Mario Brothers (and perhaps Donkey Kong before that), the jump has been iconic of Platform games.  At first glance, it seems like it would be pretty easy to implement a jump using classic physics - apply an upward force to the player and then have gravity act as a constant downward acceleration.  This can be done, however, it leads to pretty punishing gameplay.  &lt;br /&gt;&lt;br /&gt;Platform games don't follow the laws of physics.  Here's a few reasons.&lt;br /&gt;&lt;br /&gt;1. We want the player to be able to move horizontally in the air.  This lets the player tweak movement and land much more difficult jumps.  This breaks the 1st law of Thermodynamics.&lt;br /&gt;2. We want the jump (and the pull of gravity) to be limited by a max velocity.  There are a few reasons for this.  One, it makes the gameplay a bit more manageable to not be flying all over the place.  Second, the algorithms of collision detection start to break down if the player (or any other object) moves faster than the height of a tile in a single update of the game loop.  &lt;br /&gt;3. We want the jump to have a constant upward motion, instead of a large initial velocity immediately starting to taper off by gravity.  As long as a player presses the jump key (within limits), we want the player to jump upwards.  &lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/zG711OK9-78?fs=1&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/zG711OK9-78?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;So let's look at the pieces needed to implement a jump:&lt;br /&gt;&lt;br /&gt;For Platform Hack, I wanted jumps to be pretty versatile.  Which means there will be double (and even triple) jumps, wall jumps and upgrades to jump power.  So I needed a data type that could store and abstract away the details of the jump:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;  &lt;br /&gt;    public struct JumpStruct&lt;br /&gt;    {&lt;br /&gt;        public int curNumJump;&lt;br /&gt;        public int totalNumJump;&lt;br /&gt;&lt;br /&gt;        public bool isJumping;&lt;br /&gt;        public bool wasJumping;&lt;br /&gt;&lt;br /&gt;        public float jumpTime;&lt;br /&gt;        public TimeSpan jumpTimer;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;  &lt;br /&gt;&lt;br /&gt;In the struct we have curNumJump and totalNumJump.  This is used to keep track of double and triple jumps.&lt;br /&gt;&lt;br /&gt;isJumping is a boolean thats mapped to the player jump key.  wasJumping is a boolean that specifies whether the player was pressing jump *the previous update*.  This is important for making sure the player presses the jump key for each jump instead of just holding it down.&lt;br /&gt;&lt;br /&gt;jumpTime is the total amount of time the player can jump.  Increasing this number allows the player to press down the jump key longer, and have larger jumps.  jumpTimer is the actual timer that counts down as soon as the jump starts.&lt;br /&gt;&lt;br /&gt;During each game loop, we must run the update on the player physics:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;   &lt;br /&gt;GravityVector.Y = MathHelper.Clamp(velocity.Y + GravityAcceleration * elapsed, -MaxFallSpeed, MaxFallSpeed);&lt;br /&gt;PlayerVector.Y = DoJump(PlayerVector.Y, gameTime);&lt;br /&gt;PlayerVector.X += MathHelper.Clamp(movement * MoveAcceleration * elapsed, -MaxMoveSpeed, MaxMoveSpeed);&lt;br /&gt;velocity = GravityVector + PlayerVector + Force1Vector + Force2Vector;&lt;br /&gt;velocity.X = MathHelper.Clamp(velocity.X, -MaxMoveSpeed, MaxMoveSpeed);&lt;br /&gt;velocity.Y = MathHelper.Clamp(velocity.Y, -MaxMoveSpeed, MaxMoveSpeed);&lt;br /&gt;Position += velocity * elapsed;&lt;br /&gt;Position = new Vector2((float)Math.Round(Position.X), (float)Math.Round(Position.Y));&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;One thing I've done is kept the various velocities (GravityVector, PlayerVector) seperate, and then combined them before applying to the player movement.  However, when I update gravity, it draws from the full velocity.  This little tweak helps smooth out the upward curve of the player jump, or if they fall off a ledge.  Gravity is also "clamped" at MaxFallSpeed, which acts as a sort of terminal velocity.  Clamp is important for reason #2 above.&lt;br /&gt;&lt;br /&gt;The Player.X velocity (horizontal movement) is updated by player control - the movement variable is set with the left and right buttons.  This allows the player to move horizontally even if they are in the air.&lt;br /&gt;&lt;br /&gt;The Player.X veloctiy is set with the DoJump function:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;  &lt;br /&gt;private float DoJump(float VelocityY, GameTime gametime)&lt;br /&gt;{&lt;br /&gt; VelocityY = 0;&lt;br /&gt; if (JumpCheck(gametime, IsOnGround))&lt;br /&gt; {&lt;br /&gt;  if ((IsOnGround) || playerJumpStruct.jumpTimer &gt; TimeSpan.Zero)&lt;br /&gt;  {&lt;br /&gt;   if (playerJumpStruct.jumpTimer.TotalSeconds == playerJumpStruct.jumpTime)&lt;br /&gt;   {&lt;br /&gt;    level.thisPlatformerGame.gameAudio.playSound("PlayerJump");&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // if we are in the ascent of the jump&lt;br /&gt;  if (TimeSpan.Zero &lt; playerJumpStruct.jumpTimer &amp;&amp; playerJumpStruct.jumpTimer &lt;= TimeSpan.FromSeconds(playerJumpStruct.jumpTime))&lt;br /&gt;  {&lt;br /&gt;&lt;br /&gt;   GravityVector.Y = 0;&lt;br /&gt;   // fully override the vertical velocity with a power curve that gives players more control over the top of the jump&lt;br /&gt;   VelocityY = JumpLaunchVelocity * (1.0f - (float)Math.Pow((playerJumpStruct.jumpTime-playerJumpStruct.jumpTimer.TotalSeconds) / playerJumpStruct.jumpTime, JumpControlPower));&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; return VelocityY;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Essentially, this function first checks if we can jump.  JumpCheck returns true if the player is on the ground, or the curNumJumps is less than totalNumJumps.  &lt;br /&gt;&lt;br /&gt;If we're on the ground, or the jump timer is less than the total jump time, then set the Player.Y velocity.  We're using a power function to give the player a sort of exponential curve to upward velocity, starting with the most power and decreasing as we reach the top.  We also are setting Gravity to 0 to give the jump a bit more "floatiness".&lt;br /&gt;&lt;br /&gt;Once the DoJump returns, we have to calculate the player's new position.  Velocity (and acceleration values - JumpAcceleration, GravityAcceleration) is stored in terms of seconds (500 pixels / second).  Each update function only takes a fraction of a second, so we need to multiple the velocity by elapsed, which will give the appropriate amount to move the player.  &lt;br /&gt;&lt;br /&gt;Lastly, we round the player position to the nearest round number, so the sprite is positioned cleanly on the pixels.  This is essential for player collision - otherwise the player can get stuck in floors and walls due to a fraction of a pixel overlapping. &lt;br /&gt;&lt;br /&gt;The *feel* of the jump is essential to how the game plays.  Stronger gravity and less precision of player movement can make the game much more difficult.  Conversely, if gravity is too weak and the player is too floaty, the game can feel slow, frustrating or boring.  Tweaking the GravityAcceleration, JumpAcceleration and Clamp values can drastically change the feel of the jump.&lt;br /&gt;&lt;br /&gt;Next: I'll go into the details of the infamous grappling hook!&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Note on Code samples: I'm more interested exploring algorithms and general concepts on this blog rather than  complete code samples.  The codebase I'm working with is a bit messy to upload for each example.  If you want to follow along, start with the Platformer Starter Kit for XNA and go from there.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-5881839315575090339?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/5881839315575090339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2010/12/platform-physics-jumping.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5881839315575090339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/5881839315575090339'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2010/12/platform-physics-jumping.html' title='Platform Physics: Jumping'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-4583205033268561844</id><published>2010-12-23T09:45:00.000-08:00</published><updated>2010-12-23T10:03:49.083-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='super metroid'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='platformer'/><title type='text'>Where I'm At Now</title><content type='html'>Right now I have a pretty good idea of what I want Platform Hack to be in regards to gameplay.  The original inspiration was actually &lt;a href="http://en.wikipedia.org/wiki/Super_Metroid"&gt;Super Metroid&lt;/a&gt;, one of the best platformers of all time.  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_35Tb4BicIFQ/TROO8h9pqnI/AAAAAAAADro/j6e6-Ov1VJ4/s1600/Samus_1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 247px; height: 320px;" src="http://1.bp.blogspot.com/_35Tb4BicIFQ/TROO8h9pqnI/AAAAAAAADro/j6e6-Ov1VJ4/s320/Samus_1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5553939936038201970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Super Metroid has all the standard action-platformer elements of jumping and attacking enemies, but what really set the game apart were the RPG elements, weapons and boss fights.  As you make your way through the maze-world, you unlock upgrades to health and weapons.  There are also tools you acquire that allow you to traverse the world more easily, including the the grapple beam and the space jump.   The boss fights were also extremely polished, with animations to match, finding that great balance between challenge and cakewalk.&lt;br /&gt;&lt;br /&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/L2rplW5VZ68?fs=1&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/L2rplW5VZ68?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;I'd like Platform Hack to borrow a lot of those elements, including the "movement" upgrades like the double jump and the grapple hook.  Because the world in Platform Hack will be procedurally generated, there's the possibility of having super high vertical walls and cliffs, which could potentially post a problem for the standard jump.  Of course, I'll have to tweak those maze-generation algorithms to limit the cliffs on the easier levels.  But one of the goals of the game will be to acquire these "movement tools" in addition to more powerful weapons.&lt;br /&gt;&lt;br /&gt;As far as development, I see the project in three stages:&lt;br /&gt;&lt;br /&gt;1. Core Engine Development.  This includes algorithms for collision detection, physics, player control, HUD, enemy movement and attacks, and boss scripting.&lt;br /&gt;&lt;br /&gt;2. Game World Development.  This is the world generation using procedural maze algorithms, different "features" like elevators, springs, doors, traps, as well as the more specific enemy and boss instances.&lt;br /&gt;&lt;br /&gt;3. Asset Creation.  This is where the game finally gets it's look - includes drawing and importing all the player, enemy and boss sprites, particle effects, tile and background images, HUD font and icons, sounds and music.  Hopefully I have some help on board for this stage.  But it's still a ways off.&lt;br /&gt;&lt;br /&gt;Right now I'm still deep in stage 1, trying to work out the tweaks in collision detection for various movement tools, including the Grapple Hook and Jump Jets.  But that's for another post -&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-4583205033268561844?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/4583205033268561844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2010/12/where-im-at-now.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4583205033268561844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/4583205033268561844'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2010/12/where-im-at-now.html' title='Where I&apos;m At Now'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_35Tb4BicIFQ/TROO8h9pqnI/AAAAAAAADro/j6e6-Ov1VJ4/s72-c/Samus_1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5955792218658139168.post-8298126775203366502</id><published>2010-12-23T08:16:00.001-08:00</published><updated>2010-12-23T08:22:30.053-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='platfomer'/><category scheme='http://www.blogger.com/atom/ns#' term='xna'/><category scheme='http://www.blogger.com/atom/ns#' term='roguelike'/><title type='text'>Fire it up</title><content type='html'>So I've started this blog to track progress and explore ideas for the game I'm building: Platform Hack.  &lt;br /&gt;&lt;br /&gt;Platform Hack is a combination &lt;a href="http://en.wikipedia.org/wiki/Platform_game"&gt;platform-jumper&lt;/a&gt; / &lt;a href="http://en.wikipedia.org/wiki/Rougelike"&gt;rogue-like&lt;/a&gt; (&lt;a href="http://en.wikipedia.org/wiki/NetHack"&gt;NetHack&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;The game is being built in XNA 4.0 using a heavily modified &lt;a href="http://msdn.microsoft.com/en-us/library/dd254918(v=xnagamestudio.31).aspx"&gt;Platformer starter kit&lt;/a&gt;.  I'll also be using some open source maze generation algorithms that come from &lt;a href="http://en.wikipedia.org/wiki/Angband_(video_game)"&gt;Angband&lt;/a&gt; and other rougelikes.&lt;br /&gt;&lt;br /&gt;The "engine" was already used for a simple game I released called &lt;a href="http://daydalus.net/wordpress/?p=345"&gt;Zombie Bash&lt;/a&gt;, which was basically an experiment to figure out the collision detection and intricacies of drawing / displaying assets in XNA.&lt;br /&gt;&lt;br /&gt;There's still a lot to go, and the next few blogs will go over the goals I have for the game, as well as some challenges of building it -&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5955792218658139168-8298126775203366502?l=platformhack.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://platformhack.blogspot.com/feeds/8298126775203366502/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://platformhack.blogspot.com/2010/12/fire-it-up.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/8298126775203366502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5955792218658139168/posts/default/8298126775203366502'/><link rel='alternate' type='text/html' href='http://platformhack.blogspot.com/2010/12/fire-it-up.html' title='Fire it up'/><author><name>Tim</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
