<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Developer of games and internets, Sugoi Papa
Personal Site@emmett9001Github</description><title>emmett9001</title><generator>Tumblr (3.0; @emmett9001)</generator><link>http://emmett9001.tumblr.com/</link><item><title>Parse.ly Blog: To the Next Parse.ly Intern: Learning is Not A Race</title><description>&lt;a href="http://blog.parsely.com/post/50495864825/to-the-next-parse-ly-intern-learning-is-not-a-race"&gt;Parse.ly Blog: To the Next Parse.ly Intern: Learning is Not A Race&lt;/a&gt;: &lt;p&gt;&lt;a class="tumblr_blog" href="http://blog.parsely.com/post/50495864825/to-the-next-parse-ly-intern-learning-is-not-a-race"&gt;parsely&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Emmett Butler is a web and video game developer and an NYU senior studying computer science and music technology. In this post, he reflects on his time as an intern at Parse.ly&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Today, I leave &lt;a href="http://parse.ly/" target="_blank"&gt;Parse.ly&lt;/a&gt; after 20 months of work that took me from writing web scrapers to diving deep into semantic…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wrote this post for the next wave of Parse.ly interns.&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/50497159455</link><guid>http://emmett9001.tumblr.com/post/50497159455</guid><pubDate>Wed, 15 May 2013 10:30:25 -0400</pubDate></item><item><title>Rainbow Smoke Experiments</title><description>&lt;p&gt;&lt;img alt="image" src="http://emmettbutler.com/img/noise.gif"/&gt;&lt;/p&gt;
&lt;p&gt;This is an exploration I did last night into pseudorandom noise generation. I was working on a project that involved the use of Perlin noise to make a target move erratically, and I couldn&amp;#8217;t resist the temptation of making vapor trails (a pretty common use case for noise).&lt;/p&gt;
&lt;p&gt;Nina and I found a Perlin &lt;a href="http://www.dreamincode.net/forums/topic/66480-perlin-noise/"&gt;noise implementation&lt;/a&gt; and adapted it into a &lt;a href="https://gist.github.com/emmett9001/4563945412e66cfd1831"&gt;simple class&lt;/a&gt;. Later in the evening, listening to the &lt;a href="https://itunes.apple.com/us/album/endless-fantasy/id628657245"&gt;new Anamanaguchi album&lt;/a&gt;, I was inspired to make something cool looking, which led to this smoky rainbowy excellence.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://gist.github.com/emmett9001/5578779"&gt;code&lt;/a&gt; that draws the smoke lines is based on code that simply draws a horizontal line. From the horizontal line, noise is applied to the vertical position of each pixel in an amount proportional to the distance of the pixel from the right side of the window. This is why the right side of the image appears less erratic than the far left side. The noise function is also passed the frame count as a parameter, to make the smoke lines progress from one side of the screen to the other and off then side. Without this addition, the lines would compress onto themselves over time, never leaving the screen.&lt;/p&gt;
&lt;p&gt;The colors are generated by three sine waves, each representing one of red, green, and blue. The phases of these sine waves are disturbed by Perlin noise, and these disturbances are what cause the changing color palette.&lt;/p&gt;
&lt;p&gt;This animation is created by writing pixel color values into a texture, then applying the texture to a sprite. The sprite is also scaled up by a factor of six in this image, since calculating the noise function at each pixel on a retina display makes the app run at &amp;lt;1 FPS.&lt;/p&gt;
&lt;p&gt;Check out the code for this demo &lt;a href="https://gist.github.com/emmett9001/5578779"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/50437443056</link><guid>http://emmett9001.tumblr.com/post/50437443056</guid><pubDate>Tue, 14 May 2013 15:40:00 -0400</pubDate></item><item><title>To the Next Parse.ly Intern: Learning is Not A Race</title><description>&lt;p&gt;&lt;em&gt;Emmett Butler is a web and video game developer and an NYU senior studying computer science and music technology. In this post, he reflects on his time as an intern at Parse.ly&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Today, I leave &lt;a href="http://parse.ly"&gt;Parse.ly&lt;/a&gt; after 20 months of work that took me from writing web scrapers to diving deep into semantic web standards to designing mobile SDKs. Here is some advice and emotional primer for the incoming Parse.ly intern. I can only speak from my own experience, and while I try to generalize, all of my advice is heavily colored by what I went through when I started.&lt;/p&gt;
&lt;p&gt;When I started at Parse.ly, I was working 20 hours a week alongside another part-time work study job. I was entering my 3rd year of an NYU double music technology/cs degree, and my technical skills were rudimentary. I had no &amp;#8220;real world&amp;#8221; experience to speak of, and the extent of my outside experience was a few hackathons, schoolwork, and a handful of personal projects. I actually remember thinking during my first few weeks at Parse.ly that I had no idea what I was doing - I didn&amp;#8217;t delude myself.&lt;/p&gt;
&lt;p&gt;In the course of my time here, I&amp;#8217;ve gone from mechanically writing 4-6 web crawler scripts per day to developing &lt;a href="http://schema.to"&gt;semantic web tools&lt;/a&gt; and &lt;a href="http://github.com/emmett9001/parsely-ios"&gt;mobile SDKs&lt;/a&gt; for Parsely&amp;#8217;s customers, as well as contributing to the main analytics product, Dash. I gained experience in most of Parse.ly&amp;#8217;s codebases circa mid-2012, primarily as a result of my own exploration. I personally feel that I&amp;#8217;ve come a long way.&lt;/p&gt;
&lt;p&gt;Parse.ly was both my first &amp;#8220;real&amp;#8221; job and my first time collaborating with other professional developers. Knowing that I was extremely inexperienced, it was easy to assume that everyone else on the team had all of the answers. In my mind, there was no question I could ask the other developers that would challenge them - the rest of the team was light years beyond me as far as I was concerned. This was my mindset for probably the first 2 or 3 months I spent at Parse.ly, and it didn&amp;#8217;t really change until I had done something I saw as substantial enough to warrant being taken seriously by anyone else. Of course, this is a poisonous mindset and it can (and did) lead to all kinds of negative emotions and behaviors. Primarily, it stopped me from contributing meaningfully to discussions, since I was convinced that I had nothing to offer.&lt;/p&gt;
&lt;p&gt;What I came to realize about this mindset is that it is (obviously?) not founded in fact. I&amp;#8217;m sure this realization is something everyone has to go through at some point or another, but the most important thing for me to personally understand was that &lt;em&gt;there is no worldwide programmer race&lt;/em&gt;. I am prone to operate under the assumption that there is a race going on between all programmers in the world to see who can be the &amp;#8220;best&amp;#8221; the fastest, and I&amp;#8217;m losing. The fact is that nobody actually thinks this way about anyone other than themselves - everyone is worried about their own skills, but they don&amp;#8217;t spend time comparing other people.&lt;/p&gt;
&lt;p&gt;The point is that everyone has their own expertise and skillset, and it&amp;#8217;s very unlikely (no matter how much you want to believe it) that the sum of your own knowledge is fully duplicated across the rest of the Parse.ly team. You know something someone else doesn&amp;#8217;t, and this simple fact invalidates the &amp;#8220;race&amp;#8221; idea. Skill sets are vectors, not scalars - you can&amp;#8217;t just &amp;#8220;rank&amp;#8221; people based on the entirety of what they know or don&amp;#8217;t know.&lt;/p&gt;
&lt;p&gt;The upshot for me was to stop comparing myself to other developers, especially the Parse.ly team. There is nothing to be gained from worrying about &amp;#8220;how good you are&amp;#8221;.&lt;/p&gt;
&lt;p&gt;As for contributing to discussions, I think about it like this: you are very familiar with yourself. You probably have a constant internal monologue in which you acknowledge your own thoughts about the discussions and team activity happening around you. You&amp;#8217;re comfortable with this. If you&amp;#8217;re anything like me, you tend to forget that other people (especially people who don&amp;#8217;t know you very well) are not familiar with your internal monologue. To me, it seemed that the worst consequence of not contributing to discussions was having to go along with whatever decisions were made. It turns out, though, that since the rest of the team doesn&amp;#8217;t hear your thoughts, the worst consequence is, in the long term, gaining a reputation on the team as unengaged. This applies, as far as I can tell, to any tech team, not just Parse.ly. If you don&amp;#8217;t actively contribute in group settings, people may see you as unengaged, or they &lt;em&gt;might&lt;/em&gt; give you the benefit of the doubt and assume that you&amp;#8217;re still paying attention. If you do contribute, though, you remove all doubt as to whether you care about being a productive team member. Ultimately, contributing to conversations is bound to make you look better, not worse.&lt;/p&gt;
&lt;p&gt;My first project at Parse.ly was the data exporting feature (what became Dash&amp;#8217;s &amp;#8220;save page as&amp;#8221; buttons). My first day was consumed by haphazardly setting up virtualenv, python, pip, mongodb, postgres, and dash on my laptop, and the assignment came on my second day (in my experience, this is a typical timeline for Parse.ly interns). The environment setup consisted mostly of Andrew guiding me through the setup processes (which were at the time alien to me) over a google hangout. When Andrew told me my assignment, it was presented as a verbal list of customer-facing requirements and a few technical pointers (for example, &amp;#8220;try using &lt;a href="https://github.com/kennethreitz/tablib"&gt;tablib&lt;/a&gt; for converting to CSV&amp;#8221;).&lt;/p&gt;
&lt;p&gt;I had no idea where to start. The project was an exercise in smart google searching and lots of trial and error. It felt weird at the time to be given a project that I would have to learn a lot to complete, and the distributed nature of the development team made it even more intimidating to ask for help when I needed it. A distributed team is a great environment for seasoned engineers to collaborate asynchronously, but it leaves something to be desired for a novice developer in the &lt;a href="http://www.catb.org/jargon/html/L/larval-stage.html"&gt;process of learning&lt;/a&gt;. In a non-distributed environment, I could lean over and ask another engineer to look something over or give a pointer - this becomes less natural when you&amp;#8217;re collaborating over IRC.&lt;/p&gt;
&lt;p&gt;As a result of the team&amp;#8217;s geographic separation and my above-mentioned mental blocks, I learned how to figure things out for myself. I started spending more time searching online and participating in StackOverflow than I did wondering when some team member could find time to help me learn. Honestly, I think the distributed environment contributed positively to my learning, as it forced me to break out of the comfort of more experienced devs and learn to fend for myself, so to speak. If I wasn&amp;#8217;t already an autodidact, I certainly became one around this time.&lt;/p&gt;
&lt;p&gt;There is a lot that you can do as an incoming intern at Parse.ly to make the experience most worthwhile for yourself. Most importantly, learn how to teach yourself. Don&amp;#8217;t let insecurity about your skills stop you from sharing your thoughts. React to intimidating projects with curiosity, not fear. Do not be afraid of &lt;a href="http://parsely.com/team.html#toms"&gt;this man&lt;/a&gt;, he is &lt;a href="http://www.flickr.com/photos/toms/8699322047/in/photostream"&gt;scarier than he looks&lt;/a&gt;. I mean, not as scary as he looks. He may be the most opinionated member of the Parse.ly team, but he will teach you to challenge your assumptions and defend your positions. Take every opportunity to learn bits of the codebase you&amp;#8217;ve never seen before, in languages you&amp;#8217;re unfamiliar with.&lt;/p&gt;
&lt;p&gt;In short, do not let any real or perceived lack of expertise stop you from being the developer you can be. Contribute often, teach yourself whenever you can, and allow yourself to be supported by the amazing team you&amp;#8217;re entering.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I&amp;#8217;m more than happy to provide personal or techincal advice if you&amp;#8217;re the target audience for this post. You can email me at emmett dot butler three 2 one at g mail dot com. (Change all number-words to digits and all &amp;#8220;dot&amp;#8221; to .)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Andrew Montalenti, whose encouragement to self-reflection helped these thoughts crystallize&lt;/em&gt;&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/50421750823</link><guid>http://emmett9001.tumblr.com/post/50421750823</guid><pubDate>Tue, 14 May 2013 10:48:00 -0400</pubDate></item><item><title>ninjashadowwarrior:

35 points
</title><description>&lt;img src="http://25.media.tumblr.com/3a7e485869c2f1cb7b538f256a64f61d/tumblr_mmi9o6PgxE1qfvm68o1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a class="tumblr_blog" href="http://ninjashadowwarrior.tumblr.com/post/49973781985/35-points"&gt;ninjashadowwarrior&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;35 points&lt;/p&gt;
&lt;/blockquote&gt;</description><link>http://emmett9001.tumblr.com/post/50007688466</link><guid>http://emmett9001.tumblr.com/post/50007688466</guid><pubDate>Thu, 09 May 2013 08:05:56 -0400</pubDate></item><item><title>Heads Up was on the front page of Adult Swim dot com</title><description>&lt;img src="http://24.media.tumblr.com/fa53efc8764c99fb0b2ea658e99e268c/tumblr_mkj67mNoOn1qirv5co1_500.png"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Heads Up was on the front page of Adult Swim dot com&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/46761290713</link><guid>http://emmett9001.tumblr.com/post/46761290713</guid><pubDate>Sun, 31 Mar 2013 11:11:46 -0400</pubDate></item><item><title>Schema.to Publicity</title><description>&lt;p&gt;I just googled myself and found this&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://graphics8.nytimes.com/images/blogs/open/2012/11/ossf_emmett.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. When did you first create your github repo?&lt;/strong&gt;&lt;br/&gt;We open-sourced Mr. Schemato &lt;a href="http://open.blogs.nytimes.com/2012/10/17/live-blogging-timesopen-bigger-data-and-smarter-scaling/"&gt;live&lt;/a&gt; at the TimesOpen event on October 17!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Have you been surprised by any of the feedback or contributions from other github users?&lt;/strong&gt;&lt;br/&gt;The feedback from users has been really helpful. People have run Mr. Schemato on their sites and have essentially served as testers, helping us see how well it’s working now and where we can improve. We could never do all that testing ourselves.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Describe your ideal forker/contributor.&lt;/strong&gt;&lt;br/&gt;We’d love to work with semantic web experts and people who are standards evangelists.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Finish this sentence: Open source is ____.&lt;/strong&gt;&lt;br/&gt;Open source is the only way to do software.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://open.blogs.nytimes.com/2012/11/21/open-source-science-fair-exhibitor-experiences/"&gt;The full story&lt;/a&gt;&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/44862881588</link><guid>http://emmett9001.tumblr.com/post/44862881588</guid><pubDate>Fri, 08 Mar 2013 10:39:00 -0500</pubDate></item><item><title>How Git Saved My Workshop</title><description>&lt;p&gt;This weekend, I gave a series of two talks on iOS game development at Pace University&amp;#8217;s computer science school. The talks, which introduced developers to cocos2d and box2d, couldn&amp;#8217;t have gone as well as they did if I hadn&amp;#8217;t learned how to use Git as a teaching tool. I can&amp;#8217;t say I was surprised at how well Git fit this role, or at the degree to which it became a stumbling block for those who had never seen it before.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been using Git for about as long as I&amp;#8217;ve been programming seriously. At first, the add-commit-push paradigm was hard for me to grasp, and I learned important lessons through trial and error: stash your changes before you pull, always use the &amp;#8212;rebase flag when pulling, et cetera. I learned some rules the hard way: don&amp;#8217;t use push -f unless you &lt;em&gt;really &lt;/em&gt;know what you&amp;#8217;re doing (even when Git&amp;#8217;s helpful error output tells you to). To learn this lesson in particular cost me several hours of team code. I know from experience how unforgiving Git can seem to a newcomer.&lt;/p&gt;
&lt;p&gt;My workshops were based on a toy project I made in late 2011 to teach myself the basics of iOS game dev, including sprite animation, collision detection, and time-based actions. To prepare this old project for the workshops, I actually rewrote most of the code in a &lt;a href="https://github.com/emmett9001/iPhoneGameDemo"&gt;new repository&lt;/a&gt;. One might ask why I didn&amp;#8217;t just use the old code; the main reason was to provide a &lt;a href="https://github.com/emmett9001/iPhoneGameDemo/commits/master"&gt;full change history&lt;/a&gt; to the workshop attendees. For a workshop that was primarily based on live coding, showing the attendees a complete changeset representing our demo app in different stages of development made a huge difference in their ability to learn the material.&lt;/p&gt;
&lt;p&gt;As I rewrote the project, I git-tagged each important commit with a number and some semantic content referencing its commit message. For example, when I added walls to the physics scene, I tagged the commit with&lt;/p&gt;
&lt;pre&gt;git tag 2_walls&lt;/pre&gt;
&lt;p&gt;This enabled anyone who cloned the repository to checkout commits by semantic content, rather than looking them up by hash. That ability engendered more participation on the part of almost everyone involved, since participants who fell behind could instantly catch up to the rest of the group with a simple git checkout.&lt;/p&gt;
&lt;p&gt;The workshops were attended by a varied bunch: some professional developers, many beginner programmers who were interested in iOS, and a few nonprogrammers who came for the design knowledge. Ultimately, the wide variance in participants&amp;#8217; experience levels proved challenging, especially given my presentation&amp;#8217;s heavy use of Git. I had to spend some time at the outset attempting to get everyone up to speed on the basics, including the difference between saving and committing, and the importance of stashing and unstashing changes. The workshops, especially the second (a day-long Saturday session) comprised building my demo app with the group: I talked through and wrote the project on a projector as if from scratch, and participants followed along and asked questions. For the beginning of the workshop, when the group was having an easy time following along, I hardly even used the tagged commits.&lt;/p&gt;
&lt;p&gt;At some point, though, the going got tougher. Around the time that I started leading the group through spritesheet creation and importing, I could tell that many were getting lost. After I had blasted through the material with characteristic disregard for those slower on the uptake, I noticed more than half of the group looking very confused. Almost nobody had followed my logic, and those who had had made significant changes to accommodate their incomplete understanding of the code. The whole room had code that was inconsistent with what I&amp;#8217;d written on the projector, and few people knew how to fix it.&lt;/p&gt;
&lt;p&gt;Enter Git tags. As a result of my pre-workshop tag setup, I could ask everyone to stash their changes and checkout the tagged commit that roughly corresponded to our position in the live coding session. This ensured that everyone in the room was playing with the same code, a huge benefit for a workshop leader. &lt;strong&gt;Careful planning and repository construction using native Git features saved my workshop.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Used in this way, Git works amazingly well as a teaching aid. To those who would set up their own workshop using a similar Git-based scheme I offer the following advice. Focusing your project on a visible change history obviously works best if your audience is already familiar with Git, at least on a superficial level. If they aren&amp;#8217;t, you will spend time (probably more than you&amp;#8217;d like) explaining the difference between committing and saving, or between stashing and stash-popping. If you&amp;#8217;re alright with splitting your time between Git and your subject matter like this (as I was), it might work well. Also, if you&amp;#8217;re live coding with a group and following the structure of a preexisting codebase, the closer you stay to the structure of that code, the less confusing your workshop will become.&lt;/p&gt;
&lt;p&gt;Thanks to Andrew Montalenti for seeding the idea of Git as a teaching aid. You can find the repository referenced in this post on my &lt;a href="https://github.com/emmett9001/iPhoneGameDemo"&gt;github&lt;/a&gt; and a video of one of the presentations on my &lt;a href="http://emmett9001.tumblr.com/post/43722569673/yesterday-i-gave-the-first-of-two-ios-game"&gt;blog&lt;/a&gt;.&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/43989269757</link><guid>http://emmett9001.tumblr.com/post/43989269757</guid><pubDate>Mon, 25 Feb 2013 11:47:00 -0500</pubDate><category>workshops</category></item><item><title>Yesterday, I gave the first of two iOS game development...</title><description>&lt;iframe src="http://player.vimeo.com/video/60225441" width="400" height="240" frameborder="0"&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Yesterday, I gave the first of two iOS game development workshops at Pace University. I spoke and answered questions about cocos2d and box2d for two hours, and I captured it all on video. This video uses https://github.com/emmett9001/iPhoneGameDemo for code examples. Enjoy!&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/43722569673</link><guid>http://emmett9001.tumblr.com/post/43722569673</guid><pubDate>Fri, 22 Feb 2013 09:18:00 -0500</pubDate><category>workshops</category></item><item><title>This week Nina, Diego and I participated in a nine-day game jam...</title><description>&lt;img src="http://25.media.tumblr.com/1f890902f59d1a1d0425857b28a2a95b/tumblr_mig1ldnfVU1qirv5co1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;This week &lt;a href="http://twitter.com/hentaiphd"&gt;Nina&lt;/a&gt;, &lt;a href="http://twitter.com/radstronomical"&gt;Diego&lt;/a&gt; and I participated in a nine-day game jam hosted by Sony. They gave us access to the Playstation Mobile SDK, which provides a 2D game engine abstraction in C# and targets the PS Vita. We made a game in which you control a robot gardener searching for the perfect interspecies plant hybrid. Nina and I pair-programmed pretty much all of this, and Diego’s art is legend. We had a lot of fun, especially watching our friends from the NYU Game Center take home a semifinal spot!&lt;/p&gt;
&lt;p&gt;Thanks to Sony and Indiecade for this awesome opportunity!&lt;/p&gt;
&lt;p&gt;&lt;img src="http://emmettbutler.com/img/jam.gif" width="600"/&gt;&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/43449710004</link><guid>http://emmett9001.tumblr.com/post/43449710004</guid><pubDate>Mon, 18 Feb 2013 20:43:09 -0500</pubDate></item><item><title>Some recent graphics tests from my game engine project. These...</title><description>&lt;img src="http://25.media.tumblr.com/caf04e9281b14d8a738a67201d7d2c7d/tumblr_mi7ts821YE1qirv5co1_400.gif"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Some recent graphics tests from my game engine project. These tests illustrate the sprite drawing and transforming capabilities of my rudimentary OpenGL-based system. Excluding the creation of the graphics context and OpenGL itself, all of the code executing to achieve these effects is my own (especially the transformation matrix math!). The last two examples are currently serving as stress tests for the renderer, which runs them at about 18 fps. The next step is some basic physics!&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://emmettbutler.com/img/sprites.gif"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://emmettbutler.com/img/shmup.gif"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://emmettbutler.com/img/spiral.gif"/&gt;&lt;/p&gt;
&lt;p&gt;I especially love the pattern I was able to create in this last example, because this beautiful result came about totally by accident. &lt;a href="https://gist.github.com/emmett9001/4953497"&gt;The code that accomplishes this motion&lt;/a&gt; is fairly simple.&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/43079374909</link><guid>http://emmett9001.tumblr.com/post/43079374909</guid><pubDate>Thu, 14 Feb 2013 10:32:46 -0500</pubDate></item><item><title>indiecade:

The teams are hard at work for the PlayStation...</title><description>&lt;img src="http://24.media.tumblr.com/b85799b0c3f80020dec542d98ea97e8b/tumblr_mi0zqsMuCA1r8zs9so2_500.jpg"/&gt;&lt;br/&gt; &lt;br/&gt;&lt;img src="http://24.media.tumblr.com/62f614f3851bb925c964de40fae29495/tumblr_mi0zqsMuCA1r8zs9so6_500.jpg"/&gt;&lt;br/&gt; &lt;br/&gt;&lt;img src="http://25.media.tumblr.com/2b914611f32e6a26be62f07e81d94218/tumblr_mi0zqsMuCA1r8zs9so5_500.jpg"/&gt;&lt;br/&gt; &lt;br/&gt;&lt;img src="http://25.media.tumblr.com/550dc78c6de79e28581ac280ccf56d3b/tumblr_mi0zqsMuCA1r8zs9so1_500.jpg"/&gt;&lt;br/&gt; &lt;br/&gt;&lt;img src="http://25.media.tumblr.com/f2eb8724dd9d8e0b235b93a6f3542ae8/tumblr_mi0zqsMuCA1r8zs9so3_500.jpg"/&gt;&lt;br/&gt; &lt;br/&gt;&lt;p&gt;&lt;a class="tumblr_blog" href="http://indiecade.tumblr.com/post/42789327006/the-teams-are-hard-at-work-for-the-playstation"&gt;indiecade&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The teams are hard at work for the PlayStation Mobile hosted GamJam. See what they come up with at &lt;a href="http://www.indiecade.com/2013/east_info/" title="IndieCade East info"&gt;IndieCade East&lt;/a&gt;, Feb 15-17, at the Museum of the Moving Image in Queens, New York. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You, me and @hentaiphd&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/42852336048</link><guid>http://emmett9001.tumblr.com/post/42852336048</guid><pubDate>Mon, 11 Feb 2013 12:50:36 -0500</pubDate></item><item><title>donutgoku:

colorlimit:

SPAWN MY BABBIES

~LEARNING ABOUT...</title><description>&lt;img src="http://24.media.tumblr.com/2cc207f9a047209dbffbdd8737bb4708/tumblr_mi0wu5x8RY1qejiw0o1_400.gif"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a class="tumblr_blog" href="http://donutgoku.tumblr.com/post/42786484772/colorlimit-spawn-my-babbies-learning-about"&gt;donutgoku&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a class="tumblr_blog" href="http://colorlimit.tumblr.com/post/42783617798/spawn-my-babbies"&gt;colorlimit&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SPAWN MY BABBIES&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;~LEARNING ABOUT SPRITES~&lt;/p&gt;
&lt;p&gt;watch ‘em makin’ children~*&lt;/p&gt;
&lt;/blockquote&gt;</description><link>http://emmett9001.tumblr.com/post/42788969148</link><guid>http://emmett9001.tumblr.com/post/42788969148</guid><pubDate>Sun, 10 Feb 2013 17:29:33 -0500</pubDate></item><item><title>Heads Up postmortem pt. 6</title><description>&lt;h1&gt;Difficulty Tuning&lt;/h1&gt;
&lt;p&gt;We knew from early in the Heads Up project that the flow of gameplay would center on hot dogs falling more and more frequently. We were looking for ways to gradually ramp up the difficulty per game in a semitransparent way. We wanted players to not really notice the difficulty ramp, so that without realizing it they&amp;#8217;d end up in some arcade zen. Originally, we had the idea that having more people on screen would make the game harder, so we also slowly ramped up the number of people on screen as well as the speed of falling hot dogs. Pretty quickly, though, we realized that having more people on screen actually made things way easier, so we allowed the people spawn speed to remain constant.&lt;/p&gt;
&lt;p&gt;We also tried shortening the amount of time a hot dog could live on the ground before decaying as a method of increasing difficulty, but our attempts at this made the game way too hard - after a short time, hot dogs wouldn&amp;#8217;t sit on the ground at all, making things very difficult. That idea was eventually scrapped in favor of simplicity.&lt;/p&gt;
&lt;p&gt;At first, the gradual decrement of the hot dog spawn rate was based on time: at certain time intervals, the rate would be decremented by some discrete value (eg at 30s, delay -= .5). The main problem with this method was that a player who was slower at mastering the mechanic would be faced with a huge challenge before they were ready for it and the game would feel way too hard.&lt;/p&gt;
&lt;p&gt;Instead of time benchmarks, spawn-time decrementing in the production version is based on point benchmarks, so the effective difficulty of the game is dependent on how well the player has done so far. For example: delay -= .5 at 10000 points, 20000 points, etc. This way, slower players still feel appropriately challenged. This strategy alone doesn&amp;#8217;t stop players from feeling that the game gets too hard too fast, but it does put players on the same footing, so at least most players should feel that the difficulty increases at the same rate.&lt;/p&gt;
&lt;p&gt;Interesting note: when the timing of these difficulty increases is literally identical across player skill levels (ie increase at 30s, 1m, 90s, etc&amp;#8230;.), some players complain that the game gets difficult too fast. However, when the timing is adjusted based on player skill (ie different for everyone), players feel like it&amp;#8217;s consistent. Interesting how that works.&lt;/p&gt;
&lt;p&gt;For a while, the delay between hot dog spawns was the only parameter being adjusted to increase difficulty. Somewhere along the way, we decided that having 18 hot dogs on the screen at once might be unmanageable. We introduced a maximum number of dogs onscreen, in an attempt to mitigate that issue. This ended up becoming another parameter used to affect the difficulty - increasing at certain point benchmarks. For example: at 50,000 points, increase the maximum from 7 to 8. This, combined with the spawn delay decrements, proved to be enough to create a frantic feeling in the players.&lt;/p&gt;
&lt;p&gt;This also leads to an emergent wave pattern in the hot dog spawns. Enforcing a maximum means that even if the spawn delay time is past, a new dog won&amp;#8217;t spawn unless there are less than the max onscreen. If not, it will wait to spawn until some dogs are removed. This means that if the max is hit and all of the onscreen dogs leave on a single head, more will come down all at once. This creates the feeling that things are frantic but still manageable.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m reminded of a funny story from testing: I noticed one day that one of the testers had posted a Game Center high score higher than I&amp;#8217;d ever gotten - somewhere in the 150k area. Thinking I was the best Heads Up! Hot Dogs player in the world, I immediately started a game trying to beat his score. After passing about 50000 points I noticed that I had neglected to account for someone being this good at the game. The dog spawn rate didn&amp;#8217;t increase past that point, and gameplay quickly became boring for a player who was practiced enough to manage the five hot dogs.&lt;/p&gt;
&lt;p&gt;Side note: I missed the guy&amp;#8217;s high score by about 100 points. T__T&lt;/p&gt;
&lt;p&gt;This was a great catch, though, since it led me to ensure that skilled players wouldn&amp;#8217;t ever reach a plateau of difficulty. I made sure that after a certain point, the game would increase in difficulty much faster than it had before, almost guaranteeing that high-level players would still have something to do up there at the top.&lt;/p&gt;
&lt;p&gt;What does all of this mean? I think we did a good job of creating a curve that feels fairly transparent to the player. Maybe that&amp;#8217;s a goal for arcade games with mechanics as simple as ours.&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/39315758692</link><guid>http://emmett9001.tumblr.com/post/39315758692</guid><pubDate>Mon, 31 Dec 2012 12:28:53 -0500</pubDate></item><item><title>deckman:

my friend emmett and i are working on a music...</title><description>&lt;img src="http://25.media.tumblr.com/25c39888ac15999a6c81e9b5f7155f0e/tumblr_mfeitgu6UI1qbeadxo1_500.gif"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;&lt;a class="tumblr_blog" href="http://blog.cosstropolis.com/post/38492966058/my-friend-emmett-and-i-are-working-on-a-music"&gt;deckman&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;my friend &lt;a href="https://twitter.com/emmett9001"&gt;emmett&lt;/a&gt; and i are working on a music visualizer using c and opengl. our goal is to make it cool enough for chiptune visuals (and to make it stop using up half our system resources)&lt;/p&gt;
&lt;p&gt;what should we name it?&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/emmett9001/opengl_audio_vis"&gt;3d audio visualizer&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Started the gfx side of this like a week ago lol&lt;/p&gt;
&lt;p&gt;seriously though, names?&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/38493284297</link><guid>http://emmett9001.tumblr.com/post/38493284297</guid><pubDate>Fri, 21 Dec 2012 17:13:12 -0500</pubDate></item><item><title>Heads Up postmortem pt. 5</title><description>&lt;h1&gt;HotDogManager&lt;/h1&gt;
&lt;p&gt;There was a point in Heads Up development when I started realizing that I had to account for the iOS actions surrounding its execution - home button taps, double taps, sleep button presses, music and sfx changes, and things like that. Yes, this moment only came after months of never thinking about these things (it&amp;#8217;s my first app, ok?) Before then I&amp;#8217;d been mostly avoiding the questions that couldn&amp;#8217;t be solved by not allowing the app to run in the background, until I noticed the double-tap home button question.&lt;/p&gt;
&lt;p&gt;Some of the boilerplate that Cocos had put into the project paused and restarted the gameplay automatically on &lt;code&gt;applicationWillResignActive&lt;/code&gt; and &lt;code&gt;applicationDidBecomeActive&lt;/code&gt;, the functions that the app delegate calls when the home button is double-tapped to bring up the little list of apps on the bottom of the screen. This was great for me, since I didn&amp;#8217;t need to worry about how to do that pausing myself&amp;#8230;&lt;/p&gt;
&lt;p&gt;until I implemented an in-game pause screen. Immediately I ran into the issue where every time the user dismissed the app list, the action on screen would restart, including when the pause screen was up. This meant that the pause menu would stay there with action running behind it - obviously not a good situation.&lt;/p&gt;
&lt;p&gt;My immediate reaction to this is to tell the app delegate about when the pause screen is up, so it knows when to start the action and when not to - but the app delegate and the gameplay screen are in different and apparently unrelated files. I don&amp;#8217;t really remember what I tried, but I quickly realized that this was a pretty good use case for a singleton (a class that is guaranteed to only be instantiated a maximum of one time).&lt;/p&gt;
&lt;p&gt;So now there&amp;#8217;s a &lt;code&gt;HotDogManager&lt;/code&gt; singleton that maintains a state flag called &lt;code&gt;isPaused&lt;/code&gt; that indicates whether or not the gameplay pause screen is displayed. Since there&amp;#8217;s only one instance of the manager, the app delegate can just check it and see whether it should restart action.&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;// in applicationDidBecomeActive &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;HotDogManager&lt;/span&gt; &lt;span&gt;sharedManager&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;isPaused&lt;/span&gt;&lt;span&gt;]){&lt;/span&gt;
    &lt;span&gt;[[&lt;/span&gt;&lt;span&gt;CCDirector&lt;/span&gt; &lt;span&gt;sharedDirector&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;resume&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;It works quite nicely. That was the original use case, and since then I added a few more flags to the singleton to help keep track of more global state - things like sfx on/off, app running time, functions for reporting analytics events, and some more.&lt;/p&gt;
&lt;p&gt;Another awesome side effect of this is that now that the app always knows if it&amp;#8217;s paused or not, I can let it run in the background and display the pause screen if the user leaves and comes back in the middle of a round. This actually works by always resuming the game loop upon the app entering the foreground, and then checking within the game loop whether to display a pause screen. Something like&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;// in the game loop... &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;([[&lt;/span&gt;&lt;span&gt;HotDogManager&lt;/span&gt; &lt;span&gt;sharedManager&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;isPaused&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;&lt;span&gt;pauseLock&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
    &lt;span&gt;// display the ingame pause screen and freeze the action &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span&gt;[&lt;/span&gt;&lt;span&gt;self&lt;/span&gt; &lt;span&gt;pauseButton&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;NSNumber&lt;/span&gt; &lt;span&gt;numberWithBool&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;]];&lt;/span&gt;
    &lt;span&gt;// make sure we only send the pause command once &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span&gt;pauseLock&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;When the app enters the background, &lt;code&gt;isPaused&lt;/code&gt; gets set true. Then as soon as the app comes back up, one cycle of the main loop runs and then this code gets hit, freezing the action before the second loop.&lt;/p&gt;
&lt;p&gt;Beyond being pretty cool, I feel like this functionality might improve engagement or retention or some other marketing word since the user isn&amp;#8217;t always forced to restart their games when they get phone calls or whatever.&lt;/p&gt;
&lt;p&gt;This was my first time using a singleton, and if the idea had occurred to me sooner, I probably could have done an even better job of storing all of the global state in this manager, similar to how cocos does it with the CCDirector. But I suppose that&amp;#8217;s the next project.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve thought of so, so many ways I could refactor this code and make it way nicer. Effort probably better spent on making the next project awesome, though.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;~emmett&lt;/em&gt;&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/37402785402</link><guid>http://emmett9001.tumblr.com/post/37402785402</guid><pubDate>Fri, 07 Dec 2012 09:12:26 -0500</pubDate></item><item><title>Heads Up postmortem pt. 4</title><description>&lt;h1&gt;Touch Tracking&lt;/h1&gt;
&lt;p&gt;Since Heads Up&amp;#8217;s core gameplay centers on the quick manipulation of physics objects with touches, designing some system that allowed it efficiently and cleanly was one of my biggest concerns during development.&lt;/p&gt;
&lt;p&gt;We knew from the beginning that we wanted to allow players to grab hot dogs with their fingers, and this basic interaction was something that I actually learned on my first night working through some example box2d code. The general idea is simple: when a touch event happens inside the boundaries of a grabbable object, create what box2d calls a mouse joint, which is a type of physics joint specifically made for mouse (or finger) manipulation. Use this joint to connect the finger and the object, moving the object to the touch position for the duration of the touch, and destroying the joint when the touch ends. Not so bad.&lt;/p&gt;
&lt;p&gt;The big requirement that made this more of a problem was multitouch. When we had the guarantee that only one hot dog would ever be grabbed at a time, it was easy to use the simple algorithm above to move it along with the only touch. When there could be more than one grabbed hot dog at a time, though, there was suddenly the issue of determining which touch should have which hot dog attached to it.&lt;/p&gt;
&lt;p&gt;My first try here was to use the above algorithm to try and handle more than one touch, with predictably unsatisfying results. One touch still worked fine, but touching anywhere else on the screen (grabbing a hot dog or not) caused the hot dog that the first touch was holding to float halfway between the two touches, constantly having its target position alternated between the two touch positions. The program logic was telling the hot dog to be in both positions at once, instead of choosing just one touch to hold it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Aside: I guess I probably had no idea why that was happening at the time, and I most likely said something like &amp;#8220;that&amp;#8217;s a showstopper bug&amp;#8221;. This seems a lot simpler in hindsight.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So this was a problem. It seemed like a big problem. I was scared of it. And intrigued.&lt;/p&gt;
&lt;p&gt;My naive approach was, essentially, an attempt to roll my own system of identifying touches uniquely. &amp;#8220;Why would he do that?&amp;#8221; you might wonder, &amp;#8220;Doesn&amp;#8217;t he know about touch hashes?&amp;#8221; Unfortunately the answer at the time was no. But more on that in a moment.&lt;/p&gt;
&lt;p&gt;My best attempt to uniquely identify touch events was based on movement tracking - intuitively: &amp;#8220;if this touch is close to where touch A was a second ago, this touch must be touch A&amp;#8221;. meh.&lt;/p&gt;
&lt;p&gt;The touch&amp;#8217;s last known position was saved and compared to its current position, and I treated them as part of the same &amp;#8220;macro&amp;#8221; touch event if the current and past positions were close enough together. I was actually really happy with this implementation at the time, thinking I was pretty smart for figuring out what (for some reason) I hadn&amp;#8217;t been able to find on any box2d forum.&lt;/p&gt;
&lt;p&gt;Predictably, though, there were a ton of problems. Worst, since the comparison between positions involved testing an absolute value for proximity to zero, the bottom left corner of the screen became a bug haven (in cocos, bottom-left is the origin). The dog-grabbing logic sort of broke down near this area. Aside from that, the design imposed a maximum speed for hot dog dragging, since touches that moved too far per frame would leave their hot dogs behind. As a result, the core interaction felt kind of sluggish. Sometimes hot dogs wouldn&amp;#8217;t respond to touches. Sometimes they&amp;#8217;d get stuck in midair. Bringing two dragged hot dogs close enough together made them do strange things. Not good.&lt;/p&gt;
&lt;p&gt;We lived with this system for a while, through the early testing phases. Testers reported all of the bugs mentioned above (which I already knew about). Then one day, for some reason, I decided to google something like &amp;#8220;ios touch event identifier&amp;#8221; and discovered that iOS gives each complete touch event its own unique id for its entire duration - that is, across touchesBegan, touchesMoved, and touchesCancelled - the hash.&lt;/p&gt;
&lt;p&gt;Suddenly the whole problem became practically trivial. Not having to worry about providing touch ID myself, keeping hot dog grabs separate was as simple as comparing new touch hashes against stored ones. The above intuition becomes &amp;#8220;if this touch has the same ID as touch A, then it is touch A&amp;#8221;. Much better. (Notice the difference in wordings: &amp;#8220;must be&amp;#8221; versus &amp;#8220;is&amp;#8221;)&lt;/p&gt;
&lt;p&gt;Look at this code:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;// in CCTouchesMoved &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;
&lt;span&gt;for&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NSValue&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;v&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;dogTouches&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
    &lt;span&gt;// stored as NSValues &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;
    &lt;span&gt;DogTouch&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;DogTouch&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;)[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt; &lt;span&gt;pointerValue&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
    &lt;span&gt;// get the touch hash for this stored touch &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;
    &lt;span&gt;NSNumber&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;hash&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[[&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt; &lt;span&gt;getHash&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;retain&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
    &lt;span&gt;// compare the currently processed UITouch with this DogTouch by hash &lt;/span&gt;
    &lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;hash&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;intValue&lt;/span&gt; &lt;span&gt;==&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;touch1&lt;/span&gt; &lt;span&gt;hash&lt;/span&gt;&lt;span&gt;]){&lt;/span&gt;
        &lt;span&gt;[&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt; &lt;span&gt;moveTouch&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;NSValue&lt;/span&gt; &lt;span&gt;valueWithPointer&lt;/span&gt;&lt;span&gt;:&amp;amp;&lt;/span&gt;&lt;span&gt;locations&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt;retain&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;topFloor&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;FLOOR4_HT&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
    &lt;span&gt;}&lt;/span&gt; &lt;span&gt;else&lt;/span&gt; &lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;count&lt;/span&gt; &lt;span&gt;&amp;gt;=&lt;/span&gt; &lt;span&gt;2&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;touch2&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;hash&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;intValue&lt;/span&gt; &lt;span&gt;==&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;touch2&lt;/span&gt; &lt;span&gt;hash&lt;/span&gt;&lt;span&gt;]){&lt;/span&gt;
        &lt;span&gt;[&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt; &lt;span&gt;moveTouch&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span&gt;NSValue&lt;/span&gt; &lt;span&gt;valueWithPointer&lt;/span&gt;&lt;span&gt;:&amp;amp;&lt;/span&gt;&lt;span&gt;locations&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;span&gt;retain&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;topFloor&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;FLOOR4_HT&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
    &lt;span&gt;}&lt;/span&gt;
    &lt;span&gt;// have to pass in the height of the top floor here, since moveTouch needs &lt;/span&gt;
    &lt;span&gt;// to know about it and it varies across platforms (iPad, iPhone) &lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;dogTouches is an NSArray of NSValues containing pointers to DogTouch objects, which in turn contain a stored hash for the touch to which they belong, as well as methods for positioning the hot dogs according to the touch position. &lt;code&gt;count&lt;/code&gt; on that array easily tells how many hot dogs are grabbed at the moment.&lt;/p&gt;
&lt;p&gt;This code deals with a touch event ending (ie a finger being pulled off the screen):&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;// the cocoa touch events that just ended &lt;/span&gt;
&lt;span&gt;for&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;UITouch&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;touch&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;touches&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
    &lt;span&gt;// our stored touch objects &lt;/span&gt;
    &lt;span&gt;for&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NSValue&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;v&lt;/span&gt; &lt;span&gt;in&lt;/span&gt; &lt;span&gt;dogTouches&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
        &lt;span&gt;DogTouch&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;DogTouch&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;)[&lt;/span&gt;&lt;span&gt;v&lt;/span&gt; &lt;span&gt;pointerValue&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
        &lt;span&gt;NSNumber&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;hash&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[[&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt; &lt;span&gt;getHash&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;retain&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
        &lt;span&gt;// if the touch that just ended has the same hash, &lt;/span&gt;
        &lt;span&gt;if&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;touch&lt;/span&gt; &lt;span&gt;hash&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;==&lt;/span&gt; &lt;span&gt;hash&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;intValue&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
            &lt;span&gt;// drop the hot dog associated with that touch &lt;/span&gt;
            &lt;span&gt;[&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt; &lt;span&gt;removeTouch&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;FLOOR4_HT&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
            &lt;span&gt;[&lt;/span&gt;&lt;span&gt;dt&lt;/span&gt; &lt;span&gt;flagForDeletion&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
        &lt;span&gt;}&lt;/span&gt;
    &lt;span&gt;}&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;With this implementation, dog grabbing is faster, more responsive, and less buggy (and dare I say more fun?) than it ever was during testing. Much better.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;~emmett&lt;/em&gt;&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/37191273269</link><guid>http://emmett9001.tumblr.com/post/37191273269</guid><pubDate>Tue, 04 Dec 2012 11:08:59 -0500</pubDate></item><item><title>Heads Up postmortem pt. 3</title><description>&lt;h1&gt;Cheat Codes&lt;/h1&gt;
&lt;p&gt;Near the end of the Heads Up development cycle, we were looking for some easter eggs to covertly sprinkle around the app - I guess to put our &amp;#8220;signature&amp;#8221; on it, in a way. I like the idea of knowing something about the app that nobody else does, and having that knowledge be demonstrable in such an obvious way as a secret cheat code, so if a friend is playing on their phone, I can say &amp;#8220;hey check THIS out&amp;#8221; and suddenly drop into Spicy Chorizo Hell Mode*. Yes, this is a self-centered view of my role as the developer. Sorry. It&amp;#8217;s fun.&lt;/p&gt;
&lt;p&gt;Also, cheat codes are a dying breed, and including some makes Heads Up feel all the more &amp;#8220;retro&amp;#8221; (as much as that description stinks)&lt;/p&gt;
&lt;p&gt;So the codes are secret, and obviously I&amp;#8217;m not revealing them here. But I had fun implementing the cheat code recognizer.&lt;/p&gt;
&lt;p&gt;The codes are entered by performing a specific series of directional swipes at the level select screen. All of the menu screens in Heads Up actually have their own main loops in the form of &lt;code&gt;tick&lt;/code&gt; functions, which I sometimes use for running or switching animations, or in the case of the level screen, moving between the levels and processing cheats.&lt;/p&gt;
&lt;p&gt;The cheat recognizer is pretty simple: every time a directional swipe is performed, it places a string representing the swipe direction into its buffer, and once the number of entered swipes is equal to the length of the cheat it&amp;#8217;s responsible for, compares the buffer to its &amp;#8220;correct&amp;#8221; cheat code direction sequence. One of those might look like&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;NSArray&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;cheatSwipeSequence&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;"l"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"u"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"r"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"d"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"r"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"u"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"l"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"d"&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;&lt;br/&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;After that check, the entered swipes buffer is freed, to allow the next attempt to be made.&lt;/p&gt;
&lt;p&gt;The one other bit is that if a certain amount of time goes by without any input, the swipes buffer is cleared - that&amp;#8217;s necessary to allow multiple attempts and multiple cheat code entries.&lt;/p&gt;
&lt;p&gt;Obviously, the strings used to represent the swipe directions could just as easily be chars or ints, since they really just represent one of four states. I wanted the sequences to be easy to read, though (so I can remember them!)&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t know how old-school button sequence cheats are implemented, but I imagine it&amp;#8217;s something really similar to this - keeping sequences of entered inputs, validating, and then releasing for retry.&lt;/p&gt;
&lt;p&gt;The one other thing about this implementation is that I was feeling lazy about learning how Cocoa&amp;#8217;s built-in gesture recognizer classes work, so I just wrote my own (certainly an interesting manifestation of laziness). Naively, I first tried simply comparing the start and end position of the swipe, checking each of the directions (eg &lt;code&gt;last.x &amp;gt; first.x&lt;/code&gt; means the swipe was to the right) within a four-part &lt;code&gt;&lt;span class="pre"&gt;if...else&lt;/span&gt;&lt;/code&gt;. This didn&amp;#8217;t work too well, though, since using &lt;code&gt;else&lt;/code&gt; excluded some checks, and using only &lt;code&gt;if&lt;/code&gt; produced two outputs (eg &amp;#8220;u&amp;#8221; and &amp;#8220;r&amp;#8221; for an up-right swipe). That&amp;#8217;s fine, but it didn&amp;#8217;t totally fit what I wanted - I just required the main direction of the swipe, disregarding the smaller component of its vector.&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;firstTouch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;/span&gt; &lt;span&gt;lastTouch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;swipeLenX&lt;/span&gt; &lt;span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;swipeLenY&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
    &lt;span&gt;// right swipe&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;firstTouch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt; &lt;span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;lastTouch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;swipeLenX&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;/span&gt; &lt;span&gt;swipeLenY&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
    &lt;span&gt;// up swipe&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;firstTouch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;/span&gt; &lt;span&gt;lastTouch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;swipeLenX&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;/span&gt; &lt;span&gt;swipeLenY&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
    &lt;span&gt;// down swipe&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;firstTouch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt; &lt;span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;lastTouch&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;swipeLenX&lt;/span&gt; &lt;span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;swipeLenY&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
    &lt;span&gt;// left swipe&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;&lt;br/&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;So, in the final version of that bit, I check the larger component of the swipe vector, which I imagine is very similar to what Cocoa&amp;#8217;s recognizers do for directional swipes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;~emmett&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;*Spicy Chorizo Hell Mode may or may not actually exist&lt;/em&gt;&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/36665547335</link><guid>http://emmett9001.tumblr.com/post/36665547335</guid><pubDate>Tue, 27 Nov 2012 09:36:52 -0500</pubDate></item><item><title>At NYTM</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_mdhrgf3JrZ1qirv5co1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;At NYTM&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/35716159082</link><guid>http://emmett9001.tumblr.com/post/35716159082</guid><pubDate>Wed, 14 Nov 2012 14:00:15 -0500</pubDate></item><item><title>Heads Up postmortem pt. 2</title><description>&lt;h1&gt;Storing Level Data&lt;/h1&gt;
&lt;p&gt;In classic Emmett form, the first time Diego mentioned the idea of multiple levels/areas in Heads Up, my reaction was something between &amp;#8220;how do you do that&amp;#8221; and &amp;#8220;that&amp;#8217;s impossible&amp;#8221;. Claiming that problems are unsolvable is apparently a favorite pasttime of mine, and at the time (around April), I could barely conceptualize the work necessary to set up different levels. Of course, having done it, the problems now seem totally trivial, but that&amp;#8217;s called learning I guess.&lt;/p&gt;
&lt;p&gt;I was still a bit uncomfortable with Objective-C at that time, and a big question I had was &amp;#8220;how would we avoid massive code duplication across levels?&amp;#8221;. My gut reaction to the idea was that all of the game logic code would at best be put into utility functions, at worst be copy-pasted for each level*.&lt;/p&gt;
&lt;p&gt;Luckily, I at least knew enough about good coding practices at the time to know that both of the above were horrible ideas. Both were based on the idea that each level would be contained in its own cocos2d screen, totally independent from the others. This probably seemed like the most reasonable idea at the time.&lt;/p&gt;
&lt;p&gt;I ended up slowly easing into a fully formed level implementation step by step. First, we wanted to randomly choose a background image for the round: Philly or New York (the only two backgrounds that were finished at the time). This seemed much less intimidating than &amp;#8220;building levels&amp;#8221; to me, so this time my reaction was less fearful and more pragmatic. Easy, just switch on a random number between 1 and 2 at game load time to choose between two background images. We did something similar to choose audio tracks for each round.&lt;/p&gt;
&lt;p&gt;The real meat of the levels implementation came when I wanted to create a linking between the background and the music - so that every time the NYC background was shown, we&amp;#8217;d hear the same music. This was solved simply enough by storing a struct with the string name of the background and the string name of the audio file, one struct for each level. Then, the random choice at load time was between two structs instead of two strings. Much better than turning the whole game loop into shared code (or copypasta).&lt;/p&gt;
&lt;p&gt;Over time, ths struct grew to include lots of data about a specific level, until it grew into what you see below (truncated for brevity)&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NSValue&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;chicago&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NSNumber&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;full&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;
    &lt;span&gt;BOOL&lt;/span&gt; &lt;span&gt;loadFull&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;full&lt;/span&gt; &lt;span&gt;boolValue&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;

    &lt;span&gt;// some properties are used only in-game, others are used on multiple screens &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span&gt;// this saves load time on non-game screens &lt;/span&gt;
    &lt;span&gt;levelProps&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;lp&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; &lt;span&gt;levelProps&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;
    &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;enabled&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
    &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;slug&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"chicago"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// canonical identifier &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"Chicago"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// user-facing name &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;unlockNextThreshold&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;8000&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// used for determining trophy level &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;thumbnail&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"Chicago_Thumb.png"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// level select screen image &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;func&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"switchScreenChicago"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// callback function to load level &lt;/span&gt;
    &lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;loadFull&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
        &lt;span&gt;[[&lt;/span&gt;&lt;span&gt;CCSpriteFrameCache&lt;/span&gt; &lt;span&gt;sharedSpriteFrameCache&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;addSpriteFramesWithFile&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;"sprites_chicago.plist"&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;bg&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"Chicago_BG.png"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// gamplay background &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;bgm&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"04 - Chaos Dog In The Windy City.mp3"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// gamplay music &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;introAudio&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"03 - Chaos Dog In The Windy City (Intro).mp3"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;gravity&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;-&lt;/span&gt;&lt;span&gt;27.0f&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// force of gravity per level &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;spritesheet&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"sprites_chicago"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;sfxVol&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;.8&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;personSpeedMul&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// multiplier for people's walk speed &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;restitutionMul&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;.8&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// multiplier for head bounciness &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;frictionMul&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;1.1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// multiplier for head friction &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;maxDogs&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;6&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// initial value for max dogs allowed onscreen &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;hasShiba&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;  &lt;span&gt;// is the dog in this level&lt;/span&gt; &lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;spcDogData&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;dd&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; &lt;span&gt;spcDogData&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;  &lt;span&gt;// each level has a special sandwich &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;dd&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;riseSprite&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"ChiDog_Rise.png"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
        &lt;span&gt;dd&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;fallSprite&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"ChiDog_Fall.png"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
        &lt;span&gt;dd&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;mainSprite&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"ChiDog.png"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
        &lt;span&gt;dd&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;grabSprite&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;@&lt;/span&gt;&lt;span&gt;"ChiDog_Grab.png"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
        &lt;span&gt;// ... &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;lp&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;spcDog&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;dd&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
    &lt;span&gt;}&lt;/span&gt;
    &lt;span&gt;return&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;NSValue&lt;/span&gt; &lt;span&gt;valueWithPointer&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;lp&lt;/span&gt;&lt;span&gt;]];&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Looking back on this progression from naive implementation to sensible one, I notice that the main difference between them is an attention to the actual form of the problem. Turning the game loop into shared code between different level views might work in some other cases, but for Heads Up it seems like overkill. A lot of code would still be duplicated. Storing level data as structs, on the other hand, abstracts the idea of a level out only as far as one level differs from another. All of the levels are more or less the same. Hot dogs are always falling from the sky, sitting on the ground, and then dying after some amount of time. All of the physics are the same. People move in the same patterns. We don&amp;#8217;t need vastly different functions to deal with these.&lt;/p&gt;
&lt;p&gt;The level structures encapsulate the exact ways that the levels differ from each other, and nothing more. At load time, a struct is chosen from the array of all level structs based on the &lt;code&gt;slug&lt;/code&gt; field.&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;// populate an array with all of the level structs &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;NSMutableArray&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;levelStructs&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;LevelSelectLayer&lt;/span&gt; &lt;span&gt;buildLevels&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;NSNumber&lt;/span&gt; &lt;span&gt;numberWithInt&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]];&lt;/span&gt;
&lt;span&gt;for&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt; &lt;span&gt;i&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt; &lt;span&gt;i&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;levelStructs&lt;/span&gt; &lt;span&gt;count&lt;/span&gt;&lt;span&gt;];&lt;/span&gt; &lt;span&gt;i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
    &lt;span&gt;level&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;levelProps&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;)[[&lt;/span&gt;&lt;span&gt;levelStructs&lt;/span&gt; &lt;span&gt;objectAtIndex&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;pointerValue&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;
    &lt;span&gt;// if the slug is the one the levels screen passed in &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;    &lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;level&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;slug&lt;/span&gt; &lt;span&gt;==&lt;/span&gt; &lt;span&gt;levelSlug&lt;/span&gt;&lt;span&gt;){&lt;/span&gt;
        &lt;span&gt;// use it &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;        &lt;span&gt;break&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
    &lt;span&gt;}&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Looks like it might make more sense to pass in the whole struct here rather than loading all of them and discarding all but one.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;slug&lt;/code&gt; field of the level struct is also useful for storing persistent data like high scores and unlocked levels. Cocoa allows apps to store a plist file full of arbitrary keys and values persistently on the device, called &lt;code&gt;NSUserDefaults&lt;/code&gt;. I think that&amp;#8217;s normally used to store the defaults for user-editable settings. I do use it for that a bunch, like storing the sfx on/off preference, but I also use it for the progression data mentioned above. The slug helps here since I can store a key like&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;standardUserDefaults&lt;/span&gt; &lt;span&gt;setInteger&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;_score&lt;/span&gt; &lt;span&gt;forKey&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;NSString&lt;/span&gt; &lt;span&gt;stringWithFormat&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;"highScore%@"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;level&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;slug&lt;/span&gt;&lt;span&gt;]];&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;persisting the high score for the current level. I do something similar for unlocked/not unlocked and the highest trophy earned per level. I can read the stored data with&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;highScore&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;standardUserDefaults&lt;/span&gt; &lt;span&gt;integerForKey&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;NSString&lt;/span&gt; &lt;span&gt;stringWithFormat&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;"highScore%@"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;level&lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt;slug&lt;/span&gt;&lt;span&gt;]];&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And just like that, we have persistent storage of per-level data.&lt;/p&gt;
&lt;p&gt;Another clever and possibly questionable overloading of the &lt;code&gt;slug&lt;/code&gt; functionality is the way that the code chooses characters per level.&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;NSMutableArray&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;philly&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;
    &lt;span&gt;NSMutableArray&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;&lt;span&gt;levelArray&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[[[&lt;/span&gt;&lt;span&gt;NSMutableArray&lt;/span&gt; &lt;span&gt;alloc&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;init&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;retain&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;

    &lt;span&gt;[&lt;/span&gt;&lt;span&gt;levelArray&lt;/span&gt; &lt;span&gt;addObject&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;NSValue&lt;/span&gt; &lt;span&gt;valueWithPointer&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;self&lt;/span&gt; &lt;span&gt;businessman&lt;/span&gt;&lt;span&gt;]]];&lt;/span&gt;
    &lt;span&gt;[&lt;/span&gt;&lt;span&gt;levelArray&lt;/span&gt; &lt;span&gt;addObject&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;NSValue&lt;/span&gt; &lt;span&gt;valueWithPointer&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;self&lt;/span&gt; &lt;span&gt;youngPro&lt;/span&gt;&lt;span&gt;]]];&lt;/span&gt;
    &lt;span&gt;[&lt;/span&gt;&lt;span&gt;levelArray&lt;/span&gt; &lt;span&gt;addObject&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;NSValue&lt;/span&gt; &lt;span&gt;valueWithPointer&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;self&lt;/span&gt; &lt;span&gt;jogger&lt;/span&gt;&lt;span&gt;]]];&lt;/span&gt;

    &lt;span&gt;return&lt;/span&gt; &lt;span&gt;levelArray&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Each level has a function associated with it, simply named the same as the level&amp;#8217;s slug. Objective-C lets you call functions by string name pretty easily, which makes this work awesomely. This function calls a few others, each of which load a specified set of data encapsulating the differences between characters. Similar to the level structs, these character structs only hold the data indicating the important ways that the characters differ from each other - running speed, head bounciness, etc.&lt;/p&gt;
&lt;p&gt;Each of the characters also has a &amp;#8220;weight&amp;#8221;, which is used for probability weighting! Some characters show up more often than others (eg the cop and the hipster guy are rare). I might show that code in another post, but this one has enough code already.&lt;/p&gt;
&lt;p&gt;So there&amp;#8217;s a whirlwind tour of the level-storing logic in Heads Up. There&amp;#8217;s a lot of it, and aside from the game logic itself, this implementation probably took the most effort out of any in the app.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;~emmett&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;*Disclaimer: I realized how bad an idea this was long before I would have tried it. Don&amp;#8217;t worry.&lt;/em&gt;&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/35704155348</link><guid>http://emmett9001.tumblr.com/post/35704155348</guid><pubDate>Wed, 14 Nov 2012 09:06:20 -0500</pubDate></item><item><title>Diego and I demoing Heads Up Hot Dogs at the New York Tech...</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_mdhd3lP9RJ1qirv5co1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Diego and I demoing Heads Up Hot Dogs at the New York Tech Meetup.&lt;/p&gt;</description><link>http://emmett9001.tumblr.com/post/35703661697</link><guid>http://emmett9001.tumblr.com/post/35703661697</guid><pubDate>Wed, 14 Nov 2012 08:50:09 -0500</pubDate></item></channel></rss>
