<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>dale.io</title>
    <description>personal website</description>
    <link>https://dale.io/</link>
    <atom:link href="https://dale.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 22 Oct 2024 13:02:35 -0400</pubDate>
    <lastBuildDate>Tue, 22 Oct 2024 13:02:35 -0400</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Rustris Postmortem&amp;#58;  Making Tetris with ggez</title>
        <description>&lt;p&gt;You know what game I love? Tetris. An easy game to play but difficult to master
that’s been released on every platform under the sun. The game has had a strong
following for over 30 years and it’s still going strong. For my next Rust-based
game project, I decided to make my own version of Tetris with basic gameplay
features, a menu screen and game ending states. After a month of working on it
sporadically, I managed to get the project into a state I’m okay with releasing
into the wild (The source code is available
on &lt;a href=&quot;https://github.com/obsoke/rustris&quot;&gt;GitHub&lt;/a&gt;
or &lt;a href=&quot;https://gitlab.com/obsoke/rustris&quot;&gt;GitLab&lt;/a&gt;). Here are some of my thoughts on
challenges faced &amp;amp; choices made during development.&lt;/p&gt;

&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;/h2&gt;

&lt;p&gt;The main goal of this project was to learn how to create Tetris in Rust. It was
&lt;em&gt;not&lt;/em&gt; to learn how to make a game engine in Rust. If I had wanted to do that, I
would have started with something like SDL2 and worked off of that.&lt;/p&gt;

&lt;h2 id=&quot;making-good-games-easily&quot;&gt;Making Good Games Easily&lt;/h2&gt;

&lt;p&gt;After spending some time earlier playing around with the
Lua-based &lt;a href=&quot;https://love2d.org/&quot;&gt;love2d&lt;/a&gt; game framework, picking a Rust framework
influenced by love2d seems like the obvious path to
take. &lt;a href=&quot;http://ggez.rs/&quot;&gt;ggez&lt;/a&gt; fits the bill here, providing easy ways to draw to
the screen, play audio, access the filesystem, render text, handling input and
deal with timing. It doesn’t aim to provide every feature one can want in a game
engine such as entity-component systems or math functions; this functionality
can be provided by already-existing crates. Instead, the focus is on being easy
to get up and running, and to be productive quickly without having to think
about lower level operations. Just like the name of the framework says!&lt;/p&gt;

&lt;p&gt;Personally, I found ggez quite pleasant and easy to work with. Much of ggez
revolves around the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EventHandler&lt;/code&gt; trait. This trait contains required callbacks
that must be implemented (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw()&lt;/code&gt;) as well as a bunch of optional
input-related callbacks. From there, a developer has free reign to do whatever
they please.&lt;/p&gt;

&lt;p&gt;As an example, this is what my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GameEndState&lt;/code&gt; struct looks like:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;pub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GameEndState&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request_replay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request_menu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request_quit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Vec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;current_selection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;game_end_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;graphics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;final_score_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;graphics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;final_line_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;graphics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;final_level_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;graphics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The input system in Rustris is state-based instead of event-based so for smaller
states such as the game over screen, I store a bool for each potential input
response from a user&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. In the state’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update()&lt;/code&gt; method, I check whether any
of these switches have flipped and act accordingly. Options were abstracted into
an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option&lt;/code&gt; struct, so I store a vector of those as well as the currently
selected option. Finally, when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GameEndState&lt;/code&gt; is created, so are any
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;graphics::Text&lt;/code&gt; objects that are required to display some information on
screen. These are stored in the state and drawn to the buffer every frame.&lt;/p&gt;

&lt;p&gt;The simplicity of ggez’s API allowed me to just focus on making the game. Each
state contained what it needed to do its job and that’s it. Whenever I found
myself repeating code across states, I’d lift that code into a module containing
code shared between states. For example, my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option&lt;/code&gt; struct which is used across
multiple states (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MenuState&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GameEndState&lt;/code&gt;), is in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shared&lt;/code&gt; module. It feels
very simple and clean as well as easy to extend later on.&lt;/p&gt;

&lt;h2 id=&quot;bumps-in-the-road&quot;&gt;Bumps in the Road&lt;/h2&gt;

&lt;p&gt;Once work on the main ‘play field’ state was finished and plans for the menu
state began, I had noticed a couple of limitations:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;I had created a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transition&lt;/code&gt; enum listing potential transitions between
states within a state manager. I wanted to have both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;draw()&lt;/code&gt;
return said &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transition&lt;/code&gt;&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; so a state’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update()&lt;/code&gt; method can request state
changes but the ggez &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EventHandler&lt;/code&gt; trait is hardcoded to return an empty
tuple.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;What if I wanted to create an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Assets&lt;/code&gt; object that held all my assets that
lived at the top-level of my object hierarchy? This way, a reference to that
object can be passed to any active states that may need access to an image,
or a sound.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transition&lt;/code&gt; was defined in my code, how would &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EventHandler&lt;/code&gt; even know
about it? This is when I first jumped into the ggez &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event&lt;/code&gt; module source
code in attempts to make the return type generic. This ended a rabbit hole
filled with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Box&lt;/code&gt;es and eventually, failure.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thankfully, ggez is written in a clean and modular way - no spaghetti here. I
was able to simply make my own copy of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event&lt;/code&gt; module and make my needed
changes. I think ideally, there would be a way to define return types from
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EventHandler&lt;/code&gt;from the framework user’s end but for now, this will do. The
problem of passing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Assets&lt;/code&gt; seems like a harder one to solve. I don’t believe
Rust currently has the option to call functions with a variable number of
arguments or optional arguments. For now, editing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;event&lt;/code&gt; module will work
as a solution.&lt;/p&gt;

&lt;h2 id=&quot;other-stuff&quot;&gt;Other stuff&lt;/h2&gt;

&lt;p&gt;Another issue I had actually has to do with one of ggez’s
dependencies. &lt;a href=&quot;https://github.com/tomaka/rodio&quot;&gt;rodio&lt;/a&gt;, created by master crate
creator tomaka. Currently, it doesn’t have a way to stop any audio that is being
played. There is a PR ready to be merged into implement this, and then ggez
simply needs to offer a high-level interface to stop audio&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. This isn’t a
huge deal, but it will be nice to have this functionality when it is finally
implemented.&lt;/p&gt;

&lt;p&gt;The design for both the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Assets&lt;/code&gt; struct and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transitions&lt;/code&gt; enum were shamelessly
inspired by the Rust-based &lt;a href=&quot;https://www.amethyst.rs/&quot;&gt;Amethyst&lt;/a&gt; game engine,
another excellent project. It has tons of great ideas and I’m excited to start
playing around with it in the future on larger projects.&lt;/p&gt;

&lt;p&gt;I implemented a state manager inspired by the “Pushdown Automata” discussed in
the “State” chapter of the excellent
&lt;a href=&quot;http://gameprogrammingpatterns.com/state.html&quot;&gt;Game Programming Patterns&lt;/a&gt;. I
believe that Amethyst also uses a similar pattern which makes sense if my
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transition&lt;/code&gt; enum, used to transition between game states, was inspired by
Amethyst’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Trans&lt;/code&gt; enum. With a state stack, all one needs to do to add a ‘pause
state’ or ‘inventory’ screen’ is to push that state on the stack when needed and
pop it off when done.&lt;/p&gt;

&lt;p&gt;I’m not an artist nor a musician, so I had to rely on open source and freely
licensed assets. All the audio and sound effects were found online and some of
the assets I made, such as the black hole graphic on the menu and the background
of the play field. It’s not the best looking or sounding game in the world but
for what was an educational non-commercial product, I think it did the job.&lt;/p&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;Tetris is a fun game to write in Rust. I don’t think that my code is some kind
of incredible work of art, a standard that other code should be judged against
(if anything, it’s probably the opposite) but I had lots of fun and I learned
quite a bit about making games, making games in Rust and Rust itself. That was
my goal, so mission accomplished! You can check out the source code
on &lt;a href=&quot;https://github.com/obsoke/rustris&quot;&gt;GitHub&lt;/a&gt;
or &lt;a href=&quot;https://gitlab.com/obsoke/rustris&quot;&gt;GitLab&lt;/a&gt;. I don’t have access to a Windows
or Mac right now so I unfortunately cannot produce any binaries to distribute
this at the moment.&lt;/p&gt;

&lt;p&gt;ggez is a great framework to use for small 2D games. I was able to talk with
Icefox, one of the library authors, at the
&lt;a href=&quot;https://air.mozilla.org/game-developement-in-rust/&quot;&gt;Game Development in Rust&lt;/a&gt;
meetup in Toronto on July 7th 2017. He’s a nice &amp;amp; smart guy and after watching
him talk about the future of ggez during his presentation of the framework, I
have 100% confidence that it will continue to grow into a &lt;del&gt;fine young lad&lt;/del&gt;
great framework to use to make good games easily.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;For states with more input such as my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PlayState&lt;/code&gt;, I threw all the
potential state &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt; into its own struct - makes the code easier to read,
in my opinion. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Wrapped in ggez’s custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt; type, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GameResult&lt;/code&gt;. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Yes. Just “simply” implement it. You know, easy! &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sat, 08 Jul 2017 00:00:00 -0400</pubDate>
        <link>https://dale.io/blog/rustris-post-mortem.html</link>
        <guid isPermaLink="true">https://dale.io/blog/rustris-post-mortem.html</guid>
        
        <category>rust</category>
        
        <category>gamedev</category>
        
        <category>ggez</category>
        
        <category>sdl2</category>
        
        <category>tetris</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Automated Publishing Pipeline with Org Mode</title>
        <description>&lt;p&gt;I have some files written in Org that I want to publish &amp;amp; upload to a web server every week at a set time. Why? I’d like to be able to view my notes from anywhere, and others may stumble upon them and find them useful. However, I don’t want to have to remember to publish &amp;amp; upload everytime I make change to these files, and I want this to occur with as little user interaction as possible.&lt;/p&gt;

&lt;p&gt;To accomplish this, I’m going to make use of Emacs &lt;a href=&quot;https://www.emacswiki.org/emacs/BatchMode&quot;&gt;Batch Mode&lt;/a&gt;. Batch Mode will run Emacs in a non-interactive fashion; you feed it a file or an Elisp function to run, Emacs does its work and then exits without displaying a window. &lt;a href=&quot;https://github.com/marsmining/ox-twbs&quot;&gt;ox-twbs&lt;/a&gt; is an Emacs package I’ll be using to export my Org files to &lt;a href=&quot;http://getbootstrap.com/&quot;&gt;Bootstrap&lt;/a&gt;-themed HTML.&lt;/p&gt;

&lt;p&gt;The project I want to set up will be a couple of files that will act as a log of the things I have accomplished each week, goals for the next week and any associated notes or links I’d like to record. I’m going to create a directory for this project at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/org/log&lt;/code&gt; and create a couple of files: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.org&lt;/code&gt; will just contain a link to our second file, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2017.org&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2017.org&lt;/code&gt; will contain a descending-order list of the weeks of the year with associated notes using the following structure:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* Week 11 (March 13 2017)
** Recap
** Next Week
* Week 10 (March 6 2017)
** Recap
** Next Week
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, Org mode will create a full table of contents for the page, complete with the headlines being numbered. I’d like to avoid this: I only want to see up to the second level headlines in the table of contents and nothing below. Additionally, I don’t want the headlines to be numbered.&lt;/p&gt;

&lt;p&gt;Thankfully, I can easily specify all of these settings in one place by defining a &lt;strong&gt;project&lt;/strong&gt; in Org mode. By defining a project, we can easily generate HTML for our project with one command: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(org-publish-project &quot;PROJECT_NAME&quot;)&lt;/code&gt;. A variable called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org-publish-project-alist&lt;/code&gt; is used to define any number of Org projects one may have.&lt;/p&gt;

&lt;p&gt;The first thing I want to do is create a new Elisp file that will be used to import needed packages, define any required variables, and run the necessary function to build the site. Since I use Spacemacs (which has a fairly high amount of modules to load), the only modules I want to load are the bare minimum required to get Org running so Emacs can do its business. Inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.emacs.d/&lt;/code&gt;, I create a new file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org-export.el&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;org&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;ox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;ox-publish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user-full-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Dale Karp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user-mail-address&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;dale@dale.io&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-publish-project-alist&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;my_log&quot;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:base-directory&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;~/org/log/&quot;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:publishing-directory&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;~/projects/site/log&quot;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:publishing-function&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;org-twbs-publish-to-html&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:section-numbers&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;:table-of-contents&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org-publish-project&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;my_log&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First, I import some packages and set some variable such as who the author will be (me!). Next, the Org project gets defined within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org-publish-project-alist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I define a single project called “my_log” with some options. Some of these are self-explanatory: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:base-directory&lt;/code&gt; tells Org where to look for the files - any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.org&lt;/code&gt; file in this folder will be processed. Since I’ll be publishing this to a subsection of my website, I’ve set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:publishing-directory&lt;/code&gt; to the right location. Because I’m using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ox-twbs&lt;/code&gt; to generate our HTML, I need to tell Org to use it when publishing instead of the built-in HTML exporter. Finally, I let Org know that I don’t want any sections to have numbers, and that I only want our table of contents to have links for level 2 headlines and above.&lt;/p&gt;

&lt;p&gt;Now that our publishing pipeline is ready, I need to set up the ‘automation’ part. I host my site on GitHub Pages, so all I need to do to build my site is to create a new Git commit in my site repository after publishing, and pushing that commit to GitHub. To do all of this, I’ll write a Shell script! Because I’ll be a systemd timer to run this script at a set interval once a week, I need to set up a few things like retrieving SSH keys for the session so I can push to GitHub without being prompted for a pssword.&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# load ssh keys from keychain for this session&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;keychain &lt;span class=&quot;nt&quot;&gt;--eval&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--quiet&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--noask&lt;/span&gt; id_rsa&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# call &amp;amp; run our exporter elisp script&lt;/span&gt;
emacs &lt;span class=&quot;nt&quot;&gt;--batch&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; ~/.emacs.d/orgexport.el

&lt;span class=&quot;c&quot;&gt;# change directory to our repo&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/projects/site

&lt;span class=&quot;c&quot;&gt;# commit latest changes&lt;/span&gt;
git commit &lt;span class=&quot;nt&quot;&gt;-am&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Log for: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# push commit to get built on gh pages&lt;/span&gt;
git push
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the script written, the last thing to do is to use a scheduler to run it every week. I’m using systemd’s timers to do this, but cron should work as well. I created two files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~./config/systemd/user&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mylog-org-export.service&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Unit]
&lt;span class=&quot;nv&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Exports Org project &lt;span class=&quot;s2&quot;&gt;&quot;My_Log&quot;&lt;/span&gt; and pushes Git to GH Pages

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Service]
&lt;span class=&quot;nv&quot;&gt;ExecStart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/home/dale/.bin/org_upload.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mylog-org-export.timer&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Unit]
&lt;span class=&quot;nv&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Run mylog-org-export.service every Monday at midnight.

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Timer]
&lt;span class=&quot;nv&quot;&gt;OnCalendar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;weekly
&lt;span class=&quot;nv&quot;&gt;Persistent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;mylog-org-export.service

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Install]
&lt;span class=&quot;nv&quot;&gt;WantedBy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;timers.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now I can test to make sure our timer works and once verified, enable it:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; start mylog-org-export.service
systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;mylog-org-export.timer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verify that the timer is active with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl --user list-timers&lt;/code&gt;, and we’re good to go!&lt;/p&gt;

