<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://tyskwo.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://tyskwo.com/" rel="alternate" type="text/html" /><updated>2024-12-01T02:27:15+00:00</updated><id>https://tyskwo.com/feed.xml</id><title type="html">Tyler Wood</title><subtitle>A game programmer soon to be graduating from Champlain College that has an intense passion for UI and AI.</subtitle><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><entry><title type="html">Closing Remarks: Part 1.</title><link href="https://tyskwo.com/2017/closing-remarks-part1/" rel="alternate" type="text/html" title="Closing Remarks: Part 1." /><published>2017-05-05T00:00:00+00:00</published><updated>2017-05-05T00:00:00+00:00</updated><id>https://tyskwo.com/2017/closing-remarks-part1</id><content type="html" xml:base="https://tyskwo.com/2017/closing-remarks-part1/"><![CDATA[<p>Every once in a while, it becomes really hard to write a new post. Sometimes that’s because it’s hard to find time, or there is no motivation, or maybe there’s no easy way to formulate and corral all of the thoughts, feelings, and events that are forthcoming.</p>

<p>That last reason describes this post. It’s been over a month since my last post, and so much has and is happening.</p>

<p>Graduation is almost here – a week and a day away – and I think it could go without saying that reminiscing has been more frequent lately. Where to start…</p>

<p>The senior show was last Friday, and it could not have been a more resounding success. The recruiters has an absolute blast playing <em>Office Mayhem</em>, and there’s <a href="https://twitter.com/officemayhem/status/858699193803845633">even a picture of Don Laackman</a>, president of Champlain College, enjoying the game. The team finished the win screen, including balloon popping. It’s quite a lot of fun:</p>

<figure class="align-center">
  <img src="https://tyskwo.com/assets/images/blog/2017/05/balloons.gif" />
  <figcaption>Each player's trophy spawns a balloon of the color, and can be inflated. When popped, they shoot out colored confetti.</figcaption>
</figure>

<p>The build is in a great place, and we actually have interest from multiple publishers to release the game. It has only put an even better end-cap to my experience at Champlain. I don’t think I’m ready to write that blog post yet.</p>

<p>Working with the <em>Office Mayhem</em> team has been the best team experience I’ve had at Champlain, and I hope I’ve made that clear across the plethora of blog posts I’ve written about them and the game. I am excited to see what we make of <em>Office Mayhem</em>, and I wish them nothing but the best. They’re an extremely talented lot, and I know they will succeed in whatever they strive for.</p>

<p>In other news, <a href="wednesdavid.xyz">David</a> and I finished our physics demonstration, which was to implement volume and point based fields. I’m hoping to get a write-up of that on my portfolio in the coming weeks. I also have been slowly working on <em>DASHockey</em> in my free time, though the more progress I make the more I am unsure of its viability. I’m also working on a sample project showcasing <a href="">Action</a> – currently it is in its infancy, but I’m excited to explore what I can do with it.</p>

<p>With all of that said, I could not be happier, or more excited, to announce that I was offered and accepted a position at Vicarious Visions as a junior software engineer. I am so humbled to join their team and am itching to start working.</p>

<p>Part 2 will be in a week or so, after graduation, and will be much more emotionally fueled. Until then, I’m off to enjoy this last week to its utmost.</p>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[The first half of my reflection on Office Mayhem and Champlain College.]]></summary></entry><entry><title type="html">The week of too many hours.</title><link href="https://tyskwo.com/2017/the-week-of-too-many-hours/" rel="alternate" type="text/html" title="The week of too many hours." /><published>2017-04-03T00:00:00+00:00</published><updated>2017-04-03T00:00:00+00:00</updated><id>https://tyskwo.com/2017/the-week-of-too-many-hours</id><content type="html" xml:base="https://tyskwo.com/2017/the-week-of-too-many-hours/"><![CDATA[<p>It was a very busy week in the cubicles of <em>Office Mayhem</em>, but with work comes progress. With only three weeks left, we could use as much progress as we can get our hands on.</p>

<p>The biggest addition is the introduction of timer tasks: a group-wide task where all of the players fight over doing the most of whatever the task dictates (like throw everything out, or answer the most phone calls). When the timer runs out, points are awarded to first, second, and third place. They have been received really well at QA, and experienced players love the new strategy elements they bring to the game.</p>

<figure class="align-center">
  <img src="https://tyskwo.com/assets/images/blog/2017/04/timerUI.gif" />
  <figcaption>Only two players, but here's a timer task in action. With four players, it is a hectic dash to come in first.</figcaption>
</figure>

<p><a href="https://tyskwo.com/assets/images/blog/2017/04/timerIteration.png"><img src="https://tyskwo.com/assets/images/blog/2017/04/timerIteration.png" alt="iteration" style="width: 350px" class="align-right" /></a>
The UI for timer tasks fell on my shoulders, and it was a nice change of pace for me. With that said, it came with its fair share of difficulties: we wanted to introduce all of this new functionality to our pre-existing <code class="language-plaintext highlighter-rouge">TaskCard</code> framework, while still letting the players get the information they needed at a glance. The finished product is above, obviously, but there was a fair amount of iteration to get there.</p>

<p>Another feature added this week was a plug-in ‘attract mode’ – basically a kiosk mode if the game sits idle for too long. We also knocked out a lot of the bugs and polish items we’ve been meaning to get to. <a href="http://andrewmillsap.weebly.com">Andy</a> added random character creation on the start screen which is a nice bit of polish, and <a href="http://tonyl.info">Tony</a> finished the stamp system in the break room, which finally finishes our inner game loop.</p>

<p>This coming week, we hope to spruce up our tutorial systems so new players experience even less friction when playing the game, and to implement the accolade system and Employee of the Week room to finally be feature complete. After that it would be small ticket items like implementing new sounds, tasks, and characters. The finish line is really close, and I can’t wait to cross it.</p>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[The work train has no brakes.]]></summary></entry><entry><title type="html">Back in the swing of things.</title><link href="https://tyskwo.com/2017/back-in-the-swing/" rel="alternate" type="text/html" title="Back in the swing of things." /><published>2017-03-27T00:00:00+00:00</published><updated>2017-03-27T00:00:00+00:00</updated><id>https://tyskwo.com/2017/back-in-the-swing</id><content type="html" xml:base="https://tyskwo.com/2017/back-in-the-swing/"><![CDATA[<p>There’s something about the haphazardness of small island urban planning that is oddly refreshing to me. Maybe it’s the narrow streets, buildings right up against the side of the road, or the simpler, less rigidness of it all. Regardless, spring break has ended and it’s back to the office. We have made quite a bit of progress since coming back to cold, wet Burlington.</p>

<p>While <a href="http://richardkingcapstone.blogspot.com">Richard</a> and <a href="http://www.willconcannonart.com">Will</a> were at PAX, <a href="https://tonyl.info">Tony</a> was hard at work optimizing <em>Office Mayhem</em>. He managed to double our frame rate, and almost triple it on low-end Macs like mine. On higher end machines it isn’t too noticeable, but it is great to be able to lower our low-end target even more, especially if we decide to release. I took spring break as just that, a break, but towards the end I spent time on a lot of the smaller polish-level items we have been meaning to get done: getting random markers from the copier, level randomization, a better item spawning system in the tutorial, etc.</p>

<figure class="align-center">
 <img src="https://tyskwo.com/assets/images/blog/2017/03/whiteboard.gif" />
  <figcaption>The whiteboard is still being iterated on, but it's in a very good place. Players can draw and erase, and get new markers from the copier.</figcaption>
</figure>

<p>Once we were all back in the Green Mountain state, production was right back in full swing. <a href="https://npaquettewordpress.wordpress.com">Norman</a> started working on the fifth character head, and <a href="http://andrewmessier.blogspot.com">Andrew</a> was working on new animations for our ‘win’ room at the end of the work week, while <a href="http://www.tim-healey.com">Tim</a> has been working on a third set of levels, which I can’t wait to implement.  Richard has been working on lobby music for the start and break rooms, which are eerily quiet right now. The biggest change we brought to QA testing was character customization: <a href="http://andrewmillsap.weebly.com">Andy</a> worked diligently to add in swappable bodies and heads, which has been a really great addition judging by the feedback from QA.</p>

