<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CoronaSDK &#8211; Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<atom:link href="https://jessewarden.com/category/coronasdk-2/feed" rel="self" type="application/rss+xml" />
	<link>https://jessewarden.com</link>
	<description>Software &#124; Fitness &#124; Gaming</description>
	<lastBuildDate>Mon, 01 Sep 2014 01:10:36 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://jessewarden.com/wp-content/uploads/2016/08/cropped-Lambda2-32x32.png</url>
	<title>CoronaSDK &#8211; Software, Fitness, and Gaming &#8211; Jesse Warden</title>
	<link>https://jessewarden.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>One Game A Month &#8211; April Postmortem: Health Katas</title>
		<link>https://jessewarden.com/2013/05/one-game-a-month-april-postmortem-health-katas.html</link>
					<comments>https://jessewarden.com/2013/05/one-game-a-month-april-postmortem-health-katas.html#comments</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Sun, 05 May 2013 14:19:21 +0000</pubDate>
				<category><![CDATA[CoronaSDK]]></category>
		<category><![CDATA[1gam]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[corona]]></category>
		<category><![CDATA[coronasdk]]></category>
		<category><![CDATA[gaming]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[lua]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[onegameamonth]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[robotlegs]]></category>
		<guid isPermaLink="false">http://jessewarden.com/?p=3539</guid>

					<description><![CDATA[I&#8217;ve entered into the One Game a Month party. It&#8217;s like Ludum Dare, a challenge to make, and most importantly FINISH, a game in a set amount of time based on a theme. What makes #1GAM unique is you have an entire month and it spans an entire year. They have a thriving Twitter and [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve entered into the <a href="http://www.onegameamonth.com/">One Game a Month</a> party. It&#8217;s like <a href="http://www.ludumdare.com/compo/">Ludum Dare</a>, a challenge to make, and most importantly FINISH, a game in a set amount of time based on a theme. What makes #1GAM unique is you have an entire month and it spans an entire year. They have a thriving <a href="https://twitter.com/search?q=%231gam%20%23onegameamonth&amp;src=hash">Twitter</a> and <a href="https://plus.google.com/communities/117275686212402755276">Google+ group</a>.</p>
<p>I&#8217;ve entered strictly for learning purposes and to see if I can actually finish something. Game development is surprisingly very different from application development, and it&#8217;s nice to feel really stupid again.</p>
<p><span id="more-3539"></span><strong>Synopsis</strong></p>
<p>I fell back to my roots and attempted to build a mobile application that used &#8220;gamification&#8221;. Basically, you make the application fun through adding gaming elements to it. I&#8217;m good at building applications so figured if I fell back to my roots and adding just a little bit of game dev to it, I&#8217;d be able to create a lot more in the same period.</p>
<p>I changed my lifestyle last year in March of 2012 through adding fitness and changing my diet. A year later, I feel better and look better. I wondered how I could help others reach the same goals. While people tell you it&#8217;s 50% diet, 50% exercise, I felt for me 80% of the challenge was diet. I know nothing about cooking beyond what I&#8217;ve taught myself. My mom and grand mom taught me some stuff, but for whatever reason as I kid I just never really cared to better myself at it.</p>
<p>So, I made a list of all the smaller things I did that had longer term impact. I realize Type A Personality techniques of making huge changes with hardcore willpower are not the most effective way at changing people&#8217;s behavior. I&#8217;ve also read the statistics on how many actually keep weight off after they&#8217;ve lost it, and the time people devote to foodÂ preparationÂ vs.Â exercise. For Americans, it&#8217;s pretty dire. I took that list I wrote, and selected the ones that were the low hanging fruit, and hopefully easy attainable without requiring a Doctor&#8217;s note to attempt.</p>
<p>If you look at most nutrition advice, at least online or in books, it&#8217;s usually huge lifestyle changes. That&#8217;s asking a lot of people, and the #&#8217;s prove it doesn&#8217;t lead to longterm positive lifestyle changes. What DOES work is small habits that lead to longer term change. If you change a bunch of them, they collectively, slowly, lead to a more healthier, and more importantly, a self-empowered, individual. I started to make the application I wish I originally had: simple tips I could try everyday that didn&#8217;t totally shock my way of life, and that I could actually accomplish, and feel good about.</p>
<p><strong>Goals</strong></p>
<p>Give people simple healthy diet changes to try. From making people healthier, feel better, or empowering them to learn on their own. Giving someone 1 thing to try every day, even multiple times if they wished, to practice at being moreÂ healthy without having to focus 100% of their life on doing so. My hope was it&#8217;d be the least invasive thing in their life, thus hopefully maximizing the success rate. Kata&#8217;s are simpleÂ exercisesÂ you do in martial arts to practice and get better. I wanted something like that in a diet context vs. &#8220;OMG CHANGE YOUR LIFE!&#8221;</p>
<p>Additionally, they&#8217;d have both motivation in the form of videos and citations that show the positives of even minor diet changes as well as a world wideÂ achievementsÂ bored to see how many others had already accomplished each kata (or simpleÂ exerciseÂ  to also help with motivation.</p>
<p><strong>Actual Results</strong></p>
<p>I didn&#8217;t finish.</p>
<p>That said, all of the original katas are in the app, and you can try them, and have a record of your accomplishments. So it&#8217;s technically an early alpha, heh.</p>
<p><img fetchpriority="high" decoding="async" style="padding-left: 8px;" alt="" src="http://jessewarden.com/archives/blogentryimages/onegameamonth/apr/example-1.jpg" width="320" height="480" align="right" /></p>
<p>I ran out of time for motivations, and theÂ achievementsÂ board was slowed because it was the first time I used <a href="http://www.coronalabs.com/products/corona-cloud/">Corona&#8217;s Cloud</a> API.</p>
<p>The main problem with the data entered currently is that 3 important things are missing. I wanted to ensure all health recommendations I had were based on science that had at least 1 scientific study/citation. A lot of these studies are extremely wordy. Most people just want to know either WHY something isÂ healthy or how it&#8217;s POTENTIALLY healthy. The later is horrible in terms of how we humans operate, but it&#8217;s also a good tool to get people to do what you want them to do. Anyway, collecting +Â summarizingÂ all of that information is a ton of work. I&#8217;m constantly reading nutrition books and articles and taking notes, just not finished yet.</p>
<p>The other issue is turning those successes intoÂ congratulatoryÂ notes. When you complete a kata, you get a success message. For example, although I assumed users didn&#8217;t do drugs nor smoke, even just stopping smoking for example has a swath of awesome things that <a href="http://whyquit.com/whyquit/a_benefits_time_table.html">happen to your body</a>. It&#8217;s important you not only reward people forÂ accomplishingÂ the simpleÂ exercise, this builds self-confidence in them, but also you teach them WHY. Once someone knows the why and has self-confidence, change is afoot. Writing those is tough&#8230; even tweet size ones.</p>
<p>Finally, the questions are sometimes backwards; I need to add a boolean to the VO&#8217;s to say if yes leads to completing or starting the kata&#8230; or just make all the questions have &#8220;yes&#8221; lead to starting the kata. If you use the app now, just say yes to everything.</p>
<p><strong>What Went Wrong</strong></p>
<p>The main problems were:</p>
<ul>
<li><span style="line-height: 16px;">not enough free time</span></li>
<li>still learning nutritional science</li>
<li>Corona&#8217;s lack of basic GUI components and redraw invalidation</li>
<li>not enough documentation on Corona Cloud + having to learn a new API</li>
<li>Responsive Design</li>
<li>explaining to people how no longer eating their favorite unhealthy things is fun&#8230; in a mobileÂ application&#8230; yeah.</li>
</ul>
<p><strong>Free Time</strong></p>
<p>As usual, work both in client projects as well as outside took a lot of time. My main current client has a huge feature release coming up that we&#8217;ve all be tag teaming. This requires a lot of consistent communication as well as on-site visits which means I&#8217;m travelling a lot.Â I also travelled back to Georgia to sell my house. I&#8217;mÂ uncompromisingÂ in my workout schedule and picking up my kids from school which is 2 hours minimum a day. Also, it took me about 5 days to recover from March #1GAM burnout. Finally, <a href="http://webappsolution.com">my company</a> released the <a href="http://webappsolutioninc.github.io/flow-mvc">FlowMVC</a> framework based on the <a href="http://deftjs.org/">DeftJS</a> framework that all works atop <a href="http://www.sencha.com/">Sencha</a>, and that took a lot of time to ensure we got the alpha out as well.</p>
<p><strong>Nutrition Knowledge</strong></p>
<p>I&#8217;m notÂ classicallyÂ trained in nutrition, so am learning the same way I learned how to program: read online articles, read books, and asking questions of those who appear to be experts. Suffice to say it&#8217;s just as hard as programming to get to the real truth; it&#8217;s all masked in subjectivity and utter untruths. Making definitive statements is VERY hard to back up with science. America in particular has a ton of science around how to cure sickness, but very little on how to keep us not-sick via good nutrition. Frustrating. You have tread carefully when utilizing Qualitative science from qualified individuals. Bottom line there are a few facts, and a few of studies that reach conclusions but aren&#8217;t facts.</p>
<p>Sadly, a lot online is useless. At least with programming you can use sites like <a href="http://stackoverflow.com/">Stackoverflow.com</a>Â and communities that reference certain blogs/articles to find the good stuff. For nutrition, there are a few sites like that, but they don&#8217;t always cite their sources, nor differentiate between &#8220;the facts&#8221; and &#8220;the guesses based on the following studies which may/may not have contradictory studies&#8221;.</p>
<p>I wanted the app to have solid science, and getting solid science as a n00b is hard.</p>
<p><strong>Corona&#8217;s App State</strong></p>
<p>While Corona has made great strides on the widget front, their gaming focus, both as a company and in the runtime features are clearly biased. Even the <a href="https://github.com/coronalabs/framework-cloud">Corona cloud library</a> they posted on Github uses &#8220;name spacing&#8221;, aÂ pseudoÂ copy of how Python handles classes and packages. This, instead of using the proper class/module packages they introduced about a year ago. I reckon they did this to cater to game devs who freak out if you do 2 dots to get a &#8220;module&#8221; whereas for application developers, it&#8217;s just expected if you&#8217;re from a traditional OOP background and you get the time to actually think about class structure that often doesn&#8217;t change as much as it does in gaming.</p>
<p>This seems like a digression but it&#8217;s not; the simple fact they&#8217;re game focused makes even simple things application developers expect to be non-existent. For example, I DARE you to center a multiline block of text on the screen with arbitrary widths&#8230; and then put a different block of text in it. Works no problem in Flash/Flex and HTML(!). Corona doesn&#8217;tÂ recalculate/remeasure, and your registration point is off, and using simple x and width values to center the text suddenly fail. If you just create another text field, no problem, but even game developers know you object pool where possible.</p>
<p>Layout in this case is made worse as they abstract away device specific text fields. While it&#8217;s nice to use native device (iOS/Android) text fields that do render well, they don&#8217;t always render like you think on the simulator, namely the native options with backgrounds/borders disabled. Haveing to compile to view on the device is just awful. It defeats the whole purpose of Lua being an instantaneous code reload solution. If I wanted to recompile andÂ redeployÂ to the device, I&#8217;d use native XCode and Objective C.</p>
<p>These basic needs make building higher level abstractions that are actually efficient harder. As components scale in size and complexity,Â especiallyÂ data driven ones, you need some form ofÂ invalidationÂ routine. Invalidation is a huge topic <a href="http://jessewarden.com/2007/01/invalidation-strategies-for-flash-player.html">I&#8217;ve</a> <a href="http://jessewarden.com/2008/03/how-to-fix-the-flash-cs3-components.html">written</a> <a href="http://jessewarden.com/2005/06/dataselector-data-interaction-core-of-the-v2-framework-for-your-views.html">about</a> <a href="http://jessewarden.com/2009/03/creating-dynamic-lists-in-flex-flash.html">before</a>, but suffice to say it prevents common race conditions, is an efficient redrawÂ mechanismÂ for runtimes like Corona that share both code execution and redraw on the same thread (see <a href="http://updates.developmentarc.com/flex_4_lifecycle.pdf">elastic</a> <a href="http://www.quilix.com/node/61">race</a> <a href="http://books.google.com/books?id=Gn1fnqBIUEgC&amp;pg=PA363&amp;lpg=PA363&amp;dq=ted+patrick+elastic+racetrack&amp;source=bl&amp;ots=bfhJonDoW0&amp;sig=nyN5BaCrh1sEi7sJbpn3tF5v9Uk&amp;hl=en&amp;sa=X&amp;ei=iWWGUcL3OIeC8ATv44HYAQ&amp;ved=0CG0Q6AEwBg#v=onepage&amp;q=ted%20patrick%20elastic%20racetrack&amp;f=false">track</a> <a href="http://techie-jackie-blogs.blogspot.com/2012/11/elastic-racetrack-for-flash-9-and-avm2.html">articles</a>Â <a href="http://www.craftymind.com/2008/04/18/updated-elastic-racetrack-for-flash-9-and-avm2/">discussing</a>Â <a href="http://www.senocular.com/flash/tutorials/asyncoperations/">this</a>), and solve order of operation errors for developers using components that require multiple properties to be set to work.</p>
<p>I&#8217;m in the process of building one on top ofÂ theirÂ enterFrame, but it&#8217;s like a flash back to 2001 in Flash MX; i.e. it&#8217;s a lot of work for 1 person to complete. A company like Corona should have the resources to handle this. Either they don&#8217;t have the people working for them that know these problems, or they&#8217;re focused on other things. I think it&#8217;s the latter; game specific features like their 2.5 graphics and cloud initiatives whilst open sourcing the components are signs. That&#8217;s fine, but oy vey&#8230; pain&#8230;</p>
<p>Another annoying thing is some widgets/components don&#8217;t work with groups. I get why, but this makes layout a royal journey into frustration and workarounds, and just generally nasty looking code.</p>
<p>I will say the widgets they DO have are great overall and <a href="https://github.com/coronalabs/framework-widgets">open sourcing</a> them was a dope move. The API consistency, while I get challenging, needs to be improved in both the libraries they distribute and in their internal SDK.</p>
<p><strong>Responsive Design (lack thereof)</strong></p>
<p>Because of the above crunch, I didn&#8217;t get a very responsive design. This lead to some devices not scaling properly&#8230; which sucked. For games, you can just scale up or down; Corona does this automatically. For applications, however, you basically do a &#8220;<a href="http://en.wikipedia.org/wiki/Responsive_web_design">responsive </a><a href="http://mashable.com/2012/12/11/responsive-web-design/">design</a>&#8220;. While most web sites prefer to use <a href="http://alistapart.com/article/responsive-web-design">media queries</a> and <a href="http://www.html5rocks.com/en/mobile/responsivedesign/">funky</a> <a href="http://alistapart.com/article/fluidgrids">fontÂ measurements</a>Â to accomplish this, using things like Sencha, Flex, or even Corona, and you can simply have each component size itself and it&#8217;s children. As the application grows, this works out well because they&#8217;ll fill whatever space you tell them too.</p>
<p>The kicker here is &#8220;if the design supports it&#8221;. For example a toolbar can scale infinitely horizontally, but tends to stay 60 pixels high. On most smartphones, this is fine, but on tablets,Â especiallyÂ the high rez ones, it gets a bit too small to work. At that point you fall back to another nav. I didn&#8217;t even get that far&#8230; as soon as I went from a Nexus One to a Droid X, my app couldn&#8217;t even handle the extra 24 pixels.</p>
<p>I put a 640&#215;960 mask on stage and called it a day.</p>
<p><strong>Corona Cloud</strong></p>
<p><a href="http://coronalabs.com/blog/2013/03/20/corona-cloud-1-0-is-here/">Corona Cloud</a> is awesome. The documentation is ok. The example code is awesome, although completely ignores Corona&#8217;s package structure and they&#8217;ve foregone using metatable vs. closure based classes for the same reason a lot of JavaScript libraries do the &#8220;large object on global window&#8221; to avoid the closure vs. Object.prototype debates. Anyway, nothing major here, just hard to learn a new API in such a short time frame with all the other challenges going on, thus compounding it.</p>
<p><strong>Making Health Fun</strong></p>
<p>For me, I was sick and tired of being sick and tired. Once I make my mind up, there&#8217;s no changing my mind. I have discipline with certain things I set my mind to. I get that to make broader changes to the world, you need to be moreÂ pragmaticÂ about what you expect out of the general populace. I took the approach of &#8220;simple with positive messaging as instant reward and global awareness through achievements of other users&#8221;. The &#8220;simple&#8221; was simple, the CoronaÂ cloudÂ achievements isn&#8217;t something I need but totally get how others need thatÂ motivation.</p>
<p>The &#8220;positive messaging&#8221; though is rough. When you look at the back of a &#8220;Matt&#8217;s Organic Orange Juice&#8221; container for example, they&#8217;ll go off about Vitamin D, and how it&#8217;s greatest thing for you evarrr. It clearly was written by a talented marketing copy writer and put through a few revisions. Trying to do that, for every single kata, was rough. As you can see, I can write a lot, but saying a lot with few words is HARD. Fun, but hard.</p>
<p><strong>What Went Right</strong></p>
<p><img decoding="async" style="padding-right: 8px;" alt="" src="http://jessewarden.com/archives/blogentryimages/onegameamonth/apr/example-2.jpg" width="320" height="480" align="left" />Finding a fitting design and icons I needed on <a href="http://graphicriver.net/">GraphicRiver</a> was <a href="http://graphicriver.net/item/zweir-complete-mobile-interface/2617224">uber</a> <a href="http://graphicriver.net/item/70-food-and-drink-icons/3543222">easy</a>. Getting the design to work in Corona, my component issues non-withstanding, also easy.</p>
<p>Setting up the MVC structure, also easy. I hadn&#8217;t messed with my port of <a href="https://github.com/JesterXL/Robotlegs-for-Corona">Robotlegs for Corona</a> for almost 2 years(!) since those kind of frameworks are more used for applications and less so games, so took the opportunity to bring it up to speed.</p>
<p>Coming up with simple things that are healthy for people to try was actually pretty easy as well. I just charted my own path andÂ rememberedÂ all the hard things I did, and modified the order based onÂ difficulty and organized into levels of lifestyle impact. The app was responsive on the device, and I only had minor masking problems with the Corona widgets. Once I got some good low level components, building the GUI&#8217;s was pretty quick and easy.</p>
<p><strong>Key Takeaways</strong></p>
<p>I think like my Februrary entry, I&#8217;d like to come back to this, finish it, and polish it. Even in application development, you can get into &#8220;the grind&#8221;, the last, brutal 10%. It&#8217;s easier to power through if you believe in the final product.</p>
<p>It&#8217;s also clear I shouldn&#8217;t do anything more GUI heavy without a Corona component framework ready before I start. Oh goody, another side project! *face palm*</p>
<p>I need to organize my notes about nutrition more. Most of it is for me related to fitness vs. justÂ pragmaticÂ well being. That and I forget what research/study/book told me what, and whether it was a &#8220;study&#8221; vs. a &#8220;paper&#8221; vs. a &#8220;theory&#8221; vs. a &#8220;scientific fact&#8221;&#8230; which greatly affects the other research/beliefs it&#8217;s related to. Like programming.</p>
<p>Finally, I need more time with Corona Cloud. It&#8217;s really cool, just haven&#8217;t had enough time to play to learn it more.</p>
<p><strong>Conclusions</strong></p>
<p>May: Go back to the 2D side scroller. From myÂ FebruaryÂ entry, it&#8217;s clear I liked making Box2D levels, and need more practice in making them, even if I don&#8217;t finish.</p>
<p>Once again, I&#8217;m burnt, and need a few days to recover. This time, though, I knew it was coming and planned for it: notes for May dev all ready, concepts documented from awhile ago when I&#8217;m ready to nail down an idea, and tons of alcohol and XBox games while I recover.</p>
<p>The <a href="https://github.com/JesterXL/Health-Katas">source code</a> is up on Github and you can <a href="https://play.google.com/store/apps/details?id=com.jessewarden.healthkatas">install on your Android device here</a>Â (although I&#8217;d wait until the version says &#8220;beta&#8221; hah).</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2013/05/one-game-a-month-april-postmortem-health-katas.html/feed</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
		<item>
		<title>Finite State Machines in Game Development</title>
		<link>https://jessewarden.com/2012/07/finite-state-machines-in-game-development.html</link>
					<comments>https://jessewarden.com/2012/07/finite-state-machines-in-game-development.html#comments</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Mon, 09 Jul 2012 15:59:09 +0000</pubDate>
				<category><![CDATA[CoronaSDK]]></category>
		<category><![CDATA[Gaming]]></category>
		<category><![CDATA[corona]]></category>
		<category><![CDATA[coronasdk]]></category>
		<category><![CDATA[designpatterns]]></category>
		<category><![CDATA[gaming]]></category>
		<category><![CDATA[lua]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[statemachines]]></category>
		<guid isPermaLink="false">http://jessewarden.com/?p=3219</guid>

					<description><![CDATA[Finite State Machines are series of design patterns often used in Game Development. In this article I&#8217;ll define what they are &#038; how they work, go over 3 example implementations I have implemented in Corona SDK, and describe some of the pain points I&#8217;ve encountered using them. I&#8217;ve ported Cassio Souza&#8217;s ActionScript 3 State Machine [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://jessewarden.com/2012/07/finite-state-machines-in-game-development.html"><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/finitestatemachines-logo.jpg" style="padding-right: 8px;" width="320" height="204" align="left" /></a>Finite State Machines are series of design patterns often used in Game Development. In this article I&#8217;ll define what they are &#038; how they work, go over 3 example implementations I have implemented in <a href="http://coronalabs.com">Corona SDK</a>, and describe some of the pain points I&#8217;ve encountered using them.</p>
<p>I&#8217;ve ported Cassio Souza&#8217;s <a href="https://github.com/cassiozen/AS3-State-Machine">ActionScript 3 State Machine</a> to a <a href="https://github.com/JesterXL/Lua-Corona-SDK-State-Machine">Lua State Machine</a>, and recently a <a href="https://pub.dartlang.org/packages/jxlstatemachine">Dart version</a>, and included examples. This article has a companion video embedded below.</p>
<p>&nbsp;</p>
<p><iframe loading="lazy" width="640" height="360" src="http://www.youtube.com/embed/ShfT7HiXk3s" frameborder="0" allowfullscreen></iframe></p>
<p><span id="more-3219"></span><strong>What Are State Machines</strong></p>
<p>At their simplest form, State Machines are an <a href="http://en.wikipedia.org/wiki/Observer_pattern">Observer pattern</a> with 2 values they watch internally: an Entity and the Current State. Whenever someone, somewhere changes the internal state, it&#8217;ll let the world know.</p>
<p>The high level parts are:</p>
<ol>
<li>States which contain/define the behavior for the Entity</li>
<li>Transitions which occur when one State changes to another</li>
<li>Rules which define which States can change to certain other States</li>
<li>Events which are internally or externally dispatched which trigger State Transitions</li>
</ol>
<p>When creating State Machines, you usually know all the states up front, hence the word finite. Whether a list on paper or a bunch of boxes on a flow chart with arrows denoting where you can go from where. Some states can have parent child relationships. There can be a variety of rules that allow/prevent some states from changing to others can causing state transitions.</p>
<p><strong>Why Use State Machines</strong></p>
<p>There are 3 use cases State Machines. These are Artificial Intelligence, modeling simulations, and a refactoring path for game entities.</p>
<p>For AI programming, you have the choice of deterministic or non-deterministic. Most video games have deterministic; meaning you know how the enemies will react based on different inputs. If they don&#8217;t see you, they&#8217;ll patrol. If they see you, they&#8217;ll attack you. If you hide and wait, they&#8217;ll eventually go back to patrolling. You can simulate fuzzy logic by using random numbers to change state to something random. For example, sometimes the enemy could use a grenade vs. a gun, or attack you immediately vs. sounding the alarm&#8230; or even run away to get reinforcements. Sometimes they could even talk to you instead. This randomness makes a State Machine non-deterministic, meaning you know all the States, but you don&#8217;t know exactly all the paths between States.</p>
<p>For modeling simulations, whether complex machinery, or situations, you often have a ton of moving parts. You&#8217;re interested in the potential interactions when certain things are in certain states. Sometimes you want these situations to be repeatable.</p>
<p>For example, for simulating hardware of large steel manufacturing machinery for training purposes, you want to setup the machine either in a specific state, or towards one to teach a new operator how to handle a certain negative situation in a safe environment to learn. You start a predefined set of actions to get the machine in a state where something bad is about to happen, and the operator has to learn how to push the right buttons or turn the right knobs to stop things from going bad.</p>
<p>You can do the same at a macro level for emulating events. Think SimCity.</p>
<p>This is also why unit testing deterministic state machines is pretty easy, albeit not as fun as non-deterministic, because you know all the paths ahead of time and the potential interactions.</p>
<p>For the purpose of this article, we&#8217;re concerned with refactoring paths for game entities. Specifically, &#8220;dude, this code is too complex to manage and there are 50 billion boolean flags/if then statements to deal with&#8230;&#8221;. Using State Machines makes your code more manageable as it grows, more organized, and easier to debug.</p>
<p><strong>Behavior in a Class vs. Behavior in States</strong></p>
<p>Alan Skorkin has <a href="http://www.skorks.com/2011/09/why-developers-never-use-state-machines/">a great article</a> on why developers often don&#8217;t use state machines. While he&#8217;s referring to software development as a whole, not just game development, he brings up a lot of valid points. Specifically, <a href="http://www.skorks.com/2009/08/does-yagni-mean-you-ignore-the-obvious/">YAGNI</a>, or if you don&#8217;t know ahead of time you&#8217;ll have a lot of behavior, you start out building only what you need. The issue becomes down the line, the effort towards refactoring it to a proper state machine is a lot of work.</p>
<p>I experienced this from 2 angles. The first is what got me interested in state machines in the first place. My game entities were getting uber complex, and I asked around for advice. Colleagues recommended Finite State Machines to solve all my problems. During the refactoring, I started to learn why they&#8217;re great for lots of behavior in known states.</p>
<p>I then tried implementing one in a brand new code base with only a little behavior&#8230; and it was overly complex. Then I reached this mid-point where the complexity was hard to manage, but I didn&#8217;t want to go back to a State Machine again.</p>
<p>So I&#8217;ve had a frustrating experience and an extremely positive one.</p>
<p>You can see a <a href="https://github.com/JesterXL/ZombieStick/blob/1fdc7a46268f4677eeba41d8512a44d5f9dde33d/code/com/jxl/zombiestick/players/PlayerJXL.lua">before</a> and <a href="https://github.com/JesterXL/ZombieStick/blob/248de162452018834d4765638a0dad393f8b042a/code/com/jxl/zombiestick/players/PlayerJXL.lua">after</a> example of how State Machines can really make your game entity classes smaller and more manageable as their behavior grows.</p>
<p><strong>Example 1: Simple State &#8211; Event Handler</strong></p>
<p>Let&#8217;s show a simple <a href="http://en.wikipedia.org/wiki/1942_(video_game)">1942</a> &#8216;esque example in Lua. You have an overhead view of an airplane that has 3 firing modes: a single bullet, faster dual-bullets, and a 3 pronged super-fast bullet mode.</p>
<p>From our state flow chart below, you can see we have 3 states, with Fire 1 being the initial state. The events between states are when the plane touches a power up. If the plane hits an enemy, they&#8217;ll go back a state, from Fire 3 to Fire 2 and from Fire 2 to Fire 1.</p>
<p><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/flowchart-01.jpg" /></p>
<p>Now let&#8217;s setup our State Machine:</p>
<pre lang="lua">fireFSM = StateMachine:new()
fireFSM:addState("fire1", {from="*"})
fireFSM:addState("fire2", {from="*"})
fireFSM:addState("fire3", {from="*"})
fireFSM:setInitialState("fire3")
fireFSM:addEventListener("onStateMachineStateChanged", onChangePlayerFireFunction)</pre>
<p>Whenever anyone changes the fireFSM, it&#8217;ll dispatch the &#8220;onStateMachineStateChanged&#8221; event. We can then set the Entity&#8217;s proper fire function as well as the speed at which it should fire at in milliseconds.</p>
<pre lang="lua" line="67">function onChangePlayerFireFunction(event)
   local fireFunkyFunk
   local state = fireFSM.state
   local fireSpeed
   if state == "fire1" then
      fireFunkyFunk = player.fire1
      fireSpeed = 300
   elseif state == "fire2" then
      fireFunkyFunk = player.fire2
      fireSpeed = 200
   elseif state == "fire3" then
      fireFunkyFunk = player.fire3
      fireSpeed = 150
   end
   player.fire = fireFunkyFunk
   player.FIRE_TIME = fireSpeed
end</pre>
<p>Notice we inspect what the new state is at line 69. From there it&#8217;s just a simple switch statement to determine which firing mode to switch to. Notice we actually set the data on the Entity itself, in this case &#8220;player&#8221;. The player then uses this data in his game tick (slang for a function that fires when the Game Loop decides it&#8217;s time for your game object to do something). Like so:</p>
<pre lang="lua" line="139">function player:tick(millisecondsPassed)
   if self.firing == true then
      self.startFireTime = self.startFireTime + millisecondsPassed
      if self.startFireTime >= self.FIRE_TIME then
         self.startFireTime = 0
         self:fire()
      end
   end</pre>
<p>Notice line 144. The player/plane doesn&#8217;t know what fire actually is, it just executes it every time it&#8217;s allowed to fire. If you change it to a different fire function, it&#8217;ll use that one. Let&#8217;s take a look at those. Here&#8217;s fire1, which fires a single bullet every 300 milliseconds:</p>
<pre lang="lua" line="170">function player:fire1()
   local bullet = getBasicBullet("player_bullet_1.png", self.x + self.width / 2, self.y)
end</pre>
<p>In game, it&#8217;ll look like this:</p>
<p><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/fire1.jpg" /></p>
<p>If we press the Fire 2 button (which simulates getting a power up), it&#8217;ll change the Entity&#8217;s fire reference to the fire2 function:</p>
<pre lang="lua">function player:fire2()
   local bullet = getBasicBullet("player_bullet_2.png", self.x, self.y)
   bullet.x = bullet.x + bullet.width / 2
end</pre>
<p>The only difference here is a different image which is larger, and we center it on the player.</p>
<p><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/fire2.jpg" /></p>
<p>Finally, if we hit the Fire 3 button, it&#8217;ll change it to the fire3 function.</p>
<pre lang="lua">function player:fire3()
   local bullet1 = getBasicBullet("player_bullet_1.png", self.x, self.y)
   bullet1.rotation = -45
   bullet1.rot = math.atan2(bullet1.y -  -800,  bullet1.x - -800) / math.pi * 180 -90;
   bullet1.angle = (bullet1.rot -90) * math.pi / 180;

   local bullet2 = getBasicBullet("player_bullet_1.png", self.x, self.y)
   bullet2.rotation = 45
   bullet2.rot = math.atan2(bullet2.y -  -800,  bullet2.x - -800) / math.pi * 180 -90;
   bullet2.angle = (bullet2.rot) * math.pi / 180;
   
   -- override the functions with these instead
   function bullet1:tick(millisecondsPassed)
      self.x = self.x + math.cos(self.angle) * self.speed * millisecondsPassed
         self.y = self.y + math.sin(self.angle) * self.speed * millisecondsPassed
   end
   
   function bullet2:tick(millisecondsPassed)
      self.x = self.x + math.cos(self.angle) * self.speed * millisecondsPassed
         self.y = self.y + math.sin(self.angle) * self.speed * millisecondsPassed
   end

   local bullet3 = getBasicBullet("player_bullet_1.png", self.x + self.width / 2, self.y)
end</pre>
<p>Which looks like:</p>
<p><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/fire3.jpg" /></p>
<p>Again, the sequence of events for hitting the Fire 2 button are:</p>
<ol>
<li>fireFSM:setInitialState(&#8220;fire1&#8221;) puts the State Machine in the initial fire 1 state.</li>
<li>When you press the Fire 2 button, it&#8217;ll call fireFSM:changeState(&#8220;fire2&#8221;)</li>
<li>The State Machine internally will dispatch the change event &#8220;onStateMachineStateChanged&#8221;</li>
<li>In our event handler for it, we&#8217;ll inspect what the new state is, and assign the appropriate fire function.</li>
</ol>
<p>&nbsp;</p>
<p><strong>Example 1: Simple State &#8211; Event Handlers</strong></p>
<p>While using a change event is simple and results in 1 function, what if you have a lot of states? This is where using enter/exit handlers helps you organize your code more and it scales better. Taking our exact same example above, instead of using our onChangePlayerFireFunction to listen for the State Machine&#8217;s &#8220;onStateMachineStateChanged&#8221; event:</p>
<pre lang="lua">fireFSM:addEventListener("onStateMachineStateChanged", onChangePlayerFireFunction)</pre>
<p>We&#8217;ll instead use an enter handler instead, like so:</p>
<pre lang="lua">fireFSM:addState("fire1", {from="*", enter=onEnterStateFire1})
fireFSM:addState("fire2", {from="*", enter=onEnterStateFire2})
fireFSM:addState("fire3", {from="*", enter=onEnterStateFire3})</pre>
<p>Now, this results in 3 organized functions that are a lot smaller and easier to read. It&#8217;s also obvious what they do based on the naming convention:</p>
<pre lang="lua">function onEnterStateFire1(event)
   player.fire = player.fire1
   player.FIRE_TIME = 300
end

function onEnterStateFire2(event)
   player.fire = player.fire2
   player.FIRE_TIME = 200
end

function onEnterStateFire3(event)
   player.fire = player.fire3
   player.FIRE_TIME = 150
end</pre>
<p><strong>Example 2: Hierarchical State Machine</strong></p>
<p>There are a variety of benefits using a hierarchical State Machine; a State Machine where States have parent child relationships.</p>
<p>First, it helps <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a> your code. There are a lot of things some states have in common so you can run that initialization code once. Same goes for destroy/clean up code.</p>
<p>Secondly, it helps you organize your code; ie &#8220;Attacking code goes in this section whereas Defending code goes over here&#8221;.</p>
<p>Third, a State Machine can help you enforce paths to go from child to parent to sibling to child. Just like in <a href="http://en.wikipedia.org/wiki/StarCraft">Starcraft</a>, a Siege Tank must first transform to assault mode from the siege mode before it can actually move and fire again.</p>
<p><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/siege-tank.jpg" /></p>
<p>The State Machine will throw errors if you attempt to move to an illegal path which helps you correct your code. It will also showcase missing transitions if you forgot one. Why are paths important? Just like we can&#8217;t go from Siege Mode to Move Mode using a Starcraft Siege tank, we don&#8217;t want our War Robot in Example 2 going from Artillery Mode to Move Mode. There is some time it takes to get setup for long range artillery strikes, as well as getting out of artillery mode. Our example does NOT enforce this but gives you the mechanisms to do so to ensure the player cannot do anything whilst transitioning from one State to the next.</p>
<p>Here&#8217;s the flow chart for Example 2, where our War Robot can be an upright walking robot for recon, a defense mode for holding up shields to protect itself, and an assault mode with 3 firing modes: laser sight, sniper, and artillery (click for larger version).</p>
<p><a href="http://jessewarden.com/archives/blogentryimages/finitestatemachines/flowchart-02.jpg"><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/flowchart-02-preview.jpg" /></a></p>
<p>We&#8217;ll set up our State Machine much like before in Example 1, except here we&#8217;ll use a new parameter called &#8220;parent&#8221; like so:</p>
<pre lang="lua">botFSM:addState("scout", {from={"defend", "assault"}, enter=onEnterScout})
botFSM:addState("scoutLeft", {parent="scout", from="scoutRight", enter=onEnterScoutLeft, exit=onExitScoutLeft})
botFSM:addState("scoutRight", {parent="scout", from="scoutLeft", enter=onEnterScoutRight, exit=onExitScoutRight})

botFSM:addState("defend", {from={"scout", "assault"}, enter=onEnterDefendState, exit=onExitDefendState})

botFSM:addState("assault", {from={"scout", "defend"}, enter=onEnterAssaultState, exit=onExitAsstaultState})
botFSM:addState("assaultLeft", {parent="assault", from="assaultRight", enter=onEnterAssaultLeft, exit=onExitAssaultLeft})
botFSM:addState("assaultRight", {parent="assault", from="assaultLeft", enter=onEnterAssaultRight, exit=onExitAssaultRight})
botFSM:addState("sight", {parent="assault", from={"sniper", "artillery"}, enter=onEnterSightState, exit=onExitSightState})
botFSM:addState("sniper", {parent="assault", from={"sight", "artillery"}, enter=onEnterSniperState, exit=onExitSniperState})
botFSM:addState("artillery", {parent="assault", from={"sniper", "sight"}, enter=onEnterArtilleryState, exit=onExitArtilleryState})

botFSM:setInitialState("scout")</pre>
<p>Notice our 3 main States (Scout, Defend, and Assault) clearly define which states they are allowed to be transitioned to via the from parameter. Also notice some special things about the parent parameter. The &#8220;scoutLeft&#8221; State, a child of &#8220;scout&#8221;, does not have to define its parent in the from parameter. It&#8217;s implied in the State Machine that a child state is allowed to be transitioned to by its parent. Finally, notice the use of exit to define exit handlers.</p>
<p>All this setup defines our states, their children, and who&#8217;s allowed to transition to whom. All of this matches our flow chart.</p>
<p>Our Entity, the WarBot class, is handling all the actual animations and storing the data and handling how the behavior works. What behavior it does, and when, is controlled by the State enter and exit functions. The how is affected by its internal variables, also changed by the State changes.</p>
<p>Let&#8217;s take a look at what happens when you enter the parent &#8220;scout&#8221; State by pressing the &#8220;Scout&#8221; button:</p>
<pre lang="lua">function onEnterScout()
   warBot:showSprite("scout")
   warBot:setSpeed(4)
end</pre>
<p>It shows the scout sprite sheet and sets the speed to 4. If you press the &#8220;Scout Right&#8221; button, it&#8217;ll botFSM:changeState(&#8220;scountRight&#8221;) and call:</p>
<pre lang="lua">function onEnterScoutRight()
   warBot:showSprite("scoutRight")
   warBot:setDirection("right")
   warBot:startMoving()
end</pre>
<p>This shows the scoutRight sprite sheet which is an animation of the robot running right. It also ensures it is facing the right direction and informs it needs to start animating. If you let go/stop touching the &#8220;Scout Right&#8221; button, it&#8217;ll go back to the parent &#8220;scout&#8221; state.</p>
<pre lang="lua">function onExitScoutRight()
   warBot:showSprite("scout")
   warBot:stopMoving()
end</pre>
<p>Notice that this does NOT fire an onExitScout function; you&#8217;re still technically in the scout state since scoutLeft and scoutRight are its children. It looks like so:</p>
<p><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/scoutmove.jpg" /></p>
<p>Let&#8217;s take a look at the Defense State. He&#8217;s unique in that he doesn&#8217;t care where you came from; as soon as you let go of the Defend button, it&#8217;ll go to whatever the previousState was. Also of note, he&#8217;ll set some initial defense and speed variables (speed to 0 because you can&#8217;t move while in Defend State):</p>
<pre lang="lua">function onEnterDefendState()
   warBot:showSprite("defend")
   warBot:setDefense(10)
   warBot:setSpeed(0)
end</pre>
<p>Notice we didn&#8217;t define an onExitDefendState. It&#8217;s assumed whatever State you&#8217;re going to will handle setting the speed &#038; defense to the appropriate values.</p>
<p>Finally, we&#8217;re offloading a lot of the actual details of firing bullets, laser sights, etc. onto the Entity. Notice how all 3 of the Assault&#8217;s child modes tell the Entity to start or stop showing these effects. The benefit is you don&#8217;t have to worry about checking boolean flags before you run them; you can be sure the State Machine will only start and stop each one at the appropriate time. &#8230; Usually, heh.</p>
<p>Here&#8217;s Sniper mode&#8217;s enter and exit:</p>
<pre lang="lua">function onEnterSniperState()
   warBot:showSprite("sniper")
   warBot:setSpeed(0)
   warBot:startSniperShooting()
end

function onExitSniperState()
   warBot:showSprite("sniperReverse")
   warBot:stopSniperShooting()
end</pre>
<p>Standard stuff here; show the correct sprite sheet, set the speed to 0 when you enter, and telling the entity to start handling touch events as sniper shots. When it exits, it shows the revert animation, and stops handling touch events as sniper shots.</p>
<p><strong>State Changes Observer &#038; Path Enforcement</strong></p>
<p>Remember, the State Machine will both enforce the state paths you put in from as well as dispatch an event. Since it&#8217;s an observer, others can listen to these State changes as well. The ButtonsController we have listens to the state changes and only shows the appropriate buttons that mach our flow chart rules.</p>
<p>We give the ButtonsController a reference to the State Machine:</p>
<pre lang="lua">buttons:setStateMachine(botFSM)</pre>
<p>He&#8217;ll then add an event listener to it and initialize himself to the current state:</p>
<pre lang="lua">function buttons:setStateMachine(fsm)
   if self.stateMachine then
      self.stateMachine:removeEventListener("onStateMachineStateChanged", self)
   end
   self.stateMachine = fsm
   if fsm then
      fsm:addEventListener("onStateMachineStateChanged", self)
   end
   self:onStateMachineStateChanged()
end</pre>
<p>Now, instead of checking a bunch of rules to ensure they match our flow chart, we instead just only show the buttons you&#8217;re allowed to press in certain states:</p>
<pre lang="lua">function buttons:onStateMachineStateChanged(event)
   local state = self.stateMachine.state
   self:hideAllButtons()
   if state == "scout" or state == "scoutLeft" or state == "scoutRight" then
      self.walkLeftButton.isVisible = true
      self.walkRightButton.isVisible = true
      self.defendButton.isVisible = true
      self.attackButton.isVisible = true
   elseif state == "defend" then
      self.defendButton.isVisible = true
   elseif state == "assault" then
      self.rollLeftButton.isVisible = true
      self.rollRightButton.isVisible = true
      self.defendButton.isVisible = true
      self.scoutButton.isVisible = true
      self.sightButton.isVisible = true
      self.sniperButton.isVisible = true
      self.artilleryButton.isVisible = true
   elseif state == "assaultLeft" or state == "assaultRight" then
      self.rollLeftButton.isVisible = true
      self.rollRightButton.isVisible = true
      self.scoutButton.isVisible = true
   elseif state == "sight" or state == "sniper" or state == "artillery" then
      self.attackButton.isVisible = true
   end
end</pre>
<p>This makes your changing the State Machine really easy because you don&#8217;t have to put tests in there; you just react and change it to match the flow chart. Here&#8217;s how moveRight works; if you press the button, it sets it to moveRight, and when you let go, it goes back to scout:</p>
<pre lang="lua">function buttons:onMoveRight(event)
   if event.phase == "began" then
      self.stateMachine:changeState("scoutRight") 
   elseif event.phase == "ended" or event.phase == "cancelled" then
      self.stateMachine:changeState("scout") 
   end
end</pre>
<p><strong>Example 3: Class Based States</strong></p>
<p>Last up is the class version of the State Machine examples. My version of Classes in Lua are just <a href="http://jessewarden.com/2011/10/lua-classes-and-packages-in-corona.html">tables using closures</a> for scope reasons.</p>
<p>The class approach has some advantages. First, as your code grows in size, it&#8217;s easier to scale. You can utilize inheritance and packages help keep it clean, organized, and DRY. This also makes code reuse slightly easier as well. In the first 2 examples, you can see how the actual behavior implementation is separate from the State Machine, in main.lua. It&#8217;s not really grouped together in any organized fashion.</p>
<p>The second advantage is, like the enter and exit functions, the class only handles that behavior in which it is responsible for. If you look in Example 2, you&#8217;ll notice the WarBot, although not determining his behavior, is still responsible for setting himself up internally for it. Using classes, you offload the majority of that code to the appropriate state responsible for it.</p>
<p>The third advantage is leveraging Corona&#8217;s event system. States can both react to events from the global event bus, <a href="http://developer.coronalabs.com/reference/index/events/runtime/runtimeaddeventlistener">Runtime</a>, as well as dispatch their own in case other State Machines need to know about something. This allows a loose coupling for inter-State Machine communication.</p>
<p>Downsides are moar code which requires moar unit tests which in turn is moar code. This is moar complexity which can result in a lower iteration speed. Not always ideal for games. I like it, though, coming from an <a href="http://en.wikipedia.org/wiki/Object-oriented_programming">OOP</a> background.</p>
<p>Let&#8217;s start with a really simple State Machine: a character that can move left, right, jump, and attack.</p>
<p><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/example3.jpg" /></p>
<p>And here&#8217;s the flow chart with the State paths. Notice if the character sits still, he can rest. That&#8217;s it (click for larger image).</p>
<p><a href="http://jessewarden.com/archives/blogentryimages/finitestatemachines/flowchart-03.jpg"><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/finitestatemachines/flowchart-03-preview.jpg"></a></p>
<p>Setting up the State Machine is only slightly different; you use addState2, and put a class instance inside it, like so:</p>
<pre lang="lua">fsm:addState2(ReadyState:new())
fsm:addState2(RestingState:new())
fsm:addState2(MovingRightState:new())
fsm:addState2(MovingLeftState:new())
fsm:addState2(JumpLeftState:new())
fsm:addState2(JumpRightState:new())
fsm:addState2(AttackState:new())
fsm:setInitialState("ready")

gameLoop:addLoop(fsm)</pre>
<p>Also note I added it to the Game Loop. I default all States to have a tick method so they can tap into the global Game Loop as well.</p>
<p>Pay special note to the setInitialState; it takes a String name. I used a convention to keep the the API the same: ReadyState becomes &#8220;ready&#8221;, MovingRightState becomes &#8220;movingRight&#8221;, etc. All classes use their name in the constructor so the State Machine knows what their name is.</p>
<p>In a State class, you just import the base class, extend it, and pass in your name.</p>
<pre lang="lua">require "com.jessewarden.statemachine.BaseState"
ReadyState = {}

function ReadyState:new()
   local state = BaseState:new("ready")</pre>
<p>From there, you can do whatever you wish. The standard methods to implement are onEnterState, onExitState, and tick. All State class have references to the Entity they are dealing with as well as the State Machine they are within as illustrated in the tick function getting local references to it:</p>
<pre lang="lua">function state:onEnterState(event)
end

function state:onExitState(event)
end

function state:tick(time)
   local player = self.entity
   local stateMachine = self.stateMachine
end</pre>
<p>Let&#8217;s take a look at the ReadyState&#8217;s onEnterState function. He states the Entity is not recharging his stamina, resets the internal rest timer (since you have to sit still for 3 seconds to trigger a State transition to the RestingState), and listens for global events that can trigger other, valid State transitions.</p>
<pre lang="lua">function state:onEnterState(event)
   local player = self.entity
   self.recharge = false
   
   self:reset()
   
   player:showSprite("stand")
   
   Runtime:addEventListener("onMoveLeftStarted", self)
   Runtime:addEventListener("onMoveRightStarted", self)
   Runtime:addEventListener("onAttackStarted", self)
   Runtime:addEventListener("onJumpLeftStarted", self)
   Runtime:addEventListener("onJumpRightStarted", self)
end</pre>
<p>That last part is the key. I don&#8217;t care where these events come from, I just know, if someone, somewhere says that onMoveLeftStarted, then this State class will react and say, &#8220;Ok, go ahead and change the state to the moveLeft state then.&#8221;:</p>
<pre lang="lua">function state:onMoveLeftStarted(event)
   self.stateMachine:changeStateToAtNextTick("movingLeft")
end</pre>
<p>Notice here there are no rules enforcement. They&#8217;re entirely up to you in an opt-in way. If you do not handle, or allow a State transition here, none occurs. It&#8217;s up to your class to opt in and allow State transitions. Conversely, you can have someone else with a reference to the State Machine to actually change the states; up to you. The downside here is no help from the State Machine to see if your States actually match what&#8217;s in your flow chart. I&#8217;ve thought about adding a way to declaratively add them just like you did in Example 1 and 2.</p>
<p>The JumpLeftState shows the power of inheritance at work:</p>
<pre lang="lua">require "states.JumpState"

JumpLeftState = {}

function JumpLeftState:new()
   local state = JumpState:new("jumpLeft")
   
   state.superOnEnterState = state.onEnterState
   function state:onEnterState(event)
      self:superOnEnterState(event)
      
      local player = self.entity
      player:setDirection("left")
   end
   
   state.superOnExitState = state.onExitState
   function state:onExitState(event)
      local player = self.entity
      player:applyLinearImpulse(-player.jumpForwardForce / 3, 0, 40, 32)
      self:superOnExitState(event)
   end
   
   state.superTick = state.tick
   function state:tick(time)
      local player = self.entity
      player.x = player.x + -(player.jumpForwardForce)
      self:superTick(time)
   end
   
   return state
   
end

return JumpLeftState</pre>
<p>He extends the base JumpState, allowing it to do most of the heavy lifting dealing with Box2D + Game Loop movement timing, etc. This State just sets the direction to the correct way. Notice too a rudimentary super method call to allow the base class to do it&#8217;s work first. I also extend the jump behavior by also moving the Entity in the right direction. I could let the base class do this, or the sub-class&#8230; up to you.</p>
<p>Be aware in all examples, the State classes have their onEnterState and onExitState methods called in the correct order, always. You do NOT have to implement them if you do not wish to. Finally, the most important thing to notice is the State classes use the changeStateToAtNextTick method for the State Machine class vs. changeState. The short reason for this is that it allows all the code in the current stack to run, including State machine class clean up, as well as avoiding common race conditions (if you&#8217;re a Flash Developer, think invalidation).</p>
<p><strong>Real World Challenges</strong></p>
<p>I wanted to show you some of the challenges I&#8217;ve had in the real world. While the design patterns&#8217; rules are quite clear about &#8220;Entity&#8217;s holding the data, States implementing the behavior&#8221; sometimes it&#8217;s easier to let the Entity handle the details&#8230; especially with Box2D collisions.</p>
<p>An example of this is in my ZombieStick game where a Zombie grapples with the player. They get a reference to the player they grappled, add themselves as a grappler, and await the Player&#8217;s State Machine to resolve fighting off the zombie. Off-loading a lot of this code to the Entity makes them much cleaner classes, and results in less code since the Entity&#8217;s already extend a Corona DisplayObject. To pragmatists, sounds legit, to ivory tower purists, it&#8217;s pathetic&#8230; especially in a light weight and powerfully dynamic language like Lua.</p>
<p>This works out ok in that if a collision event fires from a Zombie, but if he&#8217;s in another state where he clearly can&#8217;t grapple the player (prone, stunned, dead), he just ignores the event. Sounds great at first, but Corona collision events are just that&#8230; events, once you miss them, they&#8217;re gone. Therefore, each State class has the burden of in its onEnterState to do some checking to see what it missed. This is basically the same problem <a href="http://puremvc.org" title="Notes on Completing Round 1 of P90X">PureMVC</a> and <a href="http://robotlegs.org">Robotlegs</a> Mediators solve in application development (data is ready, you&#8217;re not vs. you&#8217;re ready, data is not), so you can do the same here as well; you just have to ensure your Entity does a good job of exposing the variables you need to have your State boot up correctly.</p>
<p>For example, here&#8217;s the Zombie&#8217;s Box2D collision handler:</p>
<pre lang="lua">function zombie:collision(event)
   if self.dead == true then return true end
   if event.phase == "began" then
      if event.other.classType == "PlayerJXL" then
         if self.collisionTargets == nil then
            self.collisionTargets = {}
         end
         if table.indexOf(event.other) == nil then
            table.insert(self.collisionTargets, event.other)
         end
      end
   elseif event.phase == "ended" then
      if event.other.classType == "PlayerJXL" then
         table.remove(self.collisionTargets, table.indexOf(event.other))
         if self.targetPlayer ~= nil and event.other == self.targetPlayer then
            self:dispatchEvent({name="onTargetPlayerRemoved", target=self})
         end
      end
   end
end</pre>
<p>All it basically does is manage an internal list of things it hit that are players. If the player moves away, great, it removes them. This allows the State classes to manage whether or not the Zombie should actually act on grappling a player not; ie the actual behavior. As soon as the State boots up, it checks this collisionTargets array in the onEnterSate function. Any time thereafter, it&#8217;ll get the proper events, thus avoiding race conditions. Additionally, the State classes can do it whenever they wish; ie whenever the State Machine moves to the IdleState, that&#8217;s the first thing he checks:</p>
<pre lang="lua">function state:handleCollisionTargets()
   local zombie = self.entity
   local targets = zombie.collisionTargets
   if targets ~= nil and #targets > 0 then
      local first = targets[1]
      zombie.targetPlayer = first
      self.stateMachine:changeStateToAtNextTick("grabPlayer")
   end
end</pre>
<p>Again, following a common solution used in other languages and frameworks&#8230; but just 1 more thing for you to remember, and moar code. I agree with it, and you DO get in a groove, just something to be aware of.</p>
<p>The other thing I noticed is that 90% of the State Machine being changed to different States is handled in the State classes themselves. However, you get into these edge cases where you need someone ELSE to change it. The example I just gave, when the Zombie grapples onto the player, the Player needs to immediately react. Using the above example, it&#8217;d be better to just have the States that are capable of legally going to Grappled Defense State handling it, right? Well&#8230; no. If a Zombie grabs you, you drop what you&#8217;re doing and react&#8230; even if you&#8217;re in the middle of the air in a Jump State. Here&#8217;s a method in the Base Player class (the Entity itself) that does just that:</p>
<pre lang="lua">function player:addGrappler(dudeGrabbingMeUpInThisMug)
   -- TODO: need to ensure you can actually be grappled, need to check state. psuedo code below
   local currentState = self.fsm.state
   if currentState == "firehose" and currentState == "grapple" and currentState == "jump" and current == "jumpLeft" and currentState == "jumpRight" then
      error("Illlegal to grapple player when they're in state: ", currentState)
   end

   -- if you're grappled, you're slowed down
   local grapplers = self.grapplers
   if table.indexOf(grapplers, dudeGrabbingMeUpInThisMug) == nil then
      table.insert(grapplers, dudeGrabbingMeUpInThisMug)
      self:resolveSpeed()
      self.fsm:changeStateToAtNextTick("grappleDefense")
      return true
   else
      error("grappler already added to array")
   end
end</pre>
<p>Yes, a code smell&#8230; further evidence that rules enforcement would mitigate this problem. So would a flow chart indicating what states a Zombie can actually grapple me in. Anyway, if you see things like this in your implementation, hopefully you now know how to solve or refactor them.</p>
<p><strong>Conclusions</strong></p>
<p>Again, the high level characteristics of a State Machine are:</p>
<ul>
<li>States which contain/define the behavior for the Entity</li>
<li>Transitions which occur when one State changes to another</li>
<li>Rules which define which States can change to certain other States</li>
<li>Events which are internally or externally dispatched which trigger State Transitions</li>
</ul>
<p></p>
<p>Using State Machines allows you to more easily scale and organize behavior code for your Game Entities, especially for AI development. The rules engine helps ensure your code matches your flowchart, and tells you at runtime if it does not (except for Classes&#8230; working on it). You can set the StateMachine&#8217;s new state anywhere, and he&#8217;ll both dispatch a change event as well as call your enter/exit functions for you. If you wish for it to utilize the global Event bus, I&#8217;ve included instructions inside of the class on how to enable this. For larger projects, the class based option helps your code scale for larger projects. All of the examples are included in the <a href="https://github.com/JesterXL/Lua-Corona-SDK-State-Machine">Github repo</a> where you can download the code.</p>
<p>Further reading:</p>
<ul>
<li><a href="http://ai-depot.com/FiniteStateMachines/FSM.html">Finite State Machines</a></li>
<li><a href="http://www.troyworks.com/cogs/">Cogs framework with presentation</a> (scroll down)</strong></li>
<li><a href="http://code.google.com/p/flash-state-engine/">Johnathan Kaye&#8217;s ActionScript 3 State Engine</a></li>
<li><a href="http://www.richardlord.net/blog/finite-state-machines-for-ai-in-actionscript">Richard Lord&#8217;s &#8220;Finite State Machines for AI in ActionScript</a></li>
<li><a href="http://www.skorks.com/2011/09/why-developers-never-use-state-machines/">Why Developers Never Use State Machines</a></li>
</ul>
<p>Also posted on <a href="http://www.ios-gaming.com/2012/07/11/finite-state-machines-in-game-development/">iOS Gaming</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2012/07/finite-state-machines-in-game-development.html/feed</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Unit Testing in Corona SDK Using Lunatest</title>
		<link>https://jessewarden.com/2012/07/unit-testing-in-corona-sdk-using-lunatest.html</link>
					<comments>https://jessewarden.com/2012/07/unit-testing-in-corona-sdk-using-lunatest.html#comments</comments>
		
		<dc:creator><![CDATA[JesterXL]]></dc:creator>
		<pubDate>Sat, 07 Jul 2012 13:10:47 +0000</pubDate>
				<category><![CDATA[CoronaSDK]]></category>
		<category><![CDATA[corona]]></category>
		<category><![CDATA[coronasdk]]></category>
		<category><![CDATA[lua]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[unittest]]></category>
		<guid isPermaLink="false">http://jessewarden.com/?p=3188</guid>

					<description><![CDATA[In this article I &#8216;ll give you an overview of why you&#8217;d want to unit test your Lua code in Corona SDK, what features Lunatest has, a walk you through some real-world unit tests and suites I&#8217;ve written. I&#8217;ve forked Lunatest on Github to make it work with Corona SDK. This blog post has a [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://jessewarden.com/2012/07/unit-testing-in-corona-sdk-using-lunatest.html"><img loading="lazy" decoding="async" style="padding-right: 8px;" src="http://jessewarden.com/archives/blogentryimages/lunatest/lunatest.jpg" alt="" width="320" height="213" align="left" /></a>In this article I &#8216;ll give you an overview of why you&#8217;d want to unit test your Lua code in Corona SDK, what features <a href="https://github.com/silentbicycle/lunatest">Lunatest</a> has, a walk you through some real-world unit tests and suites I&#8217;ve written. <a href="https://github.com/JesterXL/lunatest">I&#8217;ve forked Lunatest</a> on Github to make it work with Corona SDK. This blog post has a companion video embedded below.</p>
<p>&nbsp;</p>
<p><iframe loading="lazy" width="640" height="360" src="http://www.youtube.com/embed/szEbqu6_YRc" frameborder="0" allowfullscreen></iframe></p>
<p><span id="more-3188"></span><strong>Introduction: Why Unit Test?</strong></p>
<p>Lua in Corona SDK has 3 issues when your game/application code base grows to any large size.</p>
<p>First, Lua is a dynamic language much like JavaScript, Ruby, and Python. As such, you have little to no help from the compiler to ensure your code expects even basic parameters being passed to your functions as well as misspellings.</p>
<p>Secondly, Lua is dynamic at runtime. You actually need to run the code to see how it actually works. Examples include combining strings together to dynamically access properties on dynamically created objects in anÂ asynchronousÂ way.</p>
<p>Third, even if encapsulated, you have no way of knowing if your new code breaks existing code, or if modifying existing code allows it to work the same way with some assurance. This problem is not unique to Lua, it&#8217;s unique to any complex code base regardless of language.</p>
<p>All 3 combined necessitate a need for <a href="http://en.wikipedia.org/wiki/Unit_testing">unit tests</a>. Some would argue even just 1 of the above.</p>
<p><strong>Anatomy of Unit Testing</strong></p>
<p>Unit testing, as far as we&#8217;re concerned with Lua, are a bunch of functions that make sure things work as expected. Inside of those functions, you write those expectations about how you expect things to work as a bunch of assert functions.Â These groups of functions aren&#8217;t actually part of your main code base; they&#8217;re grouped together in a test folder and called a test suite. The more of them you have, the more test coverage you have.</p>
<p>TDD or <a href="http://en.wikipedia.org/wiki/Test-driven_development">Test Driven Development</a> is where you actually write the above paragraph test code first, and THEN actually write the code it&#8217;s testing afterwards. You start with writing a test that fails, you write the code to make it pass, and then ensure the test passes. Then you repeat.</p>
<p>The above 2 paragraphs can, and do fill books with the details of TDD &#038; unit testing&#8230; but that&#8217;s all you need to know for now. Heck, you can ignore everything I write here, start to proactively use assert, and your coding life will improve a lot.</p>
<p><strong>Asserts</strong><br />
Let&#8217;s start at the beginning. Lua already has an expectation function, called &#8220;assert&#8221;. It looks like this:</p>
<pre lang="lua">local wubWubWub = true
assert(wubWubWub, "Someone forgot to drop the bass.")</pre>
<p>This code asserts or &#8220;states positively&#8221; that the variable is true. If it were false, an error would be thrown with that string &#8220;Someone forgot to drop the bass.&#8221; passed into the error function. If you&#8217;re not aware, the error function in Lua stops execution of the current script and prints whatever string it has to the console/terminal. Secondly, all functions in Lua are implied to be successful if they return true.</p>
<p>Even without unit testing, using assert, you can be proactive in finding errors. For example, I use it all the time in manual getter/setters in Lua (not metatable ones, the set/get + method name convention). Since Lua has no typing system, I ensure my inputs are sanitized like so:</p>
<pre lang="lua">function setSpeed(newValue)
   assert(newValue ~= nil, "You cannot set speed to nil.")
   assert(type(newValue) == "number", "You must set speed to a number value.")
   self.speed = newValue
end</pre>
<p>Those 2 functions alone find ALL kinds of silly bugs where someone, somewhere accidentally set a value to nil and it made it&#8217;s way deep into the bowels of some class, and I&#8217;m wondering who&#8217;s fault it is. When everyone starts doing this, it makes it really easy to find who caused the bug, and quickly.</p>
<p>Yes, there is a performance cost to assert. However, it&#8217;s easier to remove a bunch of assert functions scattered everywhere via a Find / Replace from solid code then it is at add them to code that runs very fast with lots of unknown bugs.</p>
<p><strong>Moar Asserts</strong></p>
<p>Just about every testing framework expands upon the above function. In fact, 80% of what they offer in their libraries and frameworks are additional assert functions. Why? Three reasons. First, would you rather write this?</p>
<pre lang="lua">local icon = display.newImage("icon.png")
assert(icon ~= nil, "Icon image cannot be found.")</pre>
<p>or this:</p>
<pre lang="lua">local icon = display.newImage("icon.png")
assert_not_nil(icon, "Icon image cannot be found.")</pre>
<p>The second reason is it&#8217;s more clear what that is testing; the function name alone tells you what you need to know before you&#8217;ve even made it to the parameters.</p>
<p>Here&#8217;s another example:</p>
<pre lang="lua">local currentSpeed = character.speed
character:setSpeed(currentSpeed + 1)
assert(character.speed > currentSpeed, "Character speed did not increase.")</pre>
<p>vs writing:</p>
<pre lang="lua">local currentSpeed = character.speed
character:setSpeed(currentSpeed + 1)
assert_gt(character.speed, currentSpeed, "Character speed did not increase.")</pre>
<p>Now this one may appear backwards; &#8220;A comma vs. using the normal mathematical construct!?&#8221;</p>
<p>Keep in mind, however, many bugs are caused by misplaced operators. For example, developers often will use = instead of == to assign a value, or they&#8217;ll use > vs. >= for edge cases, etc. In writing that code, it&#8217;s completely legal, and Lua&#8217;s interpreter won&#8217;t give you an error when you run it. Using assert_gt in this instance will ensure your expected value is there, as well as ensure you&#8217;ve use the operator correctly. If not, it&#8217;ll actually&#8230; you know&#8230; help you out!</p>
<p>And although I bash Lua for not having a type system, it does have a type function for a reason. You can test a variety of types such as assert_not_boolean for a return value that&#8217;s supposed to be a number, and assert_metatable if you&#8217;re doing funky metatable magic.</p>
<p><strong>Suites</strong></p>
<p>A suite is just a series of functions that are related. For example, in my example video I show my file suite which has unit tests for testing my DeleteFileService class and my ReadFileContentsService class. Since reading and writing and deleting files are something I consider related, I created a file suite, or &#8220;a bunch of functions that test file shiz&#8221;.</p>
<p>While lunatest can test functions inline, as an OOP guy, to me that&#8217;s just gross. I like the more organized suites where all the functions are in their own file. Lua calls it a file, I call it a Class, Lunatest calls it a suite&#8230; we&#8217;re all happy.</p>
<p>Here&#8217;s my file one:</p>
<pre lang="lua">module(..., package.seeall)

function test_saveFile()
	require "com.jxl.core.services.ReadFileContentsService"

	local saveFile = SaveFileService:new()
	local data = "moo"
	assert_true(saveFile:saveFile("test.txt", system.DocumentsDirectory, data), "Failed to save test.txt")
end

function test_readFile()
	require "com.jxl.core.services.ReadFileContentsService"
	require "com.jxl.core.services.SaveFileService"

	local saveFile = SaveFileService:new()
	local data = "moo"
	assert_true(saveFile:saveFile("test.txt", system.DocumentsDirectory, data), "Failed to save test.txt for use in reading.")

	local readFile = ReadFileContentsService:new()
	local contents = readFile:readFileContents("test.txt", system.DocumentsDirectory)
	assert_string(contents, "contents are not a string.")
	assert_equal(contents, data, "Data written to file does not match what we just read out of it.")
end</pre>
<p>2 things to note about this file. First, I use the <a href="http://lua-users.org/wiki/LuaModuleFunctionCritiqued">much loathed</a> module(&#8230;, package.seeall) at the top. This is what lunatest wants in how it loads modules so&#8230; you&#8217;ll need to do this too (yes, I temporarily hacked lunatest to support Corona&#8217;s packages, but it wasn&#8217;t worth it).</p>
<p>Second, notice the 2 functions are both global and start with &#8220;test_&#8221;. Any function you want Lunatest to run as a test, you need to prefix it with &#8220;test_&#8221; in the function name. Notice they aren&#8217;t prefixed with local, they&#8217;re simple global functions.</p>
<p>That&#8217;s it. Put a bunch of functions in that file, make an assert or two within them, save it, and then in your main file, tell luna test about it.</p>
<p><strong>Advanced Suites</strong></p>
<p>The above is good enough for writing suites that&#8217;ll help you. Here&#8217;s 4 more cool things suites can do.</p>
<p>If you have repetitive code that needs to be run before every test, you can run it in the test setup. This ensures you only have to run it once, you have the option of aborting the test, and it&#8217;s run in a protected manner (aka <a href="http://www.lua.org/pil/8.4.html">pcall</a>). Additionally, you don&#8217;t have to call this yourself, nor remember to do so, Lunatest does this for you. In my StateMachineSuite, I have to instantiate the StateMachine class for every call so I put it in setup.</p>
<p>If you have code that needs to be cleaned up a lot or in a particular order, you can utilize the teardown. If you implement one, it&#8217;s called after every single test case. This also ensures that if everything is deleted, strange memory bugs are more easily found. Some classes require more than just nilling out their variables, in the case of Corona SDK Display Objects and Widgets which must have their removeSelf called, THEN you can nil out the variable reference. You can also ensure all of the benefits of setup, just in a function called teardown where you clean up your mess.</p>
<p>Finally, there is a suite_setup and a suite_teardown. Unlike setup and teardown, these are only called once for the entire suite; suite_setup before any tests are run, and suite_teardown after everything, including the last teardown, is called. Sometimes you don&#8217;t need unique setup code for your tests so you can put it here instead. This is also a good place for class imports.</p>
<p>Here&#8217;s my StateMachine example. Notice it has a suite_setup (but no suite_teardown). The setup instantiates the StateMachine and the teardown ensures it&#8217;s deleted so each test function gets a brand new SuiteMachine instance.</p>
<pre lang="lua">module(..., package.seeall)

function suite_setup()
	require "com.jxl.core.statemachine.State"
	require "com.jxl.core.statemachine.StateMachine"
	require "com.jxl.core.statemachine.BaseState"
end

function setup()
	machine = StateMachine:new()
end

function teardown()
	machine = nil
end

function test_classWorks()
	assert_not_nil(machine)
end

function test_verifyInitialStateIsNil()
	assert_nil(machine.state)
end

function test_verifyInitialStateIsNullWithStates()
	local initial = "playing"
	machine:addState(initial)
	machine:addState("stopped")
	assert_nil(machine.state)
end

function test_verifyInitialStateIsNotNil()
	local initial = "playing"
	machine:addState(initial)
	machine:addState("stopped")
	machine:setInitialState(initial)
	assert_equal(initial, machine.state)
end

function test_enter()
	local t = {}
	local hitCallback = false
	function t.onPlayingEnter(event)
		assert_equal(event.toState, "playing")
		assert_equal(event.fromState, "idle")
		hitCallback = true
	end
	machine:addState("idle")
	machine:addState("playing", { enter = t.onPlayingEnter, from="*"})
	machine:setInitialState("idle")
	assert_true(machine:canChangeStateTo("playing"), "Not alowed to change to state playing.")
	assert_true(machine:changeState("playing"))
	assert_equal("playing", machine.state)
	assert_true(hitCallback, "Didn't hit the onPlayingEnter callback.")
end

function test_preventInitialOnEnterEvent()
	local t = {}
	local hitCallback = false
	function t.onPlayingEnter(event)
		hitCallback = true
	end
	machine:addState("idle")
	machine:addState("playing", { enter = t.onPlayingEnter, from="*"})
	machine:setInitialState("idle")
	assert_false(hitCallback, "Hit the callback when I had no initial state set.")
end

function test_exit()
	local t = {}
	local hitCallback = false
	function t.onPlayingExit(event)
		hitCallback = true
	end
	machine:addState("idle", {exit = t.onPlayingExit})
	machine:addState("playing", {from="*"})
	machine:setInitialState("idle")
	machine:changeState("playing")
	assert_true(hitCallback, "Never called onPlayingExit.")
end

function test_ensurePathAcceptable()
	machine:addState("prone")
	machine:addState("standing", {from="*"})
	machine:addState("running", {from={"standing"}})
	machine:setInitialState("standing")
	assert_true(machine:changeState("running"), "Failed to ensure correct path.")
end

function test_ensurePathUnacceptable()
	machine:addState("prone")
	machine:addState("standing", {from="*"})
	machine:addState("running", {from={"standing"}})
	machine:setInitialState("prone")
	assert_false(machine:changeState("running"), "Failed to ensure correct path.")
end

function test_hierarchical()
	local t = {}
	local calledonAttack = false
	local calledOnMeleeAttack = false
	function t.onAttack(event)
		calledonAttack = true
	end

	function t.onMeleeAttack(event)
		calledOnMeleeAttack = true
	end

	machine:addState("idle", {from="*"})
	machine:addState("attack",{from = "idle", enter = t.onAttack})
	machine:addState("melee attack", {parent = "attack", from = "attack", enter = t.onMeleeAttack})
	machine:addState("smash",{parent = "melee attack", enter = t.onSmash})
	machine:addState("missle attack",{parent = "attack", enter = onMissle})

	machine:setInitialState("idle")

	assert_true(machine:canChangeStateTo("attack"), "Cannot change to state attack from idle!?")
	assert_false(machine:canChangeStateTo("melee attack"), "Somehow we're allowed to change to melee attack even though we're not in the attack base state.")
	assert_false(machine:changeState("melee attack"), "We're somehow allowed to bypass the attack state and go straigt into the melee attack state.")
	assert_true(machine:changeState("attack"), "We're not allowed to go to the attack state from the idle state?")
	assert_false(machine:canChangeStateTo("attack"), "We're allowed to change to a state we're already in?")
	assert_true(machine:canChangeStateTo("melee attack"), "We're not allowed to go to our child state melee attack from attack?")
	assert_true(machine:changeState("melee attack"), "I don't get it, we're in the parent attack state, why can't we change?")
	assert_true(machine:canChangeStateTo("smash"), "We're not allowed to go to our smash child state from our parent melee attack state?")
	
	assert_true(machine:canChangeStateTo("attack"), "We're not allowed to go back to our parent attack state?")
	assert_true(machine:changeState("smash"), "We're not allowed to actually change state to our smash child state.")
	assert_false(machine:changeState("attack"))
	assert_true(machine:changeState("melee attack"))
	assert_true(machine:canChangeStateTo("attack"))
	assert_true(machine:canChangeStateTo("smash"))
	assert_true(machine:changeState("attack"))
end</pre>
<p>Pay attention to that last part, it has some good and bad practices. The whole point of unit tests is to test 1 thing or unit. You shouldn&#8217;t have 50 billion asserts like I do. Worse, you&#8217;ll notice some of the asserts at the bottom do not have custom error messages in the 3rd parameter. If any 1 of those fail, there is no way to tell which one failed. Bad, Jesse, BAD!</p>
<p><strong>Run</strong></p>
<p>Setting up all of the above is a snap. Ready?</p>
<p>In your main.lua file, import Lunatest:</p>
<pre lang="lua">require "lunatest"</pre>
<p>Next, add your suites:</p>
<pre lang="lua">lunatest.suite("tests.com.jxl.core.ServicesSuite")
lunatest.suite("tests.com.jxl.core.services.ReadFileContentsServiceSuite")
lunatest.suite("tests.com.jxl.core.statemachine.StateMachineSuite")
lunatest.suite("tests.com.jxl.zombiestick.services.LoadLevelServiceTest")</pre>
<p>Finally, call run:</p>
<pre lang="lua">lunatest.run()</pre>
<p>That&#8217;s it! You&#8217;ll see the report of stuff in the console/terminal.</p>
<p><strong>Conclusions</strong></p>
<p>The problem with unit testing is that you need to have units to actually test. A lot of code that wasn&#8217;t written to be unit tested needs to be refactored first which can be a lot of work. If it&#8217;s also entangled with other code that&#8217;s also not easily testable&#8230; you see where this is going. That&#8217;s ok. You can start in one section, or test high level results. Yes, your setup code may be burdensome, but it&#8217;s something. Automated tests, even if a certain section, can help you a lot. Additionally, when writing new code, think about writing it in a way that&#8217;s testable, even if you never actually test it. This often results in less coupled code anyway.</p>
<p>Additionally, while testing is in fact creating more code, you find more bugs, early, and faster, proactively. For games that require quick iterations&#8230; this can be tricky. If the game needs to be built to verify it&#8217;s even fun, is it worth it to unit test? As you make a lot of games in the same tech (whether Lua, C#, ActionScript, Java, whatever&#8230;), you&#8217;ll start to gather are a large set of functions, libraries, and classes that are reusable from project to project. THOSE are worth unit testing.</p>
<p>Unit tests are just a bunch of functions that test expectations, and are organized in suites. You run a bunch of test suites inside of Lunatest. Unit tests help ensure your function types are correct since Lua has no helpful compiler to help on this front as well as spelling mistakes. It also verifies your code works as you expect at runtime. Finally, for larger code bases, you can add new code without worry of breaking old code, including if you modify old code. The more unit tests you write, the more coverage you have. The more coverage, the easier it is to manage a larger code base.</p>
<p>Remember, unit tests are code too. You can still follow all the best practices your used to such as OOP, DRY, and being clean. MOAR UNIT TESTS!</p>
<p><img decoding="async" src="http://jessewarden.com/archives/blogentryimages/lunatest/moar-unit-tests.jpg" /></p>
<p>Title image <a href="http://s4cr4m3nt.deviantart.com/art/Moon-10544945?q=boost%3Apopular%20moon&#038;qo=0">&#8220;Moon&#8221; by S4cr4m3nt</a>.</p>
<p>Also posted on <a href="http://www.ios-gaming.com/2012/07/11/unit-testing-in-corona-sdk-using-lunatest/">iOS Gaming</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jessewarden.com/2012/07/unit-testing-in-corona-sdk-using-lunatest.html/feed</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