&lt;p&gt;At this point, I have an automated Org publishing pipeline that will convert our Org files to HTML once a week and then push the new data to GitHub pages to built. This approach can be customized fairly easily to publish anything from project documentation to a personal blog. If you have any suggestions on how to improve this or have any alternative methods, please let me know!&lt;/p&gt;
</description>
        <pubDate>Sun, 12 Mar 2017 00:00:00 -0500</pubDate>
        <link>https://dale.io/blog/automated-org-publishing.html</link>
        <guid isPermaLink="true">https://dale.io/blog/automated-org-publishing.html</guid>
        
        <category>org</category>
        
        <category>emacs</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>A Rusty Venture&amp;#58; Writing a text adventure in Rust</title>
        <description>&lt;p&gt;After a couple of months of playing around with Rust, I’ve finished a project!
It’s a simple text adventure game in the vein of class text
adventure &lt;a href=&quot;https://en.wikipedia.org/wiki/Zork&quot;&gt;&lt;em&gt;Zork&lt;/em&gt;&lt;/a&gt; called &lt;em&gt;Adventure!&lt;/em&gt;. The
feature set isn’t as wide as Zork; there is no combat and movement &amp;amp; world
interaction is pretty simple. I was never really into text adventures myself,
but I though that it would make an interesting &amp;amp; fun first project with Rust.&lt;/p&gt;

&lt;h3 id=&quot;design&quot;&gt;Design&lt;/h3&gt;

&lt;p&gt;I wanted to write a game containing of a few rooms, with a few things to do in
each room. The feature set wouldn’t go past picking up objects, adding them to
an inventory, and using inventory objects with static objects in the world. I
didn’t want to involve combat on NPCs as I didn’t want to work on this project
for the long-term; it’s a toy project for learning a bit about how Rust works.&lt;/p&gt;

&lt;h3 id=&quot;changing-rooms&quot;&gt;Changing Rooms&lt;/h3&gt;

&lt;p&gt;My first design involved having &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Room&lt;/code&gt; structs that would contain a member
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connection: Connection&lt;/code&gt;. This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Connection&lt;/code&gt; struct would itself have 4 members:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;north&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;south&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;east&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;west&lt;/code&gt;. The value of these members was to be an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option&amp;lt;Box&amp;lt;Room&amp;gt;&amp;gt;&lt;/code&gt;. The main &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Game&lt;/code&gt; object that ran the whole show would have a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current_room&lt;/code&gt; reference that points to whatever instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Room&lt;/code&gt; the user was in.&lt;/p&gt;

&lt;p&gt;Unfortunately, this design gave me trouble with the borrow checker. I got many
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cannot moved out of borrowed context&lt;/code&gt; errors thrown at me. At the time, I
didn’t really fully understand how the borrow checker works - and honestly, I’m
pretty sure I still don’t understand fully. I decided to take a simpler
approach: I’d store &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current_room&lt;/code&gt; as an integer representing an index in the
vector of rooms. In Rust, the index of a vector is the type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usize&lt;/code&gt;, a
pointer-sized (therefore system-dependent) unsigned int. At first, I stored
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current_room&lt;/code&gt; as an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i32&lt;/code&gt; but this led to lots of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as usize&lt;/code&gt; casting all over
the place. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Connection&lt;/code&gt; objects would be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option&amp;lt;usize&amp;gt;&lt;/code&gt; and changing rooms
would be as simple as replacing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current_room&lt;/code&gt; with another &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usize&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;The downside of this approach is having to know each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Room&lt;/code&gt;’s index in the
vector ahead of time. I kept track of the room number while designing the game
‘map’ so it wasn’t a big deal in my particular situation. I thought being able
to ‘point’ to other &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Room&lt;/code&gt; directly with a reference would be simpler, but that
would bring its own problems with it. For example, this would bring about
circular references (eg: Room 1 is connected to Room B, but if we create Room 1
first, how do we define this relationship when creating the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Room&lt;/code&gt; object? My
solution: You wouldn’t, you’d connect the rooms afterwards).&lt;/p&gt;

&lt;h3 id=&quot;flags--actions&quot;&gt;Flags &amp;amp; Actions&lt;/h3&gt;

&lt;p&gt;My next set of problems came with dealing with state change in the game. I ended
up declaring a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashMap&amp;lt;&amp;amp;&apos;static str, bool&amp;gt;&lt;/code&gt; in a struct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Flags&lt;/code&gt; at the
top-level of the game that gets passed around to the different functions.
Originally, each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Room&lt;/code&gt; was going to have its own set of flags but I didn’t want
have to reach across rooms to check the state of something - especially if an
action in one room can have consequenes elsewhere.&lt;/p&gt;

&lt;p&gt;Dealing with the actions took the longest to figure out. I had an important
questions I needed to answer at this point: How can I define each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item&lt;/code&gt; or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Room&lt;/code&gt; to have different behaviour depending on the state of global flags? To
solve this, I used closures. For instance, here is how an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item&lt;/code&gt; is defined:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;is_grabbable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_grab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_grab&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on_use&lt;/code&gt; accept closures. Because our state is stored in a
global object, each room doesn’t really need to worry about what’s going on in
other rooms - they only need to know the state of the world through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Flag&lt;/code&gt;
objects they receive. This allows me to use closures to define certain
behaviour.&lt;/p&gt;

&lt;p&gt;I’m not exactly sure if this method is idiomatic Rust. I’ve been writing
primarily JavaScript for my day job for the past few years so I’m still in that
state of mind where functions are first class citizens that I should be taking
advtange of. I wasn’t really sure how else to define individual behaviour for
separate instances of the same type.&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;For instance, this is an example of how an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item&lt;/code&gt; is defined:&lt;/p&gt;