<figure class="align-center">
  <img src="https://tyskwo.com/assets/images/blog/2017/03/character_selection.gif" />
  <figcaption>If you look carefully, there <em>is</em> a headless option in there. We're unsure if it will stay though – just a joke for now.</figcaption>
</figure>

<p>I spent this week helping Andy with the rough edges of character customization, as well as implementing new particles I received from <a href="http://jeremynroot.com">Jeremy</a>. We finally made the elevator a breakable object, which leads to some interesting strategies. I also implemented, and removed, group tasks. These tasks worked similar to normal tasks, but they would replace all current tasks, and there would only be one of them – creating a four player rumble of sorts to complete this task. After bringing them to QA, we soon realized that they acted as a pinch point in the game flow, and could very easily let first place keep their lead in certain instances, basically creating a standstill. While fun to work around, we ultimately decided that this wasn’t the type of pace we wanted, and decided to scrap it. We took the time to look deeper at timer tasks – a specific type of group tasks that want players to do the <em>most</em> of something in a given amount of time. These don’t seem to have the same pinch points as normal group tasks, so we plan on implementing these this coming week, and hoping they fare better at QA.</p>

<p>We also took the time this week to record some gameplay for an alpha video. Take a watch!</p>

<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">

  <iframe src="https://www.youtube.com/embed/839Ih0TVC44" frameborder="0" allowfullscreen=""></iframe>

</div>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[Six more weeks of mayhem. I wouldn't want anything else.]]></summary></entry><entry><title type="html">PAX is over, time to relax a little.</title><link href="https://tyskwo.com/2017/PAX-relax/" rel="alternate" type="text/html" title="PAX is over, time to relax a little." /><published>2017-03-13T00:00:00+00:00</published><updated>2017-03-13T00:00:00+00:00</updated><id>https://tyskwo.com/2017/PAX-relax</id><content type="html" xml:base="https://tyskwo.com/2017/PAX-relax/"><![CDATA[<p>I write this sitting on a beach. It’s relaxing, but I’m more worried about getting sand in the keyboard. This week will be a calm, relaxing break before the final whirlwind (it’s so scary that graduation is only seven weeks away). PAX is now over, but it was a whole ‘nother whirlwind before (and during). Over the past week, we have added the improved whiteboard break rooms, all of the playable characters and respective animations, improvements to the game flow, updating many of the sounds, and fixing as many bugs as we could find. We were all worn out by the end.</p>

<figure class="half">
    <a href="/assets/images/blog/2017/03/richardisdesign.png"><img src="/assets/images/blog/2017/03/richardisdesign.png" /></a>
    <a href="/assets/images/blog/2017/03/pax.png"><img src="/assets/images/blog/2017/03/pax.png" /></a>
    <figcaption>Yes, Richard <em>is</em> design. Players are able to draw with markers on the whiteboard. On the right, we were quite excited for PAX, and you can see our new characters.</figcaption>
</figure>

<p>We learned so much at PAX – we had over a thousand people play a round or two! Our tutorial can be smoother, and that’s something we’ve noted for a while now – the game has just been evolving at such a rapid pace that we’ve neglected it. We are planning to add button prompts above the relative items for each stage of the tutorial to help engrain what buttons perform which actions. This also shows the pitfalls of Playstation vs Xbox controllers, with PS’ X button being Xbox’s A button, and on the Xbox controllers, we use both X and A a lot, so to people who play more on Playstation, their controllers are different, and muscle memory took over. Otherwise, the booth was really well presented; <a href="http://willconcannonart.com">Will</a> did a great job creating marketing materials for it. I really hope Champlain believes we represented them well. We seemed to have a constant flux of people playing, and we even had lines at the busier moments, which is a huge boost of pride to the team.</p>

<figure class="half">
    <a href="/assets/images/blog/2017/03/OM_businesscard.jpg"><img src="/assets/images/blog/2017/03/OM_businesscard.jpg" /></a>
    <a href="/assets/images/blog/2017/03/OM_tentcard.jpg"><img src="/assets/images/blog/2017/03/OM_tentcard.jpg" /></a>
    <figcaption>Here's the tent and team business cards that we created for the booth at PAX. <a href="http://willconcannonart.com">Will</a> did a great job designing them.</figcaption>
</figure>

<p>We also received a lot of praise, which was a little unexpected. <a href="http://richardkingcapstone.blogspot.com">Richard</a> and <a href="http://willconcannonart.com">Will</a> said that there were complete strangers laughing with each other, and if <em>Office Mayhem</em> can do that, maybe it’s not half bad. There were a good handful of people asking where to buy it. Buy it. Those words seem alien to me. People are willing to pay money for <em>Office Mayhem</em> – that’s insane. We also had people from 3 to 63 learn, play, and have fun playing it, which finally solidifies our target market of a couch party game – you never know who’s going to be sitting on the couch next to you.</p>

<figure class="half">
    <a href="/assets/images/blog/2017/03/PAX_booth.jpg"><img src="/assets/images/blog/2017/03/PAX_booth.jpg" /></a>
    <a href="/assets/images/blog/2017/03/PAX_people.jpg"><img src="/assets/images/blog/2017/03/PAX_people.jpg" /></a>
    <figcaption>Props to Richard for his <em>Office Mayhem</em>-blue shades.</figcaption>
</figure>

<p>We also might have some very, very, <em>very</em> exciting news about <em>Office Mayhem</em> in the near future, but I can’t play that hand quite yet. I hope to be able to talk more about it soon.</p>

<p> </p>

<hr />

<p> </p>

<p>In <a href="https://tyskwo.com/2017/action-a-cpp-interpolation-framework/">my last post about Action</a>, I mentioned that <code class="language-plaintext highlighter-rouge">Action</code> did not have support for bezier/custom curves. I have since added that functionality with <code class="language-plaintext highlighter-rouge">Action::GetCurveFromPoints(T x1, T y1, T x2, T y2)</code> for cubic bezier curves, and <code class="language-plaintext highlighter-rouge">Action::GetCurveFromPoint(T x1, T y1)</code> for quadratic curves. The functions clamp the x coordinates to [0, 1] to prevent the time axis from going in reverse, which could cause some ill-intended effects.</p>

<p>I also have encapsulated the framework entirely in the <code class="language-plaintext highlighter-rouge">Action</code> namespace – before the timing functions were not under it. Hopefully this will fix any potential namespace clashes.</p>

<p>Simply update your local repository, or <a href="https://github.com/tyskwo/action">pull it.</a></p>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[Quite literally the eye of the storm – with PAX behind us and graduation before us.]]></summary></entry><entry><title type="html">Action: A C++11 interpolation framework</title><link href="https://tyskwo.com/2017/action-a-cpp-interpolation-framework/" rel="alternate" type="text/html" title="Action: A C++11 interpolation framework" /><published>2017-03-05T00:00:00+00:00</published><updated>2017-03-05T00:00:00+00:00</updated><id>https://tyskwo.com/2017/action-a-cpp-interpolation-framework</id><content type="html" xml:base="https://tyskwo.com/2017/action-a-cpp-interpolation-framework/"><![CDATA[<h5 class="notice--primary" id="before-i-begin-the-repo-for-action-can-be-found-here">Before I begin, the repo for Action can be found <a href="http://github.com/tyskwo/action">here.</a></h5>

<p>Since <a href="https://tyskwo.com/work/96_flip/">Flip</a>, almost three years ago now, I’ve used interpolation in every game that I’ve created – starting with <a href="http://gamua.com/starling/">Starling</a>, and then moving to <a href="http://www.pixelplacement.com/itween/index.php">iTween in Unity</a>, and <a href="https://developer.apple.com/reference/spritekit/skaction">SKActions in SpriteKit</a>. Interpolation is used everywhere in games, from UI animations, to AI actions, animations, and even world building. It truly could be looked at as a universal tool in a game developer’s toolbox.</p>

<h2 id="what-is-interpolation">What is interpolation?</h2>