&lt;div class=&quot;language-rust highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shovel&quot;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.to_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;is_grabbable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_grab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The shovel looks as if it has never been used before; the layer of dust that falls off as you pick it up shows that it has been sitting on that table for a long time. You slip the shovel in your pocket.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.update_key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;pickedUpShovel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;on_use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;usize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// this sucks; checking if we are in the room before perfoming action&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current_room&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;glass door&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.get_key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;smashedDoor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;It takes a few swings before a couple of cracks appear in the glass. Wondering why such strong glass is needed for a greenhouse door, you continue to swing away until a loud crash and gust of fresh air announces the success of your swinging endeavours.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;.update_key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;smashedDoor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You seem to have already done a number on that poor door - maybe you should leave it alone?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nd&quot;&gt;println!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You aren&apos;t sure how to use the shovel with the {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… and that’s just &lt;strong&gt;one&lt;/strong&gt; item! Imagine a whole &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Room&lt;/code&gt;, with it’s own
behaviour and items! (Or see for yourself and
&lt;a href=&quot;https://github.com/obsoke/adventure/blob/master/src/levels.rs&quot;&gt;check out the source file with the levels defined&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Another issue is that this method leads to cases where certain objects that don’t use a specific
callback have empty closures, which makes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rustc&lt;/code&gt; complain about unused
variables. This isn’t a huge deal, but it can clutter up compiler messages which
is slightly annoying.&lt;/p&gt;

&lt;p&gt;Originally, I planned on serializing each room into data files instead of hard
coding them into Rust source code. This way, anyone can write their own text
adventure without knowing a line of Rust! As soon as I decided to use closures,
however, that task seemed like it would be much more difficult. How do you
serialize behaviour? The only method I can think of is via a scripting language,
and that was way out of scope for this project.&lt;/p&gt;

&lt;h3 id=&quot;other-random-notes&quot;&gt;Other random notes&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;It would be nice if there was a way to initialize a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashMap&lt;/code&gt; by passing a
series of key/values to its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new()&lt;/code&gt; function or via a literal. I’m using
a
&lt;a href=&quot;http://stackoverflow.com/questions/27582739/how-do-i-create-a-hashmap-literal&quot;&gt;macro I found on StackOverflow&lt;/a&gt; to
do the job right now but it would be neat if this was built into the standard
library.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;conclusion-i-like-it&quot;&gt;Conclusion: I like it.&lt;/h3&gt;

&lt;p&gt;In the process of writing this post, I’ve had to question a few of my design
choices and actually learned new stuff (the idea of changing the type of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;current_room&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i32&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usize&lt;/code&gt; happened due to this post)!&lt;/p&gt;

&lt;p&gt;The likelihood of me continuing to work on this project is low. Howevever, if I
were to make an ‘Adventure! 2.0’, I’d make the following changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Spice things up with Termion. I came
across &lt;a href=&quot;http://ticki.github.io/blog/making-terminal-applications-in-rust-with-termion/&quot;&gt;this great blog post&lt;/a&gt;
by the author of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;termion&lt;/code&gt; crate, ticki. Maybe making some item names show
up in Zelda’s “Important Noun” red, or having more of a persistant GUI on
screen such as the inventory.&lt;/li&gt;
  &lt;li&gt;Take advantage of more core Rust/Cargo tools, like rustdoc.&lt;/li&gt;
  &lt;li&gt;Tests! Testing is important. I worked on this project for a few hours a week over the span of a month so it wasn’t something at the top of my mind.&lt;/li&gt;
  &lt;li&gt;Figure out cross-compilation so I can build executables for Windows &amp;amp; MacOS from my Linux desktop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had fun working on Adventure. If you’d like to check it
out, &lt;a href=&quot;https://github.com/obsoke/adventure&quot;&gt;here is the GitHub repo&lt;/a&gt;. I’d like to
figure out cross-compilation soon to get some binaries up on on the GitHub page.
My next project will involve &lt;em&gt;gasp&lt;/em&gt; graphics! Until then…&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;As I write this, a few ideas come to mind (although I’m not sure if they actually work). Perhaps creating a trait that all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Room&lt;/code&gt;s/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Item&lt;/code&gt;s implement, and write a macro that creates a new struct with said trait with the individual behaviour defined within? Just a thought. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 07 Nov 2016 00:00:00 -0500</pubDate>
        <link>https://dale.io/blog/a-rust-venture.html</link>
        <guid isPermaLink="true">https://dale.io/blog/a-rust-venture.html</guid>
        
        <category>rust</category>
        
        <category>gamedev</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>A Boilerplate for WebGL Projects</title>
        <description>&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;2015/12/12: Added source map support&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Between &lt;a href=&quot;http://gruntjs.com/&quot;&gt;Grunt&lt;/a&gt;, &lt;a href=&quot;http://gulpjs.com/&quot;&gt;Gulp&lt;/a&gt;,
&lt;a href=&quot;https://webpack.github.io/&quot;&gt;Webpack&lt;/a&gt; and &lt;a href=&quot;http://broccolijs.com/&quot;&gt;Broccoli&lt;/a&gt;, it seems like a new
build tool/asset pipeline/module bundler/etc arrives in the land of JavaScript every few months.
While learning WebGL, I started to look into ways to make starting a new project and development a
bit easier. I’ve been using Webpack for work-related purposes over the past few months and I’ve
really grown to like its easy-to-read config files, async code splitting abilities and wide plugin
ecosystem. “Since it helped make my React-based development smooth as butter,” I thought to myself,
“perhaps using Webpack would help to make WebGL development go just as smoothly.”&lt;/p&gt;

&lt;p&gt;This post follows the steps and rationale used to build a Webpack-based boilerplate for WebGL. If
you just want to look at the code, you can
&lt;a href=&quot;https://github.com/obsoke/webgl-webpack-boilerplate&quot;&gt;grab the source here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h3&gt;

&lt;p&gt;For this build system, all you need to start with is Node.js + npm. We will use Webpack as our
module loader/build tool combo. Another invaluable tool in our arsenal will be
&lt;a href=&quot;http://babeljs.io/&quot;&gt;Babel&lt;/a&gt; library for allowing use of ES6+ features. This guide assumes you have
basic familiarity with JavaScript and using npm to install modules.&lt;/p&gt;

&lt;p&gt;We will start off by installing Webpack globally. I like doing this so I can just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webpack&lt;/code&gt; on
the command line from anywhere:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;npm &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; webpack&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Webpack is a tool used to bundle files into modules. It has a vast variety of plugins created by
both the Webpack team and community to allow modules to be created using both JavaScript and
non-JavaScript files. You can even use it in conjunction with tools like Grunt or Gulp! We will be
making use of Webpack to transpile our ES6 code to something modern browsers can read with Babel, a
plugin that allow us to write our GLSL shader code like you would for a desktop application, and
finally bundle all our code into a single (or multiple) JavaScript files.&lt;/p&gt;

&lt;p&gt;Let’s create a new directory called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webgl_project&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;webgl_project
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;webgl_project&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We will be saving a list of libraries and tools we need to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; so let’s create one first:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;npm init &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-y&lt;/code&gt; flag uses default values; we will edit these shortly. Personally, I’d rather edit
these fields in a text editor rather than input them into a prompt.&lt;/p&gt;

&lt;p&gt;Next, we will install our dependencies required for development, including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webpack&lt;/code&gt;: The webpack documentation recommends saving webpack as a local dev. dependency&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webpack-dev-server&lt;/code&gt;: Used to watch files &amp;amp; recompile on changes, servers files&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;babel-core&lt;/code&gt;: Compiler used to make our ES6 code usable in modern browsers&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;babel-preset-es2015&lt;/code&gt;: Since version 6, Babel comes with no settings out of the box. This is a preset to compile ES6.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;babel-loader&lt;/code&gt;: Webpack plugin to transpile JavaScript files before creating modules out of them&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;html-webpack-plugin&lt;/code&gt;: A plugin used to auto-generate a HTML file with all webpack modules included.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webpack-glsl-loader&lt;/code&gt;: Webpack plugins to load our shaders from files into strings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s install these modules all at once:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;npm &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;webpack webpack-dev-server babel-core babel-reset-es2015 babel-loader html-webpack-plugin webpack-glsl-loader &lt;span class=&quot;nt&quot;&gt;--save-dev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;At this point, I usually like to open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; and start making some edits. This is what I end up with:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;webgl-webpack-boilerplate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;private&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a boilerplate webpack project for getting started with WebGL.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;author&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Dale Karp &amp;lt;dale@dale.io&amp;gt; (http://dale.io)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;license&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;CC-BY-4.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;repository&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;git&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://github.com/obsoke/webgl-webpack-boilerplate&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;devDependencies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;babel-core&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^6.1.19&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;babel-loader&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^6.1.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;babel-preset-es2015&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^6.1.18&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;html-webpack-plugin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^1.7.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;webpack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^1.12.4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;webpack-dev-server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^1.12.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;webpack-glsl-loader&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;^1.0.1&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We’ll come back to this file to add some commands to use to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scripts&lt;/code&gt; key. For now, let’s hop
back to the terminal.&lt;/p&gt;

&lt;h3 id=&quot;project-structure&quot;&gt;Project Structure&lt;/h3&gt;

&lt;p&gt;I wanted the file structure for an intial project to be simple:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;c&quot;&gt;.
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;├── package.json #&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;lists dependencies &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;easy re-install
&lt;span class=&quot;go&quot;&gt;├── src
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;│   ├── index.html #&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;html to use as template &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;generated output html
&lt;span class=&quot;go&quot;&gt;│   ├── js
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;│   │   └── main.js #&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;entry point &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;our application
&lt;span class=&quot;go&quot;&gt;│   └── shaders
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;│       └── ... #&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;glsl files go here
&lt;span class=&quot;gp&quot;&gt;└── node_modules/ #&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;folder containing our dependencies&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This structure can be created with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkdir&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;touch&lt;/code&gt; commands.&lt;/p&gt;

&lt;p&gt;Now that we have a clear idea of what files are going to be a part of the project, let’s get a Git repository
going and set up a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;git init
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;touch&lt;/span&gt; .gitignore&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Open up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; up and enter the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;node_modules
dist&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Since the contents of these two folders are generated, we shouldn’t commit them to version control.&lt;/p&gt;

&lt;p&gt;With that out the way, let us continue by setting up Webpack.&lt;/p&gt;

&lt;h3 id=&quot;webpack-configuration&quot;&gt;Webpack Configuration&lt;/h3&gt;

&lt;p&gt;Webpack can be configured a few different ways: with its own configuration files, via the command line with flags,
or as a module in Gulp/Grunt. We’ll be using the config file route. Create a file in the root of your project
directory called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webpack.config.js&lt;/code&gt;. Input the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HtmlWebpackPlugin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;html-webpack-plugin&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ROOT_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ENTRY_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ROOT_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;src/js/main.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SRC_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ROOT_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JS_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ROOT_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;src/js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TEMPLATE_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ROOT_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;src/index.html&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SHADER_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ROOT_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;src/shaders&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;BUILD_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ROOT_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NODE_ENV&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;production&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ENTRY_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;WebGL Project Boilerplate&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TEMPLATE_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;inject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;BUILD_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bundle.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;JS_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SRC_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;loaders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;js$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JS_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;exclude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;node_modules|bower_components&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;babel&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;cacheDirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;presets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;es2015&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;glsl$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SHADER_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;webpack-glsl&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;devtool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;debug&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;eval-source-map&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;source-map&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s take a look at what’s going on here:&lt;/p&gt;

&lt;h4 id=&quot;file-header&quot;&gt;File header&lt;/h4&gt;
&lt;p&gt;Firstly, we import some modules such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;path&lt;/code&gt; and our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;html-webpack-plugin&lt;/code&gt;. We also define some
constants containing the absolute paths to the folders we wil keep various types of files in, along
with the entry and output paths.&lt;/p&gt;

&lt;p&gt;We also check for the presence of the environmental variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NODE_ENV&lt;/code&gt; to determine whether to
build production or development bundles.&lt;/p&gt;

&lt;h4 id=&quot;entry&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;entry&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;The JavaScript entry point of our application.&lt;/p&gt;

&lt;h4 id=&quot;plugins&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugins&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;html-webpack-plugin&lt;/code&gt; generates HTML files that already have appropriate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;link&lt;/code&gt;
tags to bundled JS and CSS bundles. We’ll make use of that plugin with a few options. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;title&lt;/code&gt; is the
value of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;title&lt;/code&gt; tag. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;template&lt;/code&gt; is a path to the HTML file we want to base our index.html off
of. Finally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inject&lt;/code&gt; allows us to control where our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script&lt;/code&gt; tags are being created. Valid values
are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt;. We will set up our HTML template after configuring Webpack.&lt;/p&gt;

&lt;h4 id=&quot;output&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;output&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Here we define where we want Webpack to place the modules it creates.&lt;/p&gt;

&lt;h4 id=&quot;resolve&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resolve&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resolve&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; key lets you tell Webpack which folders to search in when importing one file into another.
For example, imagine the following file structure:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;c&quot;&gt;.
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;├── js
│   ├── Component
│   │   └── Dude.js
│   ├── main.js
│   └── Utility
│       └── VectorUtils.js
└── shaders&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js/utility/VectorUtils.js&lt;/code&gt; look something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getDotProduct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// gets &amp;amp; returns dot product&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Without setting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resolve.root&lt;/code&gt; property in our Webpack settings, the way to include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VectorUtils.js&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dude.js&lt;/code&gt; would look something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getDotProduct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;../VectorUtils.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Dude&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// use getDotProduct somewhere in here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resolve.root&lt;/code&gt; to include our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/js&lt;/code&gt; path, we can treat that as a root directory that Webpack will search through to find other modules. This lets us write import paths like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getDotProduct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Utility/VectorUtils.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Dude&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// use getDotProduct somewhere in here&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Since we’ve also added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; as a root path, we’ll be able to include shaders just by writing something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boxShader&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Shaders/boxShader_v.glsl&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This makes importing files easy, no matter what directory you happen to be working in.&lt;/p&gt;

&lt;h4 id=&quot;module&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;module&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loader&lt;/code&gt; key on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;module&lt;/code&gt; tells Webpack which files to load into modules, and how to load them.
We’ve defined two loaders: one for JavaScript files, and one for our GLSL shaders. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt; is a
regular expression that will bundle the files that match it; obviously for a JavaScript loader, we
want Webpack to find modules ending with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.js&lt;/code&gt;. We don’t want Webpack to do anything with our
dependencies unless we explicitly import one, so we tell Webpack to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exclude&lt;/code&gt; them. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loader&lt;/code&gt; key
is the name of the Webpack plugin used to process JS files. Since we want to be able to write using
ES6 syntax, Babel will handle that responsibility. Because Babel 6 comes with no options out of the
box, we need to tell it to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;es2015&lt;/code&gt; presets package we installed earlier. Enabling directory
caching will give us faster compile times so of course we enable that.&lt;/p&gt;

&lt;p&gt;Our last loader is for our shader files, ending with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.glsl&lt;/code&gt;. Here, we simply tell Webpack to use
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webpack-glsl&lt;/code&gt; loader.&lt;/p&gt;

&lt;h4 id=&quot;debug&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Some loaders will perform optimizations when building bundles depending on whether the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;debug&lt;/code&gt; key
is set to true or false.&lt;/p&gt;

&lt;h4 id=&quot;devtool&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devtool&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;At the moment, this tells Webpack which style of source maps to use. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source-map&lt;/code&gt; is recommended for
production use only, so we’ll use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval-source-map&lt;/code&gt; which is faster and produces cache-able source
maps.&lt;/p&gt;

&lt;p&gt;With that, our configuration of Webpack is complete. Not too bad, eh?&lt;/p&gt;

&lt;p&gt;Let’s re-open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; and add some commands to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scripts&lt;/code&gt; that will make interacting with
webpack a bit easier:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;scripts&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;NODE_ENV=production webpack --progress --colors&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;webpack --progress --colors --watch&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;dev-server&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;webpack-dev-server --progress --colors --inline --hot&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Webpack will check for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webpack.config.js&lt;/code&gt; and use it if found. I’m using flags to show build
progress and to give the output a bit more colour. Any key added to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scripts&lt;/code&gt; object can be used
by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run &amp;lt;keyname&amp;gt;&lt;/code&gt;. This gives us three easily accessible commands:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NODE_ENV=production npm run build&lt;/code&gt;: Builds our project into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dist/&lt;/code&gt;. Uses a flag to tell Webpack we want loaders to build production-mode modules.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run watch&lt;/code&gt;: Builds our project and watches files for changes, re-builds on change.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm run dev-server&lt;/code&gt;: Builds our project and watches files for changes, also serves files from a web server. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--inline --hot&lt;/code&gt; flags enable Hot Module replacement, which will update your page without any user input. You can read more about HMR in &lt;a href=&quot;http://webpack.github.io/docs/webpack-dev-server.html&quot;&gt;webpack-dev-server’s documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we have one thing left to do, and that is to create our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.html&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dist&lt;/code&gt;. This is what the contents
look like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;en&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;http-equiv=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Content-type&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/html; charset=utf-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;{%= o.htmlWebpackPlugin.options.title %}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;canvas&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;canvas&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That weird value used in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;title&lt;/code&gt; tag allows Webpack to change the page’s title depending on the
value of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;title&lt;/code&gt; key passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;html-webpack-plugin&lt;/code&gt;. As you can see, no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script&lt;/code&gt; tags are
needed - Webpack will handle that for us.&lt;/p&gt;

&lt;p&gt;And with that, the boilerplate is complete. “But Dale,” you exclaim, “I don’t see the point of this.
You made a simple Webpack config, so what?”&lt;/p&gt;

&lt;h3 id=&quot;motivations&quot;&gt;Motivations&lt;/h3&gt;

&lt;p&gt;My main motivations behind this came from my own experiences trying to learn WebGL. I’ve noticed
that many WebGL tutorials will demonstrate shader usage in WebGL in one of two ways:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Write a JavaScript string containing the shader code.&lt;/li&gt;
  &lt;li&gt;Have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script&lt;/code&gt; element of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-ver-shader&lt;/code&gt; and grab the element’s content from JavaScript.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Personally, I don’t like either of these solutions. The first one is just ugly, unreadable and
difficult to maintain yet most of the WebGL resources I see introduce shaders using this
method. The second is slightly better, but I prefer to keep shaders in their own files, where I can
use an editor with syntax highlighting to make readability a bit easier.&lt;/p&gt;

&lt;p&gt;I completely understand why tutorial writers do this. WebGL is complex, and wrapping your head
around everything needed to render a simple triangle in shader-based GL can be a lot to take in at
once. Once you get your head around those concepts, though, then what? What’s the best way to deal
with shaders moving forward as a project scales? I’m not claiming this boilerplate is anywhere close
to the best, but for me it works. Hopefully it does for you too (and if it doesn’t, please open an
issue/PR on the &lt;a href=&quot;https://github.com/obsoke/webpack-webgl-boilerplate&quot;&gt;GitHub repo&lt;/a&gt; and let me know).&lt;/p&gt;

&lt;h3 id=&quot;mini-example-hello-triangle&quot;&gt;Mini-example: Hello Triangle&lt;/h3&gt;

&lt;p&gt;Let’s go through a short example of how one would potentially use this boilerplate to easily load
GLSL shaders. Imagine we have two shaders in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/shaders&lt;/code&gt; directory, called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box_vert.glsl&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box_frag.glsl&lt;/code&gt; containing our vertex and fragment shader, respectively. No need for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt;
tags or multi-line strings! Just import it when you need it, where you need it.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// import our shaders and store them variables&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boxVertShaderSource&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;shaders/box_vert.glsl&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boxFragShaderSource&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;shaders/box_frag.glsl&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;canvas&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;canvas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;experimental-webgl&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// time to create our shader program with a handy function!&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// it expects the gl context and strings containing shaders.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;program&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createProgramFromGLSL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boxVertShaderSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;boxFragShaderSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;thats-all&quot;&gt;That’s all!&lt;/h3&gt;

&lt;p&gt;I hope you found this useful in some way. If you have any suggestions on how to improve the
boilerplate, please open an issue on the
&lt;a href=&quot;https://github.com/obsoke/webpack-webgl-boilerplate&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Thu, 10 Dec 2015 12:00:00 -0500</pubDate>
        <link>https://dale.io/blog/webgl-build-chain.html</link>
        <guid isPermaLink="true">https://dale.io/blog/webgl-build-chain.html</guid>
        
        <category>webgl</category>
        
        <category>webdev</category>
        
        <category>webpack</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>dale.io v4</title>
        <description>&lt;p&gt;I recently decided that my personal site needed a tune up. No longer happy with the current design, I decided to throw it away completely and to start from scratch. Here are a few things I thought about during the process of re-writing the website.&lt;/p&gt;

&lt;h3 id=&quot;choosing-a-backend&quot;&gt;Choosing a backend&lt;/h3&gt;
&lt;p&gt;Right off the bat, I knew that I wanted to continue using a static site generator for my homepage. Tools like WordPress and Ghost are interesting but for my use case I found both to be overkill. After taking a look at some of the most popular static site generators&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; around and playing around with them, I had a better idea of the current tool landscape at the time.&lt;/p&gt;

&lt;p&gt;There are a bunch of static site generators these days written in a variety of languages. I took a look at a few JavaScript-based ones, such as &lt;a href=&quot;https://hexo.io/&quot;&gt;Hexo&lt;/a&gt; and &lt;a href=&quot;http://www.metalsmith.io/&quot;&gt;Metalsmith&lt;/a&gt; - both on opposite sides of the feature list spectrum. Metalsmith is completely barebones to the point where all functionality is added via plugins. This is a pretty neat idea but I was looking for something that was more balanced between features and do-it-yourself mentality. When I was initially researching static site generators, Metalsmith had a lot of issues with plugin version rot as well. The idea of everything being a plugin is pretty neat - as long as these individual plugins are maintained! On the other end of the feature spectrum, Hexo reminds me a lot of Jekyll but written in JavaScript and more of an emphasis on blogs. This wasn’t enough to pull me away from Jekyll, a tool I already knew.&lt;/p&gt;

&lt;p&gt;On the Ruby end, I took a look at &lt;a href=&quot;https://middlemanapp.com/&quot;&gt;Middleman&lt;/a&gt; and &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;. Middleman is a great competitor for Jekyll with some neat features. It allows for incremental building of your site, a feature that Jekyll will be lacking until its v3 release. I have not had much of an issue with build times with Jekyll but I can see how a huge site with thousands of pages would not scale well without incremental builds. Middleman also offers more in the way of a default template and such. However, in the end I stuck with Jekyll. Recent additions to Jekyll such as &lt;a href=&quot;http://jekyllrb.com/docs/collections/&quot;&gt;collections&lt;/a&gt; make building non-blog and hybrid websites with Jekyll much easier.&lt;/p&gt;

&lt;h3 id=&quot;choosing-a-colour-palette&quot;&gt;Choosing a colour palette&lt;/h3&gt;
&lt;p&gt;I am not a designer - I think the previous designs of my site show as much. As much as I wish I did, I just don’t have the eye for colour. Working with designers in the past always blew my mind as to how easy it came to them. I know I could take the time to learn colour theory (and perhaps I will someday) but at the time I was more focused on redesigning my site quickly, not leisurely learning something new. This made the simple task of choosing a colour palette a long and tedious process. There are a few tools available to help one come up with a colour palette, such as &lt;a href=&quot;http://paletton.com/&quot;&gt;Paletton&lt;/a&gt; or &lt;a href=&quot;https://color.adobe.com/create/color-wheel/&quot;&gt;Adobe Color CC&lt;/a&gt;, formerly Kuler. After fiddling for them for a few days on and off and having no success, I decided just to choose a colour I liked: blue. Once I had a colour chosen for the header, I was able to build the rest of the site off of that.&lt;/p&gt;

&lt;p&gt;While I’m pleased with how the header turned out, I still feel as if the rest of the site can possibly use a splash of colour here or there just to make things a bit more appealing. I couldn’t really see any place to fit these accent colours in a way that felt natural. This will probably be something that will to be iterated on over time.&lt;/p&gt;

&lt;h3 id=&quot;the-holy-grail-that-is-flexbox&quot;&gt;The Holy Grail that is Flexbox&lt;/h3&gt;
&lt;p&gt;Flexbox is the best thing to happen to CSS. I’ll scream it from the mountain tops if needed because it’s true. As long as the only browsers your site needs to support are IE11+ or an evergreen browser, you can (mostly&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;) say goodbye to hacky CSS rules to position elements on a web page.&lt;/p&gt;

&lt;p&gt;The great thing about Flexbox is that it’s flexible (yet another surprise!) and will adjust its size across different screen sizes if the developer desires it. For example, the page header makes use of flexbox to make sure it looks great on both large and small screens. All I need to do to get my header to scale the way I wish is use the following CSS rules on the wrapper for my header block:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.nav-wrapper&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;justify-content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;align-items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This sets the wrapper rendering box style to flexbox and centers all the elements along both axis. When the screen width is below a certain size, we can use the following rules to change the direction of the main axis from a row to a reversed column so each header element has room to breath and appears in the proper order:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;only&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;600px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;.nav-wrapper&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;flex-direction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;column-reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;align-items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stretch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I’m using a few more rules to align individual items, but that is the basics of it. Flexbox has enabled me to re-arrange the entire site with just a few CSS rules and I think that is awesome. I’m using it for any part of my page that requires even a tiny bit of element positioning and it’s been very easy to both learn and use. Offloading a lot of the grunt work to the browser while providing a fewer set of CSS rules was definitely a smart move, and I’m excited to see what further revisions to the spec bring.&lt;/p&gt;

&lt;h3 id=&quot;consistency-between-old-and-new&quot;&gt;Consistency between old and new&lt;/h3&gt;
&lt;p&gt;In the redesign, I decided to make better use of header tags to denote subheading rather than bolded text. Unfortunately, a few of my older blog posts made liberal use of the old and bold way. I took this opportunity to flex my bash and regex muscles and see if I can come up with an elegant way to fix this in one swing.&lt;/p&gt;

&lt;p&gt;My first step was to construct a regular expression that would find all the old headers. The old headers took the form of bold text which, in Markdown, meant the text was surrounded by two asterisks on each end. The header would be the only string of text on the line. With this information, I came up with the following regular expression and used it to find all headers in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_posts&lt;/code&gt; folder:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;git &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^\*\*.*\*\*$&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This regular expression looks for any length of characters in between two literal asterisks that bookend the entire line. After testing that the regex worked, I used a combination of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; commands to do a massive search and replace with the following command:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;find _posts &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/^\*\*\(.*\)\*\*$/\#\#\# \1/g&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The above command looks for files in the _post directory, and for each file runs a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; command asking it to edit files in-place without a backup&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. The regular expression now creates a group around the header text so we can use it in the replace with the proper symbol denoting an h3 tag: three literal pound characters. Now all blog posts with headers will conform to the new style.&lt;/p&gt;

&lt;h3 id=&quot;design--organization-choices&quot;&gt;Design &amp;amp; organization choices&lt;/h3&gt;
&lt;p&gt;Aside from choosing site colours, I spent the most time thinking about how I wanted to layout my website. My previous v3 design was bland and didn’t make the best use of available space. I spent a lot of time looking at &lt;a href=&quot;https://github.com/jekyll/jekyll/wiki/Sites&quot;&gt;other Jekyll blogs&lt;/a&gt; for some inspiration but I found many of them to be overly busy or overly minimalistic. I would draw layout after layout on paper until I came to the one you see now. Moving the persistent navigation block from the side to the top allows me to take advantage of all the below space: this comes in handy when scaling the site to work on multiple resolutions.&lt;/p&gt;

&lt;p&gt;Since the beginning of 2015, I’ve been writing reviews on the games I have finished for fun. After deciding to add these reviews to the site. As of the launch of the redesign, only one of the eight reviews I have written are published but I’ll be editing the others and getting them online shortly. Right now, they are a separate entity from the other blog posts and I’m not sure if this was the best idea. This home page is a place for me to talk about what I love doing. For the past few years, this has solely been about programming. I’d like to expand that to writing about other subjects but dividing posts up into ‘blogs’ and ‘reviews’ may limit myself in the future. I could (and probably will) just treat everything as a blog and use tags or categories to group the related info. Design choices like this are what I spent the most time on during this redesign. Implementing the ideas I come up with are no problem but deciding whether I’m making the right choice on certain decisions is an area where working on a team definitely benefits.&lt;/p&gt;

&lt;p&gt;There are a bunch of other small but useful additions I’ve made. If you haven’t noticed, I tend to go off on tangent mid-paragraph. Making use of footnotes allows me to do this without breaking up the flow of content, and the Kramdown markdown renderer used by Jekykll makes usage of footnotes very easy. Some posts can have a header image, such as this one. If you’re reading this on a small device, you may not see it - I’m currently thinking of a good way to display the header image without making all of the above-the-fold content on a mobile device nothing but headers. Most of the small additions are there to make writing content easier for me and for said content to display correctly, no matter the screen scale.&lt;/p&gt;

&lt;h3 id=&quot;in-the-end&quot;&gt;In the end&lt;/h3&gt;
&lt;p&gt;I’m pretty happy with the layout I ended up with. I find easier on the eyes than previous designs. Standing here with the project finished, I already have a list of things I’m no longer happy with and will work on for the next iteration. Personal projects like home page redesigns give me an opportunity to experiment and play but if I don’t limit myself and consider the project ‘finished’, I’ll never release it. Do you have any suggestions about the design? Love it? Hate it? Let me know in the comments!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;According to &lt;a href=&quot;https://www.staticgen.com/&quot;&gt;StaticGen&lt;/a&gt; which ranks generators based off of GitHub stars and forks. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;While much better than the old way of doing things, Flexbox itself is not perfect. Check out &lt;a href=&quot;https://github.com/philipwalton/flexbugs&quot;&gt;Flexbugs&lt;/a&gt; for more info. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Not recommended. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 31 May 2015 21:30:00 -0400</pubDate>
        <link>https://dale.io/blog/daleiov4.html</link>
        <guid isPermaLink="true">https://dale.io/blog/daleiov4.html</guid>
        
        <category>projects</category>
        
        <category>postmortem</category>
        
        <category>webdev</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Jump Around</title>
        <description>&lt;p&gt;A few months ago, &lt;a href=&quot;http://dale.io/2014/11/21/playtime-with-phaser.html&quot;&gt;I wrote a blog post&lt;/a&gt; about my experience playing around with the
Phaser game engine. I ended up making a short 2D platformer game
called &lt;a href=&quot;http://lab.dale.io/games/jumparound/&quot;&gt;Jump Around&lt;/a&gt;. I’ve uploaded
&lt;a href=&quot;https://github.com/obsoke/jumparound&quot;&gt;the source onto GitHub&lt;/a&gt; for
those who are interested in taking a peek.  It was a great experience
in which I learnt quite a bit, so without further ado…&lt;/p&gt;

&lt;h3 id=&quot;initial-design--scope&quot;&gt;Initial Design &amp;amp; Scope&lt;/h3&gt;

&lt;p&gt;My initial goals for the project were pretty simple:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Make a short 2D platformer game.&lt;/li&gt;
  &lt;li&gt;Each level would fit on the screen; no camera work needed.&lt;/li&gt;
  &lt;li&gt;Don’t focus too much on making the ‘cleanest’ code possible on this
project. This is more getting a feel for game development again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wanted to keep things pretty simple, as this project was meant to
not only evaluate Phaser for future projects but also getting my feet
wet with some simple game design. It seems almost like a rite of
passage nowadays for game developers to make a 2D platformer, so I decided to go
for that. Jump Around is inspired by platformers such as Super Meat
Boy, where the emphasis is on pixel-perfect platforming as quickly as
possible. The smaller levels in Super Meat Boy that would fit within
the initial camera frame were always pretty interesting to me. The
small characters moving quickly around an environment in which danger
is visible everywhere made for a strange mix of emotions. Upon
entering a level, I’d both feel terror at the level that I was to get
through, and excitement at the challenge ahead.&lt;/p&gt;

&lt;p&gt;I originally scoped for around 6 levels, but I cut it down to 3 as I
came to a realization: good level design is hard work! Once the game
mechanics were implemented, the majority of my time was spent on
figuring out how to be clever with level design. This wasn’t my goal
for the project so I decided to cut the level count in half so I could
move on to another project sooner. Aside from that, I feel like I did
a good job with my initial design and didn’t end up with much feature
creep. The only feature I ended up missing was using “Jump Around” by
House of Pain as the obvious background music choice. I planned on
distributing the source code for this and I’m pretty sure I would not
have the rights to distribute that song. This is an issue I also had to look
into regarding art I used (gasp, could this be… a segue?!).&lt;/p&gt;

&lt;h3 id=&quot;art-is-hard&quot;&gt;Art is hard&lt;/h3&gt;

&lt;p&gt;Although I have tried many times, I just can’t draw very well. This
can be a problem when you are a lone programmer working on a video
game. Thankfully, there are tons of free art resources online. One of
these is the great website &lt;a href=&quot;http://opengameart.org/&quot;&gt;Open Game Art&lt;/a&gt;. I
ended up purchasing a donation-ware art pack from an incredibly
talented &amp;amp; generous artist named &lt;a href=&quot;http://kenney.nl/&quot;&gt;Kenney&lt;/a&gt;. I’ve
seen him post on &lt;a href=&quot;http://www.reddit.com/r/gamedev&quot;&gt;/r/gamedev&lt;/a&gt; before,
offering free art packs under liberal license terms for people like me
who aren’t so artistically inclined. While this was a decent solution
to not being able to produce art myself, in retrospect I think I
should have kept it simple and gone with a more abstract art style.&lt;/p&gt;

&lt;p&gt;As said before, I eventually wanted to release the source of Jump
Around. However, I wasn’t too sure about the license to redistribute
the assets. Thankfully, Kenney includes a LICENSE.TXT in his zip of
art which helpfully states that the assets are released under &lt;a href=&quot;http://creativecommons.org/publicdomain/zero/1.0/&quot;&gt;the liberal CC0&lt;/a&gt;
license. As long as I attribute him, I should be okay to redistribute
the art I used and modified for my purposes.&lt;/p&gt;

&lt;p&gt;Most of the audio I use is also from Kenney’s donation pack, but the
incredibly &lt;del&gt;cheezy&lt;/del&gt; awesome end of level noise that plays was a clip I found off
of &lt;a href=&quot;http://www.freesound.org/people/Tuudurt/sounds/258142/&quot;&gt;freesound.org&lt;/a&gt;. This is another great resource for developers just
looking for simple or placeholder sounds under a variety of
licenses. Thankfully, this asset is also CC0 so the game can be fully
redistributed with all assets intact.&lt;/p&gt;

&lt;h3 id=&quot;resolution-is-confusing&quot;&gt;Resolution is confusing&lt;/h3&gt;

&lt;p&gt;Another issue I ran into was answering the question “What resolution
am I targeting with this game?” I was making this game for web
browsers running on a desktop. I probably should have consulted the
great &lt;a href=&quot;http://store.steampowered.com/hwsurvey&quot;&gt;Valve Hardware Survey&lt;/a&gt; to get a sense of what kind of resolutions
people were playing at. While 1920x1080 is the most popular
resolution, it only had 33.48% of user share as of this blog post. In
second place was 1366x768 with 26.80%. I ended up hardcoding my game’s
resolution at a very strange and non-standard 1050x714. I did this
because that was the size of my level in tiles (50x24 tiles, as each
tile was 21x21). In retrospect, this was a dumb idea. While I haven’t
exactly alienated either of the two largest resolution groups
(according to Valve), it doesn’t scale up or down at all. I probably
should have spent more time on making sure the scaling worked; at one
point in development, I found myself even looking at options to use
the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode&quot;&gt;fullscreen API&lt;/a&gt;. In the end, I decided to push that learning
exercise to my next project.&lt;/p&gt;

&lt;p&gt;Another consideration was “Could this game work on a mobile device?”
Due to the decisions I made based on the art and not bothering to
scale anything, it wouldn’t be a great experience. However,
mechanically, it could work. I ended up adding a toggle to cause the
player to continuously jump, and I noticed the game was actually kind
of fun when I left it on. It felt more like “Pogo Around” than “Jump
Around” but it was still fun. I could have left that setting on for
the mobile version and had the user touch either side of the screen to
simulate the left/right cursor movements. Using two fingers instead of
one could make the player run… or… pogo-run… rather than
pogo-walk. In the future, I may revisit this project and try to add
that in, but for now it was out of scope of what I wanted to
accomplish.&lt;/p&gt;

&lt;p&gt;If you’re interested in trying this ‘pogo’ mode for yourself, just hit
the F key while playing the game. It adds another layer of
challenge… think of it as hard mode!&lt;/p&gt;

&lt;h3 id=&quot;architecture--tools&quot;&gt;Architecture &amp;amp; Tools&lt;/h3&gt;

&lt;p&gt;At first, I wasn’t really sure how to structure this project. I’ve
done game development before but never in JavaScript. I found a very
useful blog post called &lt;a href=&quot;http://invrse.co/build-phaser-with-browserify/&quot;&gt;Building your Phaser Projects with Browserify&lt;/a&gt;
that was helpful in getting the file structure of a game in
place.&lt;/p&gt;

&lt;p&gt;Since the majority of my game objects were simple, I was able to make
to do with simple objects that didn’t follow any particular
programming pattern. Some variables, such as current level and overall
game time, were kept in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;game&lt;/code&gt; object, while each state kind of
dealt with it’s own area. After the assets are preloaded, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;menu&lt;/code&gt;
state is spun up and waits for user input. After that, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;level&lt;/code&gt;
state is entered. The level state checks what level it should be
loading via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;game&lt;/code&gt; object and starts to create the needed
platforms and tiles.&lt;/p&gt;

&lt;p&gt;The levels themselves were created using the fantastic &lt;a href=&quot;http://www.mapeditor.org/&quot;&gt;Tiled&lt;/a&gt; map
editor. One neat feature of Tiled that I liked was creating
Objects on the map that can store any properties you wish. I ended up
doing this to store quite a bit of data in the level itself, such as
player spawn position, level key position, and starting positions of
moving platforms, as well as their speed, distance and initial
direction. This allows me to use a single state for each level with
little to no code change needed to properly load each level. I feel
like I do cheat a bit by passing the player object through each level
state to retain some data like how many times the player has died, but
it seemed like the simplest solution so I went with it.&lt;/p&gt;

&lt;p&gt;Phaser is a pretty nice framework but I ran into some
issues. Currently only a single tile layer from Tiled can be marked as
a collision layer. When Phaser moved from version 1 to 2, it lost some
of it’s advanced camera capabilities such as the ability to zoom; I
believe the current camera can only pan by default. Neither of these
are dealbreakers, but they would be nice to have features. I still
think Phaser is one of the best JS engines you can use right now. It
has a decent sized community and there are always people on the IRC
channel willing to help (such as myself!) I’ve read that Phaser 3 may
be getting a ES6 makeover which makes me very excited for the future
of the engine.&lt;/p&gt;

&lt;p&gt;However…&lt;/p&gt;

&lt;h3 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h3&gt;

&lt;p&gt;I had a blast making Jump Around, and I’m glad I finished the
project. I learnt quite a bit about a variety of topics. I now have a
huge amount of respect for great level designers, as I spent quite a
bit of time thinking of how to make each level progressively more
interesting. I’m not sure if I’ve succeeded but I tried to do
something new in each level. I also learnt a bit about 2D animation to
animate the player, audio codecs &amp;amp; conversion to get the sound effects
working, and some basic game design as a result of the project.&lt;/p&gt;

&lt;p&gt;One area that I didn’t get to focus on as much as I would have liked was the game
programming itself. I think this is because I used an engine which did
a lot of it for me. Because of this, my next project will most likely
not use an engine at all. I don’t want to do everything myself (not
yet at least) so I’ll probably use a helper library to handle things
like asset loading, input reading and window creation (if targeting
desktops rather than the web). I plan on reading some of the excellent
&lt;a href=&quot;http://gameprogrammingpatterns.com/&quot;&gt;Game Programming Patterns&lt;/a&gt; book to get a better feel on how game
architecture works and how things fit together.&lt;/p&gt;

&lt;p&gt;So that’s Jump Around! Feel free to &lt;a href=&quot;http://lab.dale.io/games/jumparound/&quot;&gt;try the game out&lt;/a&gt; and &lt;a href=&quot;https://github.com/obsoke/jumparound&quot;&gt;check out the
source&lt;/a&gt; if you’re interested.&lt;/p&gt;
</description>
        <pubDate>Fri, 27 Feb 2015 18:30:00 -0500</pubDate>
        <link>https://dale.io/blog/jump-around.html</link>
        <guid isPermaLink="true">https://dale.io/blog/jump-around.html</guid>
        
        <category>projects</category>
        
        <category>open-source</category>
        
        <category>postmortem</category>
        
        <category>gamedev</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Giffy&amp;#58; A Postmortem</title>
        <description>&lt;p&gt;I’ve recently finished up a small side project that I started quite a
while ago called &lt;a href=&quot;http://giffy.dale.io&quot;&gt;Giffy&lt;/a&gt;. It wasn’t a particularly large or complex
project but the motivation to continue working on it diminished
shortly after starting. Now that the project is done, I wanted to
write a post discussing some of the challenges I faced and thoughts I
had.&lt;/p&gt;

&lt;h3 id=&quot;on-side-projects&quot;&gt;On Side Projects&lt;/h3&gt;

&lt;p&gt;Working on a side project is a great way for any developer to learn
about a new technology, further develop an existing skill or just get
some creative juices flowing. However, I’ve found it much easier to
start a project than to actually finish one. There can be many reasons
why finishing a side project can be hard. For Giffy, those reasons
were feature creep, scope and changing personal thoughts on images on
the web. While side projects can be a great place to experiment, too
much experimenting led to a feature list that was much too long. This
can be mentally draining when done close to the beginning of a
project. I wouldn’t recommend it. I’ve learned a lot about looking at
a feature and breaking it down into smaller features. Working in
smaller chunks makes it easier for me to focus on the current
objective and to experience the thrill of seeing a feature come to
life more frequently.&lt;/p&gt;

&lt;h3 id=&quot;what-is-giffy&quot;&gt;What is Giffy?&lt;/h3&gt;

&lt;p&gt;Giffy is simply an image hosting service for gifs. You can tag gifs
that has been uploaded, and find similarly tagged gifs. If you don’t
have any gifs to upload, you can create one in the browser using your
webcam. Once you’ve created your gif, you have the option to upload it
directly to Giffy.&lt;/p&gt;

&lt;p&gt;Some features, such as adding &amp;amp; deleting tags, require an account. One
of the features I ended up cutting was a permissions system that would
let the admin define roles and associated permitted &amp;amp; forbidden
actions (eg: upload a gif, delete a tag). Bits and pieces of the
permissions system exist in the code, but it was never finished.&lt;/p&gt;

&lt;p&gt;There were a bunch of social-networky features I cut from the feature
list. I had to step back and remember what my goals were for this
project:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Learn more about Angular&lt;/li&gt;
  &lt;li&gt;Learn how to upload images directly to an Amazon S3 bucket from the
browser via CORS&lt;/li&gt;
  &lt;li&gt;Learn how to create a gif from a webcam using WebRTC and upload
that gif directly to S3&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here on the other side of the project, I feel that I’ve completed
these goals. Learning not only how to cut unnecessary fat from the
feature list, but also how to divide my main tasks into smaller, more
manageable sub tasks was important to keep me going towards the finish
line. Focusing on the important features to cut can be hard in a
project that exists solely for learning and experimenting, but for
some people it may be necessary if that project is ever going to see
the light of day.&lt;/p&gt;

&lt;h3 id=&quot;the-backend&quot;&gt;The Backend&lt;/h3&gt;

&lt;p&gt;There is not a whole lot of magic happening on the backend. All it is
really doing is serving HTTP requests and fetching data from the
database. I’m using the &lt;a href=&quot;http://bookshelfjs.org/&quot;&gt;Bookshelf ORM&lt;/a&gt; to handle all things database,
backed by Postgres. It’s a pretty nice ORM that makes mapping models
to database tables incredibly easy. While I found that it lacked some
basic features such as limiting the amount of rows returned, it’s
possible to use the underlying &lt;a href=&quot;http://knexjs.org/&quot;&gt;Knex.js&lt;/a&gt; library to perform raw SQL
queries. Other libraries I use are bcrypt for password salting,
shortid to generate a unique file name for gifs and Amazon’s AWS
library for Node.js&lt;/p&gt;

&lt;p&gt;In terms of design, I make heavy use of promises instead of callbacks
in my API code. Promises are very easy to use and, in my opinion, make
ones code much more readable (goodbye, callback hell).&lt;/p&gt;

&lt;p&gt;One design choice I regret is choosing session-based authentication
over token-based. The way I originally designed the application was a
standalone API that would be able to handle requests by clients on any
kind of device. I ended up with more of a Rails-type monolithic app so
cookie-based sessions were pretty easy to implement. From my limited
understanding, cookie-based authentication doesn’t work very well on
mobile devices. A much simpler solution would be to include a token
that identifies the user with each request. Ah well, lesson learned
for my next side project!&lt;/p&gt;

&lt;h3 id=&quot;angular&quot;&gt;Angular&lt;/h3&gt;

&lt;p&gt;It really bothers me that I need to use a &lt;a href=&quot;https://github.com/angular-ui/ui-router&quot;&gt;plugin&lt;/a&gt; for a framework just
to do something as simple as nested views. I feel like a framework
that focuses on building single-page apps like Angular should have
this built in. Perhaps I’m being nit-picky but it’s a design choice I
find baffling. Also, the way Angular differentiates services,
factories and providers is a little strange and seems arbitrary.&lt;/p&gt;

&lt;p&gt;Aside from those points, using Angular has been mostly painless and
made developing the web app portion of Giffy easy. I don’t think I was
pushing the limits of the framework or anything. Most of the
challenges I faced came with getting sessions to work between Angular
and Express, or routing static assets; nothing specific to Angular
compared to other single-page app frameworks.&lt;/p&gt;

&lt;p&gt;In the end, I was mostly pleased with Angular, and would consider it
in future projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EDIT (2015-01-17):&lt;/strong&gt; After some consideration, I’m not too sure if I
  would actually use Angular for another personal project. I’m not a
  huge fan of how Angular 2 is looking.&lt;/p&gt;

&lt;h3 id=&quot;direct-to-s3-upload&quot;&gt;Direct to S3 Upload&lt;/h3&gt;

&lt;p&gt;One feature I really wanted in Giffy was the ability to upload a file
directly to an Amazon S3 bucket directly from the browser. I wanted
the API behind Giffy to solely handle requests and to fetch the
appropriate data from the database. I found &lt;a href=&quot;https://devcenter.heroku.com/articles/s3-upload-node&quot;&gt;an article on Heroku’s dev
centre&lt;/a&gt; on the subject, which makes use of Amazon’s AWS library for
Node.js. The library is used to create the proper signature for the
upload request, which contains information like where in the bucket to
put the file, expected file size, and authentication to the
bucket. Once the image is successfully uploaded, a call to the API is
made to register the newly uploaded gif in the Giffy database.&lt;/p&gt;

&lt;p&gt;The Heroku article also included a link to a &lt;a href=&quot;https://github.com/flyingsparx/s3upload-coffee-javascript&quot;&gt;client-side S3 uploading
script&lt;/a&gt;. I quickly ran into some limits with the script though, such as
not getting as much metadata as I would have liked about the file with
the upload completion callback, or not supporting the ability to
upload a binary image blob to S3. I ended up forking the repo and made
the necessary adjustments, which you can find &lt;a href=&quot;https://github.com/obsoke/s3upload-coffee-javascript&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While this solution is novel, I kind of regret designing it this
way. This has to due with how I now feel about gifs in general. Gifs
can cause unnecessary repaints in some browsers, which can greatly
affect performance. For Giffy, where I could potentially have a page
full of gifs, I was worried that performance on some older desktop and
laptops or mobile devices would suffer.&lt;/p&gt;

&lt;p&gt;There have been some interesting ways of solving this problem. For
instance, Twitter &lt;a href=&quot;http://blog.embed.ly/post/89265229166/what-twitter-isnt-telling-you-about-gifs&quot;&gt;converts gifs to mp4&lt;/a&gt; and shows users the video file
instead. I thought this was a pretty neat solution. Not only will a
mp4 file be much smaller than the average gif, but the user also gets
control over the playback of the image. This is most likely the
solution I would have chosen for Giffy as well. However, since Giffy
uploads the image directly to S3, it wasn’t feasible for this
iteration of the project. If I decide to return to the project, it
would be the first thing I would change.&lt;/p&gt;

&lt;h3 id=&quot;create-gif-from-webcam&quot;&gt;Create gif from webcam&lt;/h3&gt;

&lt;p&gt;The final feature I wanted to implement was the ability to use one’s
own webcam to create a gif. When I was working as a contractor for
Mozilla Webmaker last year, this was an idea the frontend team played
around with for the Webmaker Profiles feature. I thought it was fun
and decided to implement it into Giffy.&lt;/p&gt;

&lt;p&gt;My implementation is pretty simple. The creation of gifs is done by
capturing frames via button click. I found a &lt;a href=&quot;http://jnordberg.github.io/gif.js/&quot;&gt;gif encoder written in
JavaScript&lt;/a&gt; that I use to create the gifs. When one clicks the
`Capture` button, the current frame displayed in the video tag is
copied pixel by pixel to a canvas. The image data stored in the canvas
is used by gif.js to create one frame of the gif. gif.js uses web
workers to create the gif in the background, leaving the interface
responsive.&lt;/p&gt;

&lt;p&gt;For one crazy second, I actually considered writing my own gif encoder
in JavaScript. It would have been an interesting project, but way out
of the scope for Giffy. Other things I would have liked to add would
have been some tacky Instagramish filters and the ability to record a
gif for N seconds, rather than having to add each frame manually.&lt;/p&gt;

&lt;h3 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h3&gt;

&lt;p&gt;Some other features that were cut from the list were allowing users to
add gifs to a favourites list, unit tests, and allowing user
comments. The ability to search by tag was another feature I cut. In
retrospect, none of these features would be particularly difficult to
implement at this point but you have to draw the line somewhere on
some personal projects or they will never end. There are other
potential projects that I am currently more interested in spending my
time on.&lt;/p&gt;

&lt;p&gt;I learned quite a bit from working on Giffy. Aside from the numerous
technical and design lessons I learned, the lessons about scope and
feature creep are what really hit me: breaking big features up into
smaller ones and setting attainable milestones that end with some
feature that can be demonstrated in at least a small fashion. Working
on Giffy one huge feature at a time made it feel like a chore, but now
that it’s finally over, the satisfaction of putting the ‘Complete’
label on a project makes it all feel worth it. Kinda weird how that
happens.&lt;/p&gt;

&lt;p&gt;Feel free to check out the source code &lt;a href=&quot;https://github.com/obsoke/giffy&quot;&gt;on my GitHub repo&lt;/a&gt;. A &lt;a href=&quot;http://giffy.dale.io/&quot;&gt;demo of
Giffy&lt;/a&gt; is also available. I’ll be writing a cron script to clean out
the database &amp;amp; S3 bucket every few days. Please don’t abuse the demo
site! Feel free to fork, open pull requests, or leave feedback!&lt;/p&gt;
</description>
        <pubDate>Wed, 31 Dec 2014 12:05:00 -0500</pubDate>
        <link>https://dale.io/blog/giffy_postmortem.html</link>
        <guid isPermaLink="true">https://dale.io/blog/giffy_postmortem.html</guid>
        
        <category>open-source</category>
        
        <category>giffy</category>
        
        <category>projects</category>
        
        <category>postmortem</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Playtime with Phaser</title>
        <description>&lt;p&gt;For the past few days, I’ve been playing around with &lt;a href=&quot;http://phaser.io/&quot;&gt;Phaser&lt;/a&gt;, a game engine written
in JavaScript. I decided that I’d like to experiment with game development for the next month. It has been
a career path I’ve considered on and off throughout my life, but I need to put the idea to the test: do I
actually &lt;strong&gt;want&lt;/strong&gt; to make games, or do I just find the thought of doing it appealing? Let’s find out!&lt;/p&gt;

&lt;h3 id=&quot;struggle-of-inaction&quot;&gt;Struggle of Inaction&lt;/h3&gt;
&lt;p&gt;A lot of new game developers (including myself) seem to fall into a trap.
Do you want to make a game, or do you want to learn how to program games through engines? My problem was that I was
obsessed with the idea that I had to start out learning how it all worked from the lowest level. “If I use an engine,”
I would think to myself, “and it limited my grand ambitious game, whatever would I do?!” I would then attempt to learn OpenGL,
get frustrated trying to tie everything together into something that resembles a game and give up.&lt;/p&gt;

&lt;p&gt;The fear of using an engine without fully understanding how games work was a huge concern, although I don’t know why. I don’t understand how my car works
but that doesn’t stop me from using it. I think I was partially making excuses to justify the &lt;a href=&quot;http://en.wikipedia.org/wiki/Not_invented_here#In_computing&quot;&gt;Not Invented Here Syndrome&lt;/a&gt;
I was experiencing. If I really want to make games, an engine is probably the best place to start. When I run into issues due to gaps in my knowledge, I’ll just
fill those gaps in as I need to.&lt;/p&gt;

&lt;h3 id=&quot;select-your-engines&quot;&gt;Select your Engines&lt;/h3&gt;
&lt;p&gt;With a renewed sense of resolve, I now had to choose a language and engine to work in.
I decided that my first project would be a simple platforming-style game so heavy engines like Unreal
or CryEngine seemed a bit over-the-top. &lt;a href=&quot;http://unity3d.com/&quot;&gt;Unity&lt;/a&gt; is another very popular engine with indie and hobbyist developers,
and has the ability to export your game to a variety of platforms. In the end,
I felt forced into using their GUI app to get stuff done. I’m just not a big fan of using mice!&lt;/p&gt;

&lt;p&gt;It had been a few years since I last looked at JavaScript game engines. Back then, audio on the web wasn’t well-supported. The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API&quot;&gt;Web Audio API&lt;/a&gt;
is now here but still doesn’t have full browser support (looking at you, IE). Regardless, I feel like JavaScript speed increases, audio API improvements and the growth of the JS game development community has made this a good time
to try out writing a game in JavaScript.&lt;/p&gt;

&lt;p&gt;There are quite a few mature JS game engines around, such as &lt;a href=&quot;http://melonjs.org/&quot;&gt;MelonJS&lt;/a&gt;, &lt;a href=&quot;http://impactjs.com/&quot;&gt;ImpactJS&lt;/a&gt;, and &lt;a href=&quot;http://phaser.io/&quot;&gt;Phaser&lt;/a&gt;. I ended up choosing Phaser for a few reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The Website looked good (Hey, what can I say, this actually matters to me)&lt;/li&gt;
  &lt;li&gt;Excellent &lt;a href=&quot;http://examples.phaser.io/&quot;&gt;examples site&lt;/a&gt; and &lt;a href=&quot;http://phaser.io/&quot;&gt;documentation&lt;/a&gt;. These two were fairly important in my final decision. The examples site contains many (you guessed it) examples
of different ways to implement everything from animation via spritesheets, using the camera, music and more. I’m a learn-by-example kind of person, so this was perfect for me. The documentation is pretty great,
and the source code itself is well commented and easy to understand.&lt;/li&gt;
  &lt;li&gt;Price &amp;amp; license. ImpactJS costs $99USD for a license. While you receive the source code with your download, you can’t contribute upstream from what I understand. Both MelonJS and Phaser are open source under the MIT license.
I’d prefer to use an open source engine if I could, as I’d like to contribute any bug fixes I may come across with the engine itself.&lt;/li&gt;
  &lt;li&gt;Built-in support for levels created with &lt;a href=&quot;http://www.mapeditor.org/&quot;&gt;Tiled&lt;/a&gt;, a tile-based map editor. This wasn’t a huge deal but it is nice to have.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both Phaser and MelonJS seemed equally capable. I found more questions asked on StackOverflow on Phaser (287 vs MelonJS’s 47 as of this post). While questions on StackOverflow isn’t the greatest metric to judge an engine on,
I just wanted to make a quick choice and this shallow justification did the job.&lt;/p&gt;

&lt;h3 id=&quot;initial-thoughts--issues&quot;&gt;Initial thoughts &amp;amp; issues&lt;/h3&gt;
&lt;p&gt;Now that I had my engine chosen, it was time to get started. This is where I encountered my first roadblock: I had no art. I needed some tilesets and character sprites to start off with.
Luckily, there are plenty of freely licensed artwork packs available for those of us who are not artistically inclined. One such pack, &lt;a href=&quot;http://opengameart.org/content/platformer-art-complete-pack-often-updated&quot;&gt;Platformer Art Complete&lt;/a&gt;
is a huge pack of tiles, items, character sprites and more made by an awesome dude named Kenney.&lt;/p&gt;

&lt;p&gt;After creating a small simple level with a few platforms, I loaded it into the
engine and noticed that some platform tiles were not the ones I selected to use
in Tiled. The initial spritesheet included in the pack that I was using had some
excess art on the right margin. Spritesheets work by providing the size of each frame
in the sheet, and the amount of rows and columns of frames. So if Tile N is on row 3,
column 3 of the sheet, and each frame is 50 pixels square, then by grabbing the subsection
of the image at x 100, y 100 should get us the desired frame. However, while Tiled
was smart enough to remove the excess tiles from the spritesheet, there is no way Phaser
could possibly know that; it just knows how big each frame is and the amount of frames per
row and column. I found a &lt;a href=&quot;http://opengameart.org/content/kenney-platformer-base-pack-for-tiled&quot;&gt;version of Kenney’s platformer base pack&lt;/a&gt;
that was made to work with Tiled. After using this, my problems went away. When I
attempt to create my own art, I’ll be able to specify how the spritesheet is layed out.
Until then, be mindful of your art!&lt;/p&gt;

&lt;p&gt;After ensuring the level was being rendering correctly, I added a simple character
with basic move left/right controls. So far, so good. I decided to test out the camera
functions by creating a level larger than the canvas/game viewport of 1280x720.
For some reason, this caused my player sprite to get caught on some invisible walls.
I did some research and found &lt;a href=&quot;http://www.html5gamedevs.com/topic/10517-camerascreenview-is-never-adjusted/&quot;&gt;this thread&lt;/a&gt; with some else describing a similar issue.
Luckily enough, a Phaser developer chimmed in stating that he found the cause and that
it had been fixed in the dev branch. Thankfully, using the dev version of Phaser
seemed to fix it.&lt;/p&gt;

&lt;p&gt;So far, I’m pretty happy with Phaser. Just getting things happening on a screen and
reacting to input is pretty awesome. Hopefully I’ll have something to show off in my
next post!&lt;/p&gt;
</description>
        <pubDate>Fri, 21 Nov 2014 07:30:00 -0500</pubDate>
        <link>https://dale.io/blog/playtime-with-phaser.html</link>
        <guid isPermaLink="true">https://dale.io/blog/playtime-with-phaser.html</guid>
        
        <category>gamedev</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Back to Blogging, Back to Game Dev</title>
        <description>&lt;p&gt;It’s been a few months since I’ve last written a post here on the blog. I’ve been working with
&lt;a href=&quot;https://mozilla.org&quot;&gt;Mozilla&lt;/a&gt; on the &lt;a href=&quot;https://webmaker.org&quot;&gt;Webmaker&lt;/a&gt; project since school ended.
Not only have I been having lots of fun doing a ton of front-end work but I’ve also been
learning from the brilliant people on my team. Working at Mozilla has been and continues to be
an awesome experience but that’s not what this blog post is about.&lt;/p&gt;

&lt;p&gt;Once again, I’ve gotten the game development itch. When I think back on the past few years,
I realize that the itch never went away but school took a priority. Additionally, my RSI was so bad that I couldn’t
really afford to use my hands for anything but programming assignments. Since then, my hands have
significantly improved. I’m now able to work full work weeks and also do programming and gaming
on the side. As things have been going so well, it seems like a good time to scratch the game
development itch.&lt;/p&gt;

&lt;p&gt;As usual, I spent quite a bit of time agonizing over what language and technologies to dedicate my
efforts towards. In the last year, I’ve worked a lot with C++ (with WebVTT in Firefox) and JavaScript (with Webmaker).
I have had prior game development experience in C++ (SFML) and C# (XNA).  I also understand that Unity is a popular choice for those who want to
start designing a game right away. After careful thought, I realized that designing a game right away is the exact opposite of what I want to do.
Perhaps I’m being stubborn, but the desire to learn how games actually work is far greater than the desire to started working on a game right away.
I’m also interested in the demoscene, which creates audio/visual demos of… well, anything. Just do a YouTube search for ‘demoscene’ to see
what I am talking about.&lt;/p&gt;

&lt;p&gt;Actually, while writing that last paragraph, I believe I thought of why I want to learn how games (and graphics) work.
There is a lot of room to be creative through programming. The cool graphics or games one can create with code
is proof of that. Right now, I have all these cool ideas in my head for potential demos and games. The problem is I
have very little technical knowledge on how to get those ideas onto the screen. So it’s time to remedy that! The languages
and technologies I’ve decided to go with are GLFW to create the window creation, OpenGL for graphics and… that is it for now.
I’ll be working on a 2D tetris clone, and I’ll be blogging about it as I go. I figure that is a good project to start with. My
first goal will be to draw a box on the screen. Once I learn exactly how to do that, I’ll be back with another post!&lt;/p&gt;
</description>
        <pubDate>Fri, 27 Sep 2013 10:58:00 -0400</pubDate>
        <link>https://dale.io/blog/back_to_blogging_back_to_game_dev.html</link>
        <guid isPermaLink="true">https://dale.io/blog/back_to_blogging_back_to_game_dev.html</guid>
        
        <category>gamedev</category>
        
        <category>open-source</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>WebVTT&amp;#58; The Middle</title>
        <description>&lt;p&gt;It’s been a while since my last post about WebVTT. A lot has been going on
since that last post in the beginning of March. The OSD team gave two presentations about
WebVTT to Mozilla Toronto: one during a class visit to MoTo and another
during MoTo’s Open Web Open Mic event to some of the Toronto open source community.
Both events were a lot of fun! I was surprised by how excited some people seemed to get when they saw
WebVTT. When you work on a project, it can be hard to take a step back
and see the impact your project has on others, especially when you can
get so invested in said project. Good job team!&lt;/p&gt;

&lt;p&gt;I haven’t been able to spend as much time on WebVTT as I would have liked
over the past month. After the push to get things working for the first
Mozilla Toronto demo, I had an avalanche of final assignments fall onto me.
Now that they are finally behind me, I’ve been able to get back into the
swing of things.&lt;/p&gt;

&lt;h3 id=&quot;review-issues&quot;&gt;Review Issues&lt;/h3&gt;

&lt;p&gt;While I’ve been busy with school, rillian has been working on the patch.
Thanks a lot, rillian! There have been several iterations of the patch since.
As always, you can see the latest updates on &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=833385&quot;&gt;the Bugzilla bug&lt;/a&gt;.
It’s been reviewed quite extensively by bz and Ms2ger who brought up a few issues.&lt;/p&gt;

&lt;p&gt;One of the issues had to do with nested templates. We were using nsTArrays like this: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsTArray&amp;lt;nsRefPtr&amp;lt;TextTrackCue&amp;gt;&amp;gt;&lt;/code&gt;,
which reads as ‘an array of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsRefPtr&lt;/code&gt; which refer to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTrackCue&lt;/code&gt; objects.’ Apparently, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&lt;/code&gt; at the very end was
being interpreted as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&lt;/code&gt; operator on some older compilers. So we just added some 
whitespace to pad out the characters: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsTArray&amp;lt; nsRefPtr&amp;lt;TextTrackCue&amp;gt; &amp;gt;&lt;/code&gt;.  Easy fix!&lt;/p&gt;

&lt;p&gt;In the review, it was suggested that we convert &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsAString&lt;/code&gt; out parameters in
class getters to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMString&lt;/code&gt;, a relatively new class in the Mozilla codebase.
I went ahead and did this, but it was not an easy fix. In fact, it was pretty
messy, and involved extracting a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringBuffer&lt;/code&gt; from an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsAString&lt;/code&gt; object and
using that to set the value of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMString&lt;/code&gt; out parameter.&lt;/p&gt;

&lt;p&gt;The code used to set getters went from this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GetKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nsAString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;aKind&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;to this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DOMString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;aKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SetStringBuffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nsStringBuffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FromString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mKind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Yikes. That’s what I call messy. To be fair, this is the only way to set the value
of a DOMString from an nsString, the type used internally to store strings.&lt;/p&gt;

&lt;p&gt;It didn’t get accepted. In retrospect, it would have been easier to just adjust the internal
members of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTrack*&lt;/code&gt; objects to use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMString&lt;/code&gt; rather than a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsString&lt;/code&gt;.
Once I clarify with others that this is the best way to go about with this fix,
I’ll probably end up doing just that.&lt;/p&gt;

&lt;p&gt;The first fix ended up making its way into the patch on Bugzilla. The pull request
on GitHub is still open due to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOMString&lt;/code&gt; issue. If you’re interested in following
that particular issue, you can &lt;a href=&quot;https://github.com/RickEyre/mozilla-central/pull/10&quot;&gt;check it out here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;exceptions&quot;&gt;Exceptions&lt;/h3&gt;

&lt;p&gt;Something I’ve wanted to start adding to the WebVTT DOM implementation for a while
now is exception handling. Firefox’s C++ code doesn’t use exceptions; I’m talking about
JavaScript exceptions. For instance, if one tries to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;removeCue(cue)&lt;/code&gt; method on
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTrackList&lt;/code&gt; JavaScript object which doesn’t contain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cue&lt;/code&gt;, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NotFoundError&lt;/code&gt; exception
should be thrown.&lt;/p&gt;

&lt;p&gt;In order to do this, we first need to edit the WebIDL file which defines
the DOM interface. We must add a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Throws]&lt;/code&gt; declaration in front of every
method which throws an exception. For example, in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTrack.webidl&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Throws&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TextTrackCue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Throws&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;removeCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TextTrackCue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;By using some crazy wizardry, this creates the necessary DOM bindings to use
exceptions. More specifically, it passes an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorResult&amp;amp;&lt;/code&gt; as the last argument
to our method. We can use this object to throw exceptions.&lt;/p&gt;

&lt;p&gt;Let’s take a look at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTrack::RemoveCue&lt;/code&gt; and how we can throw an exception
if the cue passed as an argument is not already in the internal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTrackList&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In our header file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RemoveCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TextTrackCue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;ErrorResult&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aRv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the implementation file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;TextTrack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RemoveCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TextTrackCue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                     &lt;span class=&quot;n&quot;&gt;ErrorResult&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aRv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// If the given cue is not currently listed in the&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// method&apos;s TextTrack object&apos;s text track&apos;s text&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// track list of cues, then throw a NotFoundError&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// exception and abort these steps.&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DoesContainCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;aRv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Throw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NS_ERROR_DOM_NOT_FOUND_ERR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Remove cue from the method&apos;s TextTrack object&apos;s text track&apos;s text track&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// list of cues.&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mCueList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RemoveCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aCue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The generated bindings make it very easy to throw an exception. Now that
an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorResult&amp;amp;&lt;/code&gt; is being passed to our method, we simply call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Throw&lt;/code&gt; on
the object and pass the error. One could search on MXR for the particular
error macro/constant they need; luckily, bz told me which to use in #content.&lt;/p&gt;

&lt;p&gt;Initially, I was a bit confused when trying to implement exceptions. While
looking through MXR to see examples of how other classes implemented exceptions,
I’d often see &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorResult&lt;/code&gt; initialized as a local variable within a method. Apparently,
this is only used for methods that catch exceptions. Methods that throw exceptions do it
through an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ErrorResult&amp;amp;&lt;/code&gt; argument passed in by the generated binding methods. Oh, you
Mozilla engineers. You guys/gals are magic.&lt;/p&gt;

&lt;p&gt;That particular pull request is still open at the time of writing. You can
&lt;a href=&quot;https://github.com/RickEyre/mozilla-central/pull/11&quot;&gt;check out that pull request here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;10&quot;&gt;“1.0”&lt;/h3&gt;

&lt;p&gt;I’m really not sure if this release can be considered a 1.0 release. The code still
hasn’t landed in Firefox (although it seems close). There are still things to do!
Some of those things include: maintaining and using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTracks.activeCueList&lt;/code&gt;, finish
implementing exceptions on the rest of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTrack*&lt;/code&gt; classes, and fix all of the issues
raised in the reviews done by bz and Ms2ger. Concurrently, I believe we are at the point where
we can start using the MochiTests written by Marcuus and Jordan to bring other issues to light.&lt;/p&gt;

&lt;p&gt;A big issue is the ever-shifting nature of the WebVTT spec. It seems like every week, the spec
changes - and not always for the better. For instance, there are now a list of rules associated
with every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTrack&lt;/code&gt; that defines how the text tracks should be rendered. Also, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TextTrackCue&lt;/code&gt;
is an abstract class from which we should be creating a new object: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WebVTTCue&lt;/code&gt;. Not all these
changes make sense to me (Rules for updating cues? Why?) but I guess that is a part of the age-old
rift between spec writers and implementers.&lt;/p&gt;

&lt;p&gt;Between the spec being in flux and the other items still on my to do list, there is still quite
a bit to be done before I’d be comfortable slapping the ol’ 1.0 tag on. Now that school is
officially complete forever, I should have much more time to spend on WebVTT.&lt;/p&gt;

&lt;h3 id=&quot;the-middle&quot;&gt;The Middle&lt;/h3&gt;

&lt;p&gt;Speaking of school being officially done forever, this is my last official ‘for school’ post on my blog.
This isn’t the end though, not by a longshot. I’ll be continuing my work on WebVTT as a volunteer. I’m excited
to see what happens with the project in the coming few months!&lt;/p&gt;

&lt;p&gt;Thanks to Humph for teaching the OSD classes to begin with. If you are a student at Seneca in CPA or BSD,
do yourself a favour and take these classes. The OSD classes are the best professional options offered at
Seneca, in my opinion. I’d also like to thank  my OSD teammates for a crazy 8 months. We’re still alive!
Success!&lt;/p&gt;
</description>
        <pubDate>Fri, 19 Apr 2013 11:30:00 -0400</pubDate>
        <link>https://dale.io/blog/webvtt-release-1.html</link>
        <guid isPermaLink="true">https://dale.io/blog/webvtt-release-1.html</guid>
        
        <category>open-source</category>
        
        <category>osd700</category>
        
        
        <category>blog</category>
        
      </item>
    
  </channel>
</rss>