<p>Interpolation is a method of constructing new data within the range of a discrete set of known data. Put simply, it’s the translating of one piece of data into another piece of data.</p>

<p><a href="https://mollyrocket.com/casey/stream_0018.html">Casey Muratori</a>, who worked on <em>The Witness</em>, has a great video on the basics of interpolation, which I highly, <em>highly</em> suggest watching. He explains bezier curves in 40 seconds better than other’s have done in half an hour.</p>

<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">

  <iframe src="https://www.youtube.com/embed/S2fz4BS2J3Y" frameborder="0" allowfullscreen=""></iframe>

</div>

<h2 id="introducing-action">Introducing Action.</h2>

<p>I’ve been wanting to roll my own solution for a while now. Not necessarily because I think I can do it better, or include more features, but so I can say I’ve created my own, gain experience in creating the backend of such a system, and have another tool at my disposal.</p>

<p>Thus, Action was created.</p>

<h5 id="what-it-is">What it is.</h5>

<p>It is a time-based, self-contained interpolation framework. It contains the <a href="http://easings.net">common list of easing functions</a>, and the ideology of a <code class="language-plaintext highlighter-rouge">Single</code> action. <code class="language-plaintext highlighter-rouge">Single</code> contains a value to interpolate, start/end values of that interpolation, a duration of how long the interpolation will take, a start-delay, a loop type (currently <code class="language-plaintext highlighter-rouge">None, Normal, or Yoyo</code>), an easing type, and an optional callback to be called upon completion of the interpolation.</p>

<p>There are also <code class="language-plaintext highlighter-rouge">Group</code> and <code class="language-plaintext highlighter-rouge">Sequence</code> actions: the former is a list of <code class="language-plaintext highlighter-rouge">Singles</code> that are run in concurrency, with an optional callback when the entire group is finished, and the latter is similar, except the <code class="language-plaintext highlighter-rouge">Singles</code> run sequentially.</p>

<p>The value to be interpolated is a reference to memory, and thus can be applied to any data of any object: volume of a sound clip, scale of a transform, rotation of a quaternion, etc.</p>

<h5 id="what-it-isnt">What it isn’t.</h5>

<p>The easing functions (called <code class="language-plaintext highlighter-rouge">TimingFunctions</code> in the code base) are exposed, so more can be added, but currently there is no support for bezier/custom curves. Because they’re stored as function pointers, there’s no way to include more parameters in the call without casting another <code class="language-plaintext highlighter-rouge">typedef</code>. I’m experimenting to find the best way to implement this.</p>

<p>There currently is also no option to pause actions, but that is due to the fact of me focusing on the interpolation framework more than the timer it runs on.</p>

<h2 id="how-to-use-it">How to use it.</h2>

<p>First, include <code class="language-plaintext highlighter-rouge">Action.h</code>.</p>

<p>Let’s create a value:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="c1">// imagine t is some object,</span>
<span class="c1">// with testInt being some int in that class.</span>

<span class="c1">//                 variable to change, 'start' value, 'end' value</span>
<span class="n">Value</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">value</span> <span class="p">{</span> <span class="o">&amp;</span><span class="n">t</span><span class="o">-&gt;</span><span class="n">testInt</span><span class="p">,</span>         <span class="mi">0</span><span class="p">,</span>             <span class="mi">100</span> <span class="p">};</span></code></pre></figure>

<p>There are common interpolations generally referred to as <code class="language-plaintext highlighter-rouge">To</code>, <code class="language-plaintext highlighter-rouge">From</code>, and <code class="language-plaintext highlighter-rouge">FromTo</code>. The above is an example of <code class="language-plaintext highlighter-rouge">FromTo</code>. <code class="language-plaintext highlighter-rouge">To</code> and <code class="language-plaintext highlighter-rouge">From</code> could be modeled by doing:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="c1">// To:</span>
<span class="n">Value</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">value</span> <span class="p">{</span> <span class="o">&amp;</span><span class="n">t</span><span class="o">-&gt;</span><span class="n">testInt</span><span class="p">,</span> <span class="n">t</span><span class="o">-&gt;</span><span class="n">testInt</span><span class="p">,</span> <span class="mi">100</span> <span class="p">};</span>

<span class="c1">// From:</span>
<span class="n">Value</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">value</span> <span class="p">{</span> <span class="o">&amp;</span><span class="n">t</span><span class="o">-&gt;</span><span class="n">testInt</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">t</span><span class="o">-&gt;</span><span class="n">testInt</span> <span class="p">};</span></code></pre></figure>

<h3 id="singles">Singles</h3>

<p>Now let’s take that value to interpolate, and create a <code class="language-plaintext highlighter-rouge">Single</code> from it:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">Action</span><span class="o">::</span><span class="n">addSingle</span><span class="p">(</span><span class="o">&amp;</span><span class="n">value</span><span class="p">,</span>
                  <span class="mf">3.0</span><span class="n">f</span><span class="p">,</span>   <span class="c1">// duration  </span>
                  <span class="mf">0.5</span><span class="n">f</span><span class="p">,</span>   <span class="c1">// delay</span>
                  <span class="n">TimingFunctions</span><span class="o">::</span><span class="n">ExponentialEaseIn</span><span class="p">);</span></code></pre></figure>

<p>There’s a lot of customization in <code class="language-plaintext highlighter-rouge">addSingle</code>:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="o">&gt;</span><span class="p">(</span><span class="n">Value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">value</span><span class="p">)</span>
<span class="o">&gt;</span><span class="p">(</span><span class="n">Value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">value</span><span class="p">,</span> <span class="kt">float</span> <span class="n">duration</span><span class="p">)</span>
<span class="o">&gt;</span><span class="p">(</span><span class="n">Value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">value</span><span class="p">,</span> <span class="kt">float</span> <span class="n">duration</span><span class="p">,</span> <span class="n">Callback</span> <span class="n">cb</span><span class="p">)</span>
<span class="o">&gt;</span><span class="p">(</span><span class="n">Value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">value</span><span class="p">,</span> <span class="kt">float</span> <span class="n">duration</span><span class="p">,</span> <span class="n">TimingFunction</span> <span class="n">tf</span><span class="p">)</span>
<span class="o">&gt;</span><span class="p">(</span><span class="n">Value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">value</span><span class="p">,</span> <span class="kt">float</span> <span class="n">duration</span><span class="p">,</span> <span class="n">TimingFunction</span> <span class="n">tf</span><span class="p">,</span> <span class="n">Callback</span> <span class="n">cb</span><span class="p">)</span>
<span class="o">&gt;</span><span class="p">(</span><span class="n">Value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">value</span><span class="p">,</span> <span class="kt">float</span> <span class="n">duration</span><span class="p">,</span> <span class="n">TimingFunction</span> <span class="n">tf</span><span class="p">,</span> <span class="n">Callback</span> <span class="n">cb</span><span class="p">,</span> <span class="n">LoopTypes</span><span class="o">::</span><span class="n">Type</span> <span class="n">loop</span><span class="p">)</span>
<span class="o">&gt;</span><span class="p">(</span><span class="n">Value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">value</span><span class="p">,</span> <span class="kt">float</span> <span class="n">duration</span><span class="p">,</span> <span class="kt">float</span> <span class="n">delay</span><span class="p">,</span> <span class="n">TimingFunction</span> <span class="n">tf</span><span class="p">)</span>
<span class="o">&gt;</span><span class="p">(</span><span class="n">Value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">value</span><span class="p">,</span> <span class="kt">float</span> <span class="n">duration</span><span class="p">,</span> <span class="kt">float</span> <span class="n">delay</span><span class="p">,</span> <span class="n">TimingFunction</span> <span class="n">tf</span><span class="p">,</span> <span class="n">Callback</span> <span class="n">cb</span><span class="p">)</span>
<span class="o">&gt;</span><span class="p">(</span><span class="n">Value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">value</span><span class="p">,</span> <span class="kt">float</span> <span class="n">duration</span><span class="p">,</span> <span class="kt">float</span> <span class="n">delay</span><span class="p">,</span> <span class="n">TimingFunction</span> <span class="n">tf</span><span class="p">,</span> <span class="n">Callback</span> <span class="n">cb</span><span class="p">,</span> <span class="n">LoopTypes</span><span class="o">::</span><span class="n">Type</span> <span class="n">loop</span><span class="p">)</span></code></pre></figure>

<p class="notice--info"><strong>Note:</strong> For any variable that is not set in the method call, the default is constructed: 0 seconds for delay, 1 second for duration, no looping, no callback, and <code class="language-plaintext highlighter-rouge">Linear</code> for the timing function.</p>

<p>Rather than calling one of the predefined methods, you can create a <code class="language-plaintext highlighter-rouge">Single</code> on your own:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">Single</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;*</span> <span class="n">s</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Single</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">value</span><span class="p">);</span>

<span class="n">s</span><span class="o">-&gt;</span><span class="n">setDuration</span><span class="p">(</span><span class="mf">3.0</span><span class="n">f</span><span class="p">);</span>
<span class="n">s</span><span class="o">-&gt;</span><span class="n">setTimingFunction</span><span class="p">(</span><span class="n">TimingFunctions</span><span class="o">::</span><span class="n">BounceEaseOut</span><span class="p">);</span>
<span class="n">s</span><span class="o">-&gt;</span><span class="n">setDelay</span><span class="p">(</span><span class="mf">1.5</span><span class="n">f</span><span class="p">);</span>
<span class="n">s</span><span class="o">-&gt;</span><span class="n">setLooptype</span><span class="p">(</span><span class="n">LoopTypes</span><span class="o">::</span><span class="n">Yoyo</span><span class="p">);</span>
<span class="n">s</span><span class="o">-&gt;</span><span class="n">setCallback</span><span class="p">(</span><span class="n">cb</span><span class="p">);</span> <span class="c1">// more on callbacks at the end of this post</span>

<span class="n">Action</span><span class="o">::</span><span class="n">addSingle</span><span class="p">(</span><span class="n">s</span><span class="p">);</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">Action::addSingle</code> automatically starts the interpolation (including its delay).</p>

<h3 id="groups-and-sequences">Groups and Sequences</h3>

<p>Now what about groups and sequences?</p>

<p>Let’s first create a list of <code class="language-plaintext highlighter-rouge">Singles</code>:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">SingleBase</span><span class="o">*&gt;</span> <span class="n">singleList</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">SingleBase</span><span class="o">*&gt;</span>
<span class="p">{</span>
    <span class="n">Action</span><span class="o">::</span><span class="n">createSingle</span><span class="p">(</span><span class="o">&amp;</span><span class="n">value1</span><span class="p">,</span>
                         <span class="mf">3.0</span><span class="n">f</span><span class="p">,</span>
                         <span class="mf">2.5</span><span class="n">f</span><span class="p">,</span>
                         <span class="n">TimingFunctions</span><span class="o">::</span><span class="n">ExponentialEaseIn</span><span class="p">),</span>

    <span class="n">Action</span><span class="o">::</span><span class="n">createSingle</span><span class="p">(</span><span class="o">&amp;</span><span class="n">value2</span><span class="p">,</span>
                         <span class="mf">3.0</span><span class="n">f</span><span class="p">,</span>        <span class="c1">// no delay on this one.</span>
                         <span class="n">TimingFunctions</span><span class="o">::</span><span class="n">ExponentialEaseOut</span><span class="p">)</span>
<span class="p">};</span></code></pre></figure>

<p class="notice--warning">You’ll notice here that we call <code class="language-plaintext highlighter-rouge">Action::createSingle</code> as opposed to <code class="language-plaintext highlighter-rouge">Action::addSingle</code>. The former simply returns a <code class="language-plaintext highlighter-rouge">Single</code> object without adding it to the pool of actions, whereas the latter creates the <code class="language-plaintext highlighter-rouge">Single</code>, adds it to the pool, but doesn’t return anything.</p>

<p class="notice">You can also create <code class="language-plaintext highlighter-rouge">Singles</code> like above on your own and create a list of them that way.</p>

<p>After the list of singles is constructed, creating a <code class="language-plaintext highlighter-rouge">Group</code> or <code class="language-plaintext highlighter-rouge">Sequence</code> is very straightforward:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">Callback</span> <span class="n">groupCB</span>    <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">bind</span><span class="p">([</span><span class="o">&amp;</span><span class="p">](){</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span><span class="s">"GROUP COMPLETE</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>    <span class="p">}),</span>
         <span class="n">sequenceCB</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">bind</span><span class="p">([</span><span class="o">&amp;</span><span class="p">](){</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span><span class="s">"SEQUENCE COMPLETE</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="p">}),</span>

<span class="n">Action</span><span class="o">::</span><span class="n">addGroupFrom</span>   <span class="p">(</span><span class="n">singleList</span><span class="p">,</span> <span class="c1">// list of singles     </span>
                        <span class="mf">1.0</span><span class="n">f</span><span class="p">,</span>       <span class="c1">// additional delay on top of singles' delays     </span>
                        <span class="n">groupCB</span><span class="p">);</span>   <span class="c1">// callback for when the entire group is done</span>

<span class="n">Action</span><span class="o">::</span><span class="n">addSequenceFrom</span><span class="p">(</span><span class="n">singleList</span><span class="p">,</span>      
                        <span class="mf">1.0</span><span class="n">f</span><span class="p">,</span>             
                        <span class="n">sequenceCB</span><span class="p">);</span></code></pre></figure>

<p>Like <code class="language-plaintext highlighter-rouge">Singles</code>, <code class="language-plaintext highlighter-rouge">Action::addGroupFrom</code> and <code class="language-plaintext highlighter-rouge">addSequenceFrom</code> automatically starts the interpolations.</p>

<p>  All that’s left is to call <code class="language-plaintext highlighter-rouge">Action::update();</code> in your main game loop (otherwise none of the actions will run).</p>

<h3 id="a-word-on-callbacks">A word on callbacks.</h3>

<p>Callbacks are typedefs of <code class="language-plaintext highlighter-rouge">std::function&lt;void()&gt;</code>. Thus, we can use <code class="language-plaintext highlighter-rouge">std::bind</code> and lambda function notation to create callbacks:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">Callback</span> <span class="n">exampleCB</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">bind</span><span class="p">([</span><span class="o">&amp;</span><span class="p">](){</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span><span class="s">"SINGLE COMPLETE</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span> <span class="p">});</span></code></pre></figure>

<p>The beauty of them being lambdas means any code can be executed as a callback. Going back to our example <code class="language-plaintext highlighter-rouge">t</code> class from the start of this post:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">Callback</span> <span class="n">cb</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">bind</span><span class="p">([</span><span class="o">&amp;</span><span class="p">]()</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">temp</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="k">while</span><span class="p">(</span><span class="n">temp</span> <span class="o">&lt;</span> <span class="mi">100</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">t</span><span class="o">-&gt;</span><span class="n">someRandomFunction</span><span class="p">(</span><span class="n">temp</span><span class="p">);</span>
        <span class="n">example</span> <span class="o">+=</span> <span class="mi">5</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">});</span></code></pre></figure>

<p>Creating a <code class="language-plaintext highlighter-rouge">Single</code> with a callback is as simple as:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">Action</span><span class="o">::</span><span class="n">addSingle</span><span class="p">(</span><span class="o">&amp;</span><span class="n">value</span><span class="p">,</span>
                  <span class="mf">3.0</span><span class="n">f</span><span class="p">,</span>   <span class="c1">// duration  </span>
                  <span class="mf">0.5</span><span class="n">f</span><span class="p">,</span>   <span class="c1">// delay</span>
                  <span class="n">TimingFunctions</span><span class="o">::</span><span class="n">ExponentialEaseIn</span><span class="p">,</span>
                  <span class="n">std</span><span class="o">::</span><span class="n">bind</span><span class="p">([</span><span class="o">&amp;</span><span class="p">](){</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"SINGLE COMPLETE"</span><span class="p">;</span> <span class="p">}));</span></code></pre></figure>

<p>Or, using the above callback:</p>

<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">Callback</span> <span class="n">cb</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">bind</span><span class="p">([</span><span class="o">&amp;</span><span class="p">]()</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">temp</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="k">while</span><span class="p">(</span><span class="n">temp</span> <span class="o">&lt;</span> <span class="mi">100</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">t</span><span class="o">-&gt;</span><span class="n">someRandomFunction</span><span class="p">(</span><span class="n">temp</span><span class="p">);</span>
        <span class="n">example</span> <span class="o">+=</span> <span class="mi">5</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">});</span>


<span class="n">Action</span><span class="o">::</span><span class="n">addSingle</span><span class="p">(</span><span class="o">&amp;</span><span class="n">value</span><span class="p">,</span>
                  <span class="mf">3.0</span><span class="n">f</span><span class="p">,</span>   <span class="c1">// duration  </span>
                  <span class="mf">0.5</span><span class="n">f</span><span class="p">,</span>   <span class="c1">// delay</span>
                  <span class="n">TimingFunctions</span><span class="o">::</span><span class="n">ExponentialEaseIn</span><span class="p">,</span>
                  <span class="n">cb</span><span class="p">);</span></code></pre></figure>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[Easing, tweening, interpolating. Whatever you know it as – it holds a special place in my heart.]]></summary></entry><entry><title type="html">Office Mayhem is going to PAX!</title><link href="https://tyskwo.com/2017/office-mayhem-is-going-to-pax/" rel="alternate" type="text/html" title="Office Mayhem is going to PAX!" /><published>2017-03-03T00:00:00+00:00</published><updated>2017-03-03T00:00:00+00:00</updated><id>https://tyskwo.com/2017/office-mayhem-is-going-to-pax</id><content type="html" xml:base="https://tyskwo.com/2017/office-mayhem-is-going-to-pax/"><![CDATA[<p>That’s right! <em>Office Mayhem</em> was chosen by Champlain College to represent the school at PAXEast this coming weekend in Boston. This is such a huge honor for us as there is no lack of talent or amazing projects at Champlain right now. Be sure to stop by if you’re attending the conference! It’s acting as a big morale boost for the team, even though there’s been no shortage of inspiration this past week. <a href="https://npaquettewordpress.wordpress.com">Norman</a> has been hard at work finishing up more character heads, and we’re trying our hardest to get four distinct characters in for PAX. <a href="https://andrewmillsapblog.wordpress.com">Andy</a> and <a href="http://andrewmessier.blogspot.com">Andrew</a> have finally gotten the character animations into the build, and they add so much life to the game. <a href="http://richardkingcapstone.blogspot.com">Richard</a> has added a new round of sound effects for our new office toys. I have finished adding the rest of the base tasks and interruptables, allowing us to focus more on group interactions in the coming weeks. We also have added Konami code detection to the start screen, which rains down the entire alphabet for true Scrabble gameplay. We also have cleaned up the rougher edges of the code base, which has in the process squashed the majority of the (relatively few) bugs that have popped up at QA recently. If I could say so myself, <em>Office Mayhem</em> is shaping up quite nicely: it plays smoothly and has a nice amount of polish to it, and I hope that shows well at PAX.</p>

<p><img src="https://tyskwo.com/assets/images/blog/2017/03/konami.png" alt="konami" /></p>

<p>This coming week, our main focus is to add the final touches for PAX. Things like adding the other characters, adding an attract mode of sorts, and the big bucket item: reimplementing the break rooms. Rather than being traditional break rooms, we’re making the entire floor a whiteboard that players can draw on. Tony’s been hard at work over the past week, and he’s making really great progress on that front. I’ll be focusing on smaller issues like adding more particle effects where needed, and iterating on the (now outdated) tutorial.</p>

<hr />

<p>Today during class, we were talking about adding a ball pit cheat to the start screen. I said why not?</p>

<p><img src="https://tyskwo.com/assets/images/blog/2017/03/ballpit.gif" alt="ball-pit" /></p>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[Stay calm. On a different note, so much has been added this past week.]]></summary></entry><entry><title type="html">A Quiet Week in No Man’s Land</title><link href="https://tyskwo.com/2017/a-quiet-week-in-no-mans-land/" rel="alternate" type="text/html" title="A Quiet Week in No Man’s Land" /><published>2017-02-26T00:00:00+00:00</published><updated>2017-02-26T00:00:00+00:00</updated><id>https://tyskwo.com/2017/a-quiet-week-in-no-mans-land</id><content type="html" xml:base="https://tyskwo.com/2017/a-quiet-week-in-no-mans-land/"><![CDATA[<p>It’s been quiet in the office this week (note: we don’t actually work in an office, but we’re <em>Office Mayhem</em>, so I had a moral obligation to make the joke). The art team has been hard at work tidying up assets and animations, and the design team has been balancing the task and movement systems. The engineering team has been hard at work at polishing the edges. <a href="https://tonyl.info/">Tony</a> has been hard at work <a href="https://tonyl.info/2017/02/09/office-mayhem-extending-unity/">cleaning up the elevator interface for our designers,</a> and Andy has been crunching the animation pipeline behind the scenes. I spent this week hunting down any remaining bugs.</p>

<p>There wasn’t a lot of visual progress this week, but that’s ok. The game as a whole is stronger, and we have a lot planned for these coming weeks. We’ve come to a new solution to the break rooms (but for now is under wraps), and that will be a large (and probably difficult) project over the next week. We’re hoping to get Norman’s characters with Andrew’s animations into the actual build this week, and we’re excited to see just how much life they add to the office. The accolade system is also very close to being implemented; we just need to decide on the final representation of them and how they’ll affect the players/break room environment. We also cleaned up <code class="language-plaintext highlighter-rouge">Interruptables</code> this past week, so we’re hoping and excited to start adding group task types to the mix (and with that comes the concept of point stages and difficulty curves).</p>

<p>We have a lot on our plate this coming week (obviously), and that’s not even including the smaller things like replacing outdated models, cleaning up some of our data-holding architecture, and implementing the alphabet rain in the start menu when the Konami code is input. (I really hope if <em>Office Mayhem</em> reaches the public, someone stumbles upon this post and realizes the immense power they have just unlocked). It’s going to be a long, but very exciting week.</p>

<hr />

<p>In other news, <a href="https://gauzewave.wordpress.com">David</a> and I finally finished our particle system project for Game Physics, and I could not be happier with the result. Expect a write-up on that sometime this week.</p>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[Bug fixes galore, but it's the calm before the storm.]]></summary></entry><entry><title type="html">Designing a Protocol-Oriented, Event-Driven Entity-Component System*</title><link href="https://tyskwo.com/2017/designing-a-protocol-oriented-event-driven-ecs/" rel="alternate" type="text/html" title="Designing a Protocol-Oriented, Event-Driven Entity-Component System*" /><published>2017-02-21T00:00:00+00:00</published><updated>2017-02-21T00:00:00+00:00</updated><id>https://tyskwo.com/2017/designing-a-protocol-oriented-event-driven-ecs</id><content type="html" xml:base="https://tyskwo.com/2017/designing-a-protocol-oriented-event-driven-ecs/"><![CDATA[<p>I have decided to pick up <em><a href="https://tyskwo.com/2015/DASHockey-At-GMGF/">DASHockey again.</a></em> When I last touched it (almost two years ago), the codebase was complete garbage. I tackled the game as a foray into developing for the then-new AppleTV and to be able to present it at the <em>Green Mountains Game Festival</em>. As such, getting a complete game with AI out in a week was a pretty large task. Since I’m tackling it anew, I figured I should be a good programmer and rewrite the game from the ground up. I eventually want <em>DASHockey</em> to have iPhone-connected remotes for true party game multiplayer, but for now let’s focus on the base architecture.</p>

<p class="notice--info">This post assumes the reader has a decent understanding of Swift. Thankfully, it’s a very verbose language, so it shouldn’t be too hard to get the high-level architecture from it. See <a href="https://swift.org/documentation/">Apple’s Swift handbook</a> for a great resource on Swift.</p>

<h3 id="the-entity">The Entity</h3>

<p>In this protocol-oriented, event-driven example, the base entity isn’t too different from the <a href="http://gameprogrammingpatterns.com/component.html">classic pattern.</a>:</p>

<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">class</span> <span class="kt">Entity</span>
<span class="p">{</span>
    <span class="k">var</span> <span class="nv">components</span><span class="p">:[</span><span class="kt">Component</span><span class="p">]</span>

    <span class="c1">// name and tag attached to this entity</span>
    <span class="kd">private</span> <span class="k">var</span> <span class="nv">name</span><span class="p">:</span><span class="kt">String</span>
    <span class="kd">private</span> <span class="k">var</span> <span class="nv">tag</span><span class="p">:</span> <span class="kt">String</span><span class="p">?</span>



    <span class="nf">init</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">components</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">name</span> <span class="o">=</span> <span class="s">"NONE"</span>
    <span class="p">}</span>

    <span class="nf">init</span><span class="p">(</span><span class="nv">name</span><span class="p">:</span><span class="kt">String</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">components</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
    <span class="p">}</span>

    <span class="nf">init</span><span class="p">(</span><span class="nv">name</span><span class="p">:</span><span class="kt">String</span><span class="p">,</span> <span class="nv">tag</span><span class="p">:</span><span class="kt">String</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">components</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="k">self</span><span class="o">.</span><span class="n">tag</span>  <span class="o">=</span> <span class="n">tag</span>
    <span class="p">}</span>


    <span class="kd">func</span> <span class="nf">set</span><span class="p">(</span><span class="nv">tag</span><span class="p">:</span><span class="kt">String</span><span class="p">)</span>  <span class="p">{</span> <span class="k">self</span><span class="o">.</span><span class="n">tag</span>  <span class="o">=</span> <span class="n">tag</span>  <span class="p">}</span>
    <span class="kd">func</span> <span class="nf">set</span><span class="p">(</span><span class="nv">name</span><span class="p">:</span><span class="kt">String</span><span class="p">)</span> <span class="p">{</span> <span class="k">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="p">}</span>


    <span class="kd">func</span> <span class="nf">getTag</span><span class="p">()</span>  <span class="o">-&gt;</span> <span class="kt">String</span> <span class="p">{</span> <span class="k">return</span> <span class="k">self</span><span class="o">.</span><span class="n">tag</span> <span class="p">??</span> <span class="s">"NONE"</span> <span class="p">}</span>
    <span class="kd">func</span> <span class="nf">getName</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">String</span> <span class="p">{</span> <span class="k">return</span> <span class="k">self</span><span class="o">.</span><span class="n">name</span>          <span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>Here, we have a simple array of <code class="language-plaintext highlighter-rouge">Component</code> objects (which we’ll get to), a name and tag to reference this entity by, and methods for getting/setting these values. But what about finding components in our bucket?</p>

<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">extension</span> <span class="kt">Entity</span>
<span class="p">{</span>
    <span class="c1">// get first component of type T</span>
    <span class="kd">func</span> <span class="n">find</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span><span class="p">(</span><span class="nv">component</span><span class="p">:</span> <span class="kt">T</span><span class="o">.</span><span class="k">Type</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">T</span><span class="p">?</span>
    <span class="p">{</span>
        <span class="k">for</span> <span class="n">item</span> <span class="k">in</span> <span class="n">components</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="n">item</span> <span class="k">is</span> <span class="kt">T</span>
            <span class="p">{</span>
                <span class="nf">return</span> <span class="p">(</span><span class="n">item</span> <span class="k">as!</span> <span class="kt">T</span><span class="p">)</span>
            <span class="p">}</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="kc">nil</span>
    <span class="p">}</span>

    <span class="c1">// get all components of type T</span>
    <span class="kd">func</span> <span class="n">findAllOf</span><span class="o">&lt;</span><span class="kt">T</span><span class="o">&gt;</span><span class="p">(</span><span class="nv">component</span><span class="p">:</span> <span class="kt">T</span><span class="o">.</span><span class="k">Type</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="kt">T</span><span class="p">]</span>
    <span class="p">{</span>
        <span class="k">var</span> <span class="nv">returnArray</span><span class="p">:[</span><span class="kt">T</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">for</span> <span class="n">item</span> <span class="k">in</span> <span class="n">components</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="n">item</span> <span class="k">is</span> <span class="kt">T</span>
            <span class="p">{</span>
                <span class="n">returnArray</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="n">item</span> <span class="k">as!</span> <span class="kt">T</span><span class="p">)</span>
            <span class="p">}</span>
        <span class="p">}</span>

        <span class="k">return</span> <span class="n">returnArray</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="c1">// sample use:</span>
<span class="k">let</span> <span class="nv">rink</span> <span class="o">=</span> <span class="k">self</span><span class="o">.</span><span class="nf">find</span><span class="p">(</span><span class="nv">component</span><span class="p">:</span> <span class="kt">Rink</span><span class="o">.</span><span class="k">self</span><span class="p">)</span><span class="o">!</span></code></pre></figure>

<p>Here, we use generics to be able to return any type of component (This is very similar to how Unity handles its ECS). In the singular search, we use the power of optionals to elegantly return nil if there’s no such component attached to this entity. For the multi-search, we return an empty array. In the sample use, notice that we use <code class="language-plaintext highlighter-rouge">ComponentType.self</code>. The <code class="language-plaintext highlighter-rouge">.self</code> is necessary to reference the class type, and not just the member type. It’s a small syntactical hiccup, but I think it is worth the power and flexibility it provides. If you’re savvy, you’ll notice this is in an <em>extension</em> of <code class="language-plaintext highlighter-rouge">Entity</code>. I did this simply for organization purposes: we don’t declare any new member variables, so we can place these function in an extension. I name my extensions in comments for easy finding; this one is the ‘search extension’.</p>

<p>For adding and updating components, we use a similar extension:</p>

<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">extension</span> <span class="kt">Entity</span>
<span class="p">{</span>
    <span class="kd">func</span> <span class="nf">add</span><span class="p">(</span><span class="nv">component</span><span class="p">:</span><span class="kt">Component</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">components</span><span class="o">.</span><span class="nf">append</span><span class="p">(</span><span class="n">component</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="c1">// update all components that conform to UpdateableComponent</span>
    <span class="kd">func</span> <span class="nf">update</span><span class="p">(</span><span class="nv">dt</span><span class="p">:</span> <span class="kt">Double</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">for</span> <span class="n">item</span> <span class="k">in</span> <span class="n">components</span> <span class="k">where</span> <span class="n">item</span> <span class="k">is</span> <span class="kt">Updateable</span>
        <span class="p">{</span>
            <span class="p">(</span><span class="n">item</span> <span class="k">as!</span> <span class="kt">Updateable</span><span class="p">)</span><span class="o">.</span><span class="nf">update</span><span class="p">(</span><span class="n">dt</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>Adding is simple enough, but what exactly is happening with <code class="language-plaintext highlighter-rouge">update</code>? Swift 2 added the <a href="https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html"><code class="language-plaintext highlighter-rouge">where</code> clause</a> – basically a filter on an array. Thus, in <code class="language-plaintext highlighter-rouge">update</code>, we are iterating over all of our components, and if the current one is an <code class="language-plaintext highlighter-rouge">Updateable</code> component, we call its <code class="language-plaintext highlighter-rouge">update</code> method. It’ll make more sense in a little bit.</p>

<p>That, at its core, is the entity in this system. It’s not very complicated, but can be easily expanded, which is always a great goal to have.</p>

<h3 id="the-component">The Component</h3>

<p>At its root, the <code class="language-plaintext highlighter-rouge">Component</code> class has similar initializers, name and tag functions as the <code class="language-plaintext highlighter-rouge">Entity</code> class. The interesting functionality comes from the use of protocols:</p>

<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="c1">// in Component.swift:</span>

<span class="kd">protocol</span> <span class="kt">Updateable</span>
<span class="p">{</span>
    <span class="kd">func</span> <span class="nf">update</span><span class="p">(</span><span class="n">_</span> <span class="nv">dt</span><span class="p">:</span> <span class="kt">Double</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">protocol</span> <span class="kt">Renderable</span>
<span class="p">{</span>
    <span class="kd">func</span> <span class="nf">addToScene</span><span class="p">()</span>
    <span class="kd">func</span> <span class="nf">get</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">SKNode</span>
    <span class="kd">func</span> <span class="nf">destroy</span><span class="p">()</span>
<span class="p">}</span></code></pre></figure>

<p>This is designating that any component that conforms to the <code class="language-plaintext highlighter-rouge">Updateable</code> component will have to contain a definition for the function <code class="language-plaintext highlighter-rouge">update</code> that takes a double as a parameter (and similarly for the <code class="language-plaintext highlighter-rouge">Renderable</code> protocol). What this does, at least in my setup, is that it takes items like the players, puck, and nets, and turns them from entities that would have to be handled by the scene to components that are held by a single entity. Basically, it’ just a reduction of one more layer, and it can be argued that it’s just renaming the architecture, shifting it up a level, but more importantly, it allows the puck object to contain all of its own logic, broken up into extensions and protocol implementations. Yes, in games with hundreds of thousands of objects this would not be ideal, but in <em>DASHockey</em> where there are never more than ten objects in a scene, it works very well. For instance:</p>

<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">extension</span> <span class="kt">Puck</span><span class="p">:</span> <span class="kt">Renderable</span>
<span class="p">{</span>
    <span class="kd">func</span> <span class="nf">addToScene</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">scene</span><span class="o">.</span><span class="nf">addChild</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="kd">func</span> <span class="nf">get</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kt">SKNode</span>
    <span class="p">{</span>
        <span class="k">return</span> <span class="n">node</span>
    <span class="p">}</span>

    <span class="kd">func</span> <span class="nf">destroy</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">node</span><span class="o">.</span><span class="nf">removeFromParent</span><span class="p">()</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>Here’s the puck’s implementation of the <code class="language-plaintext highlighter-rouge">Renderable</code> protocol. Granted, it is extremely simple, but it allows for complete customization on a puck-level basis. In a sense, its similar to prefabs in Unity.</p>

<p>Another high-level advantage of this system is that it allows for event-like components, like a <code class="language-plaintext highlighter-rouge">GoalScored</code> component:</p>

<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">protocol</span> <span class="kt">GoalScoredComponent</span>
<span class="p">{</span>
    <span class="kd">func</span> <span class="nf">goalScored</span><span class="p">(</span><span class="nv">team</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span>
<span class="p">}</span>

<span class="o">.....</span>

<span class="kd">extension</span> <span class="kt">Rink</span><span class="p">:</span> <span class="kt">GoalScoredComponent</span>
<span class="p">{</span>
    <span class="kd">func</span> <span class="nf">goalScored</span><span class="p">(</span><span class="nv">team</span><span class="p">:</span> <span class="kt">String</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="n">team</span> <span class="o">==</span> <span class="s">"red"</span>
        <span class="p">{</span>
            <span class="n">scene</span><span class="o">.</span><span class="n">backgroundColor</span> <span class="o">=</span> <span class="o">.</span><span class="n">red</span>
        <span class="p">}</span>
        <span class="k">else</span> <span class="k">if</span> <span class="n">team</span> <span class="o">==</span> <span class="s">"blue"</span>
        <span class="p">{</span>
            <span class="n">scene</span><span class="o">.</span><span class="n">backgroundColor</span> <span class="o">=</span> <span class="o">.</span><span class="n">blue</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>This, in turn, allows the code called for when a goal is scored be this:</p>

<figure class="highlight"><pre><code class="language-swift" data-lang="swift"><span class="kd">func</span> <span class="nf">goalScored</span><span class="p">(</span><span class="nv">net</span><span class="p">:</span> <span class="kt">Net</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">goalScored</span> <span class="o">=</span> <span class="kc">true</span>

    <span class="c1">// find all of the GoalScored components and let them do their thing</span>
    <span class="k">let</span> <span class="nv">score</span> <span class="o">=</span> <span class="kt">SKAction</span><span class="o">.</span><span class="nf">run</span><span class="p">({</span>
        <span class="k">for</span> <span class="n">c</span> <span class="k">in</span> <span class="k">self</span><span class="o">.</span><span class="n">entity</span><span class="o">.</span><span class="nf">findAllOf</span><span class="p">(</span><span class="nv">component</span><span class="p">:</span> <span class="kt">GoalScoredComponent</span><span class="o">.</span><span class="k">self</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">c</span><span class="o">.</span><span class="nf">goalScored</span><span class="p">(</span><span class="nv">team</span><span class="p">:</span> <span class="n">net</span><span class="o">.</span><span class="nf">getTag</span><span class="p">())</span>
        <span class="p">}</span>
    <span class="p">})</span>

    <span class="c1">// find all of the GoalReset components and let them do their thing</span>
    <span class="k">let</span> <span class="nv">reset</span> <span class="o">=</span> <span class="kt">SKAction</span><span class="o">.</span><span class="nf">run</span><span class="p">({</span>
        <span class="k">for</span> <span class="n">c</span> <span class="k">in</span> <span class="k">self</span><span class="o">.</span><span class="n">entity</span><span class="o">.</span><span class="nf">findAllOf</span><span class="p">(</span><span class="nv">component</span><span class="p">:</span> <span class="kt">GoalResetComponent</span><span class="o">.</span><span class="k">self</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">c</span><span class="o">.</span><span class="nf">reset</span><span class="p">()</span>
        <span class="p">}</span>
    <span class="p">})</span>

    <span class="c1">// let there be a pause between for the celebration</span>
    <span class="k">let</span> <span class="nv">wait</span> <span class="o">=</span> <span class="kt">SKAction</span><span class="o">.</span><span class="nf">wait</span><span class="p">(</span><span class="nv">forDuration</span><span class="p">:</span> <span class="mi">5</span><span class="p">)</span> <span class="c1">//global goal celebration length</span>

    <span class="c1">// create a sequence from it</span>
    <span class="k">let</span> <span class="nv">sequence</span> <span class="o">=</span> <span class="kt">SKAction</span><span class="o">.</span><span class="nf">sequence</span><span class="p">([</span><span class="n">score</span><span class="p">,</span> <span class="n">wait</span><span class="p">,</span> <span class="n">reset</span><span class="p">])</span>

    <span class="c1">// and run it! upon completion, start a new faceoff</span>
    <span class="n">scene</span><span class="o">.</span><span class="nf">run</span><span class="p">(</span><span class="n">sequence</span><span class="p">,</span> <span class="nv">completion</span><span class="p">:</span> <span class="p">{</span>
        <span class="k">self</span><span class="o">.</span><span class="n">goalScored</span> <span class="o">=</span> <span class="kc">false</span>
        <span class="k">self</span><span class="o">.</span><span class="n">entity</span><span class="o">.</span><span class="nf">add</span><span class="p">(</span><span class="nv">component</span><span class="p">:</span> <span class="kt">Faceoff</span><span class="p">(</span><span class="nv">entity</span><span class="p">:</span> <span class="k">self</span><span class="o">.</span><span class="n">entity</span><span class="p">,</span> <span class="nv">name</span><span class="p">:</span> <span class="s">"faceoff"</span><span class="p">,</span> <span class="nv">tag</span><span class="p">:</span> <span class="s">"UI"</span><span class="p">))</span>
    <span class="p">})</span>
<span class="p">}</span></code></pre></figure>

<p>This code is incredibly concise, verbose, and clean. It pushes all of the logic of the objects into the objects themselves. It’s not without its flaws: it won’t work well for larger systems, it is hard to customize objects on a per-instance basis, and objects are authoritative over their own implementation. For <em>DASHockey</em> though, this is a great system that allows the game to run in a concise matter.</p>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[Super long (but descriptive) title, with way too many dashes and buzz words. *In Swift!]]></summary></entry><entry><title type="html">Hang on, I need to answer the phone.</title><link href="https://tyskwo.com/2017/hang-on-i-need-to-answer-the-phone/" rel="alternate" type="text/html" title="Hang on, I need to answer the phone." /><published>2017-02-17T00:00:00+00:00</published><updated>2017-02-17T00:00:00+00:00</updated><id>https://tyskwo.com/2017/hang-on-i-need-to-answer-the-phone</id><content type="html" xml:base="https://tyskwo.com/2017/hang-on-i-need-to-answer-the-phone/"><![CDATA[<p>Interruptables are now in <em>Office Mayhem</em>. They are a new type of task, with a few additional rules. A single player is assigned them, and the color of the card is that player’s color. If they complete the interruptable before the timer expires, they’re safe. If they let the timer run out though, they lose the number of points on the card. Furthermore, if another player ‘steals’ it, the player who stole it <em>gains</em> points, and the player it was assigned to loses points.</p>

<p><img src="https://tyskwo.com/assets/images/blog/2017/02/interruptable.gif" alt="interruptable-example" class="align-center" /></p>

<p>Bringing interruptables to testing has seemed to be positive so far, but it is still in its early stages. There is a bug where the timer doesn’t always start, rendering the interruptable uncomplete-able, but I hope to have that fixed for this coming week. We are happy to report that interruptables are doing their assigned job of making sure players are looking at the task cards and not just completing tasks that they think will be active. Up until this point, we only had four tasks, so the chances of completing a random task and being awarded points for it was a high probability, but as we add more tasks, players will have to look at what tasks are active. Interruptables are making players do this, and the player don’t seem to think it’s unfair, which is great for the roadmap of new tasks we want to implement.</p>

<figure class="align-center">
 <img src="https://tyskwo.com/assets/images/blog/2017/02/interruptable-steal.gif" />
  <figcaption>Interruptables can be stolen - the player who steals it gets points.</figcaption>
</figure>

<p>In other news, <a href="http://andrewmillsapblog.wordpress.com">Andy</a> has completed our long-overdue intro sequence. Before each round starts, the camera is zoomed out, showcasing the entire level (and giving players an opportunity to locate all of the items in the level) before displaying what ‘day of the week’ it is and zooming in. It’s a small change, but it adds so much to the flow between levels, and players have really been appreciative of being able to glance at the entire level before being put into the action. Andy also has updated our <code class="language-plaintext highlighter-rouge">ScoreCard</code> UI so that it is easier to see which player is in the lead without having to read all of the scores – it’s like a reverse cell service icon.</p>

<p><img src="https://tyskwo.com/assets/images/blog/2017/02/scorecard-example.gif" alt="scorecard-example" class="align-center" /></p>

<p><a href="http://tonyl.info">Tony</a> fleshed out the framework for our accolade system. Right now, all it keeps track of is number of tasks completed and number of items sabotaged, but the framework is complete, which was a pretty large undertaking. The next task obviously is to create the actual accolades on the end screen and to award them to players. The team is still trying to figure out the best way to do this. On one hand, we really want to have in-office trophies the color of the player that won it, but we don’t know an easy way to distinguish the different accolades that way. Tony is also working on a transition framework to better hide the switching of Unity scenes.</p>
<figure class="align-right" style="width:350px">
 <img src="https://tyskwo.com/assets/images/blog/2017/02/charlie-run.gif" />
  <figcaption>He's on a treadmill right now, but soon enough he'll be running through the office.</figcaption>
</figure>
<p>For instance, on the start menu when all of the players crowd around the door to go to the first level, everything freezes as Unity’s <code class="language-plaintext highlighter-rouge">SceneManager</code> class loads the <code class="language-plaintext highlighter-rouge">level_1</code> scene. We hope to mask this by putting some sort of fade/screen-wipe, etc. on either end of loading a scene. It’s a polish mechanic, but I think it would add a lot to the professionalism of <em>Office Mayhem.</em></p>

<p>The art team has been hard at work this past week. <a href="https://npaquettewordpress.wordpress.com">Norman</a> has finished our first character, Charles, and <a href="http://andrewmessier.blogspot.com">Andrew</a> has finished animating him. I’m excited to get these into the build. <a href="https://willconcannonart.com">Will</a> has been hard at work cleaning up some of the pre-existing assets (like the computer and outbox) to make sure they read the better in the office, and creating new assets like the coffee pot, bathroom door, and server rack (Wait, a server rack? Yes, stay tuned).</p>

<figure class="align-right" style="width:200px">
 <img src="https://tyskwo.com/assets/images/blog/2017/02/upcomingWork.png" />
  <figcaption>If you are Sherlock Holmes, you might be able to figure out some of our planned features on the left.</figcaption>
</figure>

<p>This coming week we plan on cleaning up a lot of smaller polish-level issues we have been neglecting over the past couple of weeks. While doing that, the programming team also hopes to clean up some of the rough edges of the codebase, specifically relating to the way <code class="language-plaintext highlighter-rouge">Interruptables</code> are handled on the back end, and smaller changes to the elevator, accolade, and message systems. The artists are cranking away at new environment assets, characters and animations, and the design team is going to be hard at work creating and balancing new tasks and laying out new levels. The end of the semester is fast approaching, and we’re super excited to see how much (and what) we can add to <em>Office Mayhem</em> before then.</p>

<p>Also, I mentioned <a href="https://tyskwo.com/2017/graduation-t-14-weeks/">a couple of weeks ago</a> that I was working on transferring my website from Wordpress to my own self-hosted solution. Hopefully you noticed the site is a little different? I’m super excited because I finally have full control over things like the CSS, asset management, etc. In my opinion, this new site is a lot cleaner. Have a look around!</p>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[I just hate when I'm interrupted.]]></summary></entry><entry><title type="html">Iteration.</title><link href="https://tyskwo.com/2017/iteration/" rel="alternate" type="text/html" title="Iteration." /><published>2017-02-10T00:00:00+00:00</published><updated>2017-02-10T00:00:00+00:00</updated><id>https://tyskwo.com/2017/iteration</id><content type="html" xml:base="https://tyskwo.com/2017/iteration/"><![CDATA[<p>It’s been a relatively slow week for <em>Office Mayhem</em>, but <em>9:5 Games</em> has still accomplished a lot this past week: the artists have been working on models, characters, and rigs, the designers have been producing new sound effects, building levels, and balancing systems, and the programmers have been finishing systems from last week. <a href="http://tonyl.info">Tony</a> finished up the elevator from last week and implemented a revised dash system that uses a cool down to discourage players from constantly mashing the B-button as fast as humanly (or inhumanly) as possible. To combat this, the designers (and Tony) created a coffee pot item that allows players to move at their fastest speed for a little while after using it. It hasn’t gone through much testing, but it has already created a couple new strategies from what we’ve seen.</p>

<p><a href="https://andrewmillsapblog.wordpress.com">Andy</a> spent this week finishing up crunch time to make it more pressure-inducing for the players (and more obvious what’s going on!), and reworking the score card UI so players can more easily figure out who’s winning (and thus whose computer to break).</p>

<p>I spent this week squashing the few bugs that have been popping up in QA, as well as lending a helping hand to Tony and Andy when they’ve needed it. I created a <code class="language-plaintext highlighter-rouge">DataHolder</code> class that helps keep track of game data between rounds, which will be the start of our outer game loop framework, and I started the <code class="language-plaintext highlighter-rouge">Interruptable</code> framework. For now, I’m going the fast and easy, if not sloppy, route to get it working and tested first before spending the time to refactor it into the current task system. I would rather not waste the time to implement it cleanly and have QA rip it out of the game.</p>

<p>This coming week, I’m hoping to finish up interruptables, and I’m hoping Tony and Andy can clean up transitions between scenes, and start the accolade system. I feel like morale fell slightly this week (whether because of lack of visual progress, the plague that’s going around, or simply unenthused to tackle the problems at hand), so I’m hoping to give them (and the rest of the team) more freedom to decide what they want to work on.</p>

<p>Expect gifs and code next week :)</p>

<p>In other news, <a href="https://gauzewave.wordpress.com">David</a> and I are creating a particle system container in Game Physics, and it’s shaping up quite nicely. Expect to see a blog post on it soon.</p>]]></content><author><name>Tyler Wood</name><email>me@tyskwo.com</email></author><summary type="html"><![CDATA[Just need to keep trucking along.]]></summary></entry></feed>