Hexo, static site generator


For a while now I've been running a custom hybrid of Ghost and the static site generator I built early last year. While it was doing the job, it was a bit ugly on the backend and difficult to maintain so as a Christmas project I went looking for a replacement.

Hey Hexo!

After some cursory googling I found Hexo, which seems to satisfy all my fairly simple requirements:

  • node-based to make the most of the NPM ecosystem, and because I don't like Ruby dependencies.
  • Plain and simple, no weird tech or lock-in.

Hexo

Functionally Hexo is pretty similar to Jekyll and uses all the same terminology.

The directory layout is split between source for content and themes for layout. The latter can deal with CSS and Javascript preprocessing automatically, which I was initially cold on (small modules, yo!), but it grew on my when I realised the "hexo server" site preview tool was automatically recompiling CSS & JS as I was making changes.

It's fairly pluggable, and supports my favourite Markdown renderer Marked which does lovely things to Markdown.

Custom metadata

One of the things I'm a particular fan of with Hexo is the ability the put data (as either YAML or JSON) into the front-matter. This is awesome because it lets you make templates to do pretty much anything.

One example is my Projects page, which now consists of a paragraph of actual text, and a big glop of JSON representing each project. The template takes the JSON and renders the page as if by magic, and it's much nicer than trying to organise that stuff manually.

Hexo Homepage

Conclusion

Pretty happy with this one. I've been wanting to standardise on something decent, and this fits the bill nicely. There's a whole bunch of tools and the workflow is nice. The documentation is excellent and the process of getting from nothing to a functioning site is pretty straightforward.

I like it. If you're looking for a static site generator in the Node ecosystem, then definitely give this one a go.

Road Blocks & js13k

I've been looking forward to entering the js13k competition this year, because it's one of my favourite game jams.

TLDR: play Road Blocks (don't forget to like and share :P)

Set over a month-long period, the js13k challenge is to create a compelling game within 13 kilobytes. This doesn't sound like much, but you can do a lot with it if you get creative.

Last year I dreamed fairly small, with a space invaders clone set to polar coordinates. I had fun making it, but it wasn't especially playable and this year I wanted to do something completely different and come up with a mobile friendly touch-based game.

Road Blocks screenshot

The Concept

The concept had been rattling around in my head for a while. I've a very soft spot for city builders, and I love isometric art. While an outright city builder probably wouldn't be feasible, a subset thereof might just work.

My main inspiration was an old DOS/Windows game called Pipe Dream, in which you're given an infinite number of puzzle pieces and need to connect the start pipe to the edge of the map somewhere before the liquid spills out. Mash this concept up with the city building theme and you've got a basic connect-the-infrastructure sim.

When the theme of the jam came out as “reversed” I really struggled to find a way to align the concept with the theme, so I had to mix it up.

Ultimately I landed on the puzzle-style "arrange the pieces to fit" theme, in which you need to strategically destroy or reverse the order of the tiles as they come off the queue. It's a little less "world buildy" and a little more constrained, but I think the gameplay works, and it gives me the opportunity to expand the game with new puzzles in the future.

The Tech

The tech is also an idea that's been bouncing around in my head for a while. I've long been a fan of isometric art (pixel art as well as more recently isometric vector art and voxel art) so I wanted to do something in that style.

I had a play around in CodePen and came up with a crazy simple plan; draw everything in voxels. The algorithm to draw an isometric cube isn't all that difficult. You've got three visible sides, each side consisting of four lines and a fill colour. Turn that into a function and you can start making some cool stuff.

See the Pen HTML5 Canvas isometric cube demo by Ash Kyd (@AshKyd) on CodePen.

You can adjust the sliders on the example above to modify the cube.

Drawing voxel sprites

With the idea down, the next step was to draw a game world. There's a bunch of sites out there that have isometric code examples. I had Clint Bellanger's isometric math tab pinned in my browser for a good week, though in reality there were only two functions I really needed:

  • Convert isometric position to screen/pixel position
  • Convert screen/pixel position to isometric position

These two functions let me both draw isometric boxes to the appropriate location on the screen, and then detect where those boxes were stacked when the user interacted with them.

From there, the trick was to come up with sprites made from boxes. While it was possible to sort of work it out in your head, this was often a trial-and-error process, placing boxes and seeing where they land in the output.

See the Pen HTML5 Canvas isometric cube demo by Ash Kyd (@AshKyd) on CodePen.

In the above example you can see a road tile with three components, rendered from an array:

var sprite = [
  [-0.25,.9, 0, 0.1, 1, 0.25, '#aaaaaa'],
  [-0.25,.1, 0, .8, 1, 0.2, '#444444'],
  [-0.25,0, 0, 0.1, 1, 0.25, '#aaaaaa'],
];

Each item in the array corresponds to a coordinate. In this case the z, x, y coordinates, x width, y width and height.

In the end, my sprite list resulted in a bunch of arrays and functions that don't make a great deal of sense to the naked eye but render cute little box sprites in the game engine.

Putting it all together

With a bunch of sprites at my disposal, all that was left was to implement the game! Easy, right?

I actually took a week off specifically to work on Road Blocks, and I'm glad I did. Through the week I implemented the engine various features (some of which didn't make the final version) and tuning interactions.

Because I wanted this to be a first-class touch game, I implemented everything mobile first. This was a fantastic way to discover all the limitations of the platform at the get-go rather than having to refit a desktop game to mobile later on.

I also spent a lot of time user testing the game, be it in person or through analytics. Testing is a really important part of any gamedev process, and it was really enlightening to watch people playing my game for the first time. Many a puzzle or interaction was tuned based on feedback and watching people work out a level.

I also released my game via Twitter as a public beta to gather play statistics and weed out any errors that might crop up. I used Loggly to record a bunch of custom game stats and events, and the results were quite valuable in determining difficulty and how people were faring playing the game.

One particularly revealing fact was that most people were getting stuck on a particular level. Armed with feedback from testers and the hard facts of the analytics, I tweaked it to be not quite as difficult and pushed it from the middle of the campaign to the end to make it a sort of "final boss" level instead.

As a side note, one day I got distracted and came up with a data encoding scheme for level data which helped reduce the file size in the final zip.

Conclusions

I'm really pleased with the results this year. The game clocked in at just under 13 kilobytes and made efficient use of the space.

Some notes in hindsight:

  • Levels and sprites should probably use a binary data scheme to reduce file size and allow the use of Web Workers.
  • For some reason HTML5 canvas makes the CPU spin up like crazy. I'd like to get to the bottom of this sometime.
  • User testing is mandatory. When developing something in isolation you can get into a weird headspace and not notice the obvious stuff.
  • I had initially intended to have little cars animating along the roads, but ran out of space and couldn't think of how best to do this. I need to learn more about vectors in gamedev.

Ultimately, this year's js13k was a whole heap of fun and I'm really proud of my result. There's a bunch of awesome entries that you should check out, and you should consider entering next year.

Further reading

You can play Road Blocks on the js13k website. You can also check out:

jsfxr sequencer

I didn't go into this weekend with a project, but I woke up Saturday with an idea I couldn't get out of my head — I want to write a music sequencer with a really low footprint for use next month in the js13k game competition.

I've written about js13k before, and took part last year. This time around I want to be a bit more prepared, and I wanted to make a tool that would make it easier for the community to make cool stuff!

So this weekend I've been working on a bunch of different tools to make this project a reality.

Mini Sequencer

Mini sequencer is exactly that: a mini sequencer implementation that can play sounds at various times to form tunes.

This was my first mini project, as I was interested to see what the performance of web audio would be like; it's surprisingly good. That said, if I get time I'd like to look into replacing it with the Web Audio API, as it's a lot less hacky and should perform better.

jsfxr-editor

jsfxr is a little 8 bit synth which was implemented a few years ago for use in the js13k competition.

Since this is probably what most of my sounds are going to be implemented by, I wanted to be able to create new sounds from my sequencer. While there's a few sites out there (my favourite by Super Flash Bros) that let you adjust sliders and make new sounds, there's not actually an out-of-the-box tool you can use to plug into your own project.

So after a bit of reverse engineering of as3fxr (the original Flash version), now there is.

This actually took up a whole bunch of my time, and if I were a project manager I would have dropped this to focus on other stuff, but hindsight, right?

Fruity Timeline

I got to the end of the weekend and felt like I hadn't really ended up with much to show off.

The timeline was one of the big things I'd been putting off doing because it's slightly weird and I wasn't quite sure how to tackle it, so I went all-out and implemented a standalone component (depends on jQuery but probably doesn't need to).

I'm pretty proud of this one, it's styled reminiscent of the old Fruity Loops sequencer and just looks a bit retro.

The main event

So despite having made a million things this weekend, I haven't actually finished the project I set out to do. Right now I have:

  • Create & manage a library of instruments (with jsfxr editing built in)
  • A super rudimentary timeline (edit some JSON by hand and the music will update)
  • BPM adjustment.

Things I need to do from here:

  • Plug in the actual fruity timeline so you can edit your song visually.
  • Implement a "piano roll" feature so you can have different pitches of the same instrument.
  • Stop/play/seek functionality
  • Export your file
  • Load up proper audio files (mp3/wav/whatever) so you can play with those too.

It looks like there's a lot there left to do, but I think I'll be able to get a minimum viable product done with another weekend. I'm not sure if I want to publish the code yet since it's a massive pigsty, but I'll aim to get something out before next weekend is through.

Edit: Ended up getting something together Sunday night. Try it out.

Web workers – an overview

We recently had a talk about about service worker at BrisJS — the local Javasccript meetup — but I wanted to take a step back and talk a little more generally how workers all fit together.

You can view my original slides & interactive presentation on GitHub.

What’s a worker?

A worker is essentially a separate process in which you can run some Javascript code.

The thing about Javascript is that like most programming languages it’s single-threaded, which means when you’re executing code you can only do one thing at a time. We've got it fairly good with async tasks in Javascript land, with things like AJAX and upcoming ES6 promises, but even still if you've got a long-running task it’s going to lock up your thread until it’s done.

This doesn't sound so bad until you consider that the thread you're executing Javascript in also includes the thread that renders your page, which means your animation, scrolling, the whole shebang will stop working until your JS is done.

Thus separating your Javascript into a separate worker process can significantly improve performance on your site if you’re doing a lot of processing.

Quick description of workers

So should you just stick your code in a worker and hope for the best, right? Not quite.

A worker gives you a more Javascript-oriented environment than your standard script is used to. To start with, there's no window object, so things like window.onload don't do anything (the script in the worker starts firing once it's loaded, and doesn't need to wait for anything else). There's also no DOM or XML parsing, and you only get a subset of the APIs you’d have access to in a regular Javascript page.

This means that the code in your worker is essentially sandboxed from the regular goings on of your page, and you have to structure your app accordingly.

With such a restricted environment, it's easy to discredit workers, but there are several things a worker is good for:

  • Pretty good sandbox – makes you more mindful of your code, and helps you write good, testable modules.
  • Ideal for discrete tasks – Things that you can boil down to a standalone component are great for use in workers.
  • Longer running, CPU intensive tasks – These are where workers shine. If you're doing anything at all that might take longer than the 16.66 milliseconds/60 fps of your page draw, consider taking it out of the main thread for super performance gains & smooth animation/scrolling.

So this might include things like browser games or web apps with large amounts of data.

Types of worker

There’s three main types of worker:

  • Dedicated workers are the bread and butter worker, and work in almost all browsers. They’re really simple, you can fire them up in your page, do some processing, tear them down. Easy!
  • Shared workers are similar to dedicated workers, except you can fire one up and access it from anywhere else your entire origin. Multiple tabs and all. These aren't especially well supported, and in my opinion have been mostly superseded by:
  • Service workers! A relatively new type of worker with a longer lifecycle, which can run in the background even when your page is closed, and has a few extra APIs. They’re essentially designed to make the web more app-like.

Start up a worker

Starting up a worker looks a little something like this:

// index.html
var echoWorker = new Worker('echoworker.js');
echoWorker.onmessage = function(message){
    console.log('%cMessage from worker: ', 'color: darkred', message);
};
echoWorker.postMessage('Hello worker!');

In this example, we're firing up a worker by pointing to an external script echoworker.js and listening for any messages it might send us.

Then we're sending a hello world message to our new worker.

// echoworker.js
addEventListener('message', function(event) {
    console.log('%cMessage from parent: ', 'color: blue', event.data);
    postMessage(event.data);
}, false);

Inside the worker we can run any code we like. In this example we're simply listening for any messages our parent might send to us, and echoing them back once they've been received.

You can try this code on this page by opening up the console in the presentation and running echoWorker.postMessage('Hello worker!');.

Postmessage API

The postMessage API is the main way of communicating with a worker and has two parameters: message and transferList.

myWorker.postMessage([mixed] aMessage, [array] transferList);

In the initial spec, the message parameter only supported passing of strings, but modern browsers support structured clone which is a spec that’s similar to JSON.stringify except it supports a bunch more things, like blobs, files, regexes etc. This means that you can send a large number of data types through the message parameter, including objects.

One point to note is that passing messages using this API works differently due to the cross-process nature. While traditional Javsascript objects are passed by reference and exist only once in memory no matter how many times you pass them around, objects passed through postMessage are duplicated in order to exist in both processes. So if you're sending large amounts of data between workers, you may end up accruing a lot of duplicated memory that needs to be garbage collected.

To get around this, the transferlist parameter lets you transfer certain data types, rather than duplicating them. At the moment the only data types you can transfer are ArrayBuffers (binary data), but this covers a number of high-profile use cases including Canvas graphics and file handling.

The following example transfers the ArrayBuffer rather than duplicating it:

var myMessage = {
    command: 'doTheThing',
    data: someArrayBuffer
};
echoWorker.postMessage(myMessage, [someArrayBuffer]);

Worker sope

There's not a lot of API devoted to managing workers. Essentially you have:

  • Worker.terminate()
  • WorkerGlobalScope.close()
  • WorkerGlobalScope.importScripts()

Terminate lets you terminate a worker from the main script. Close lets you terminate a worker from the inside.

importScripts is the fun one, it's essentially the equivalent of putting a <script> tag into your HTML document, in that it blocks the page and loads the script at that point in time. Of course since we're in a worker it doesn't matter if we block the Javascript because it doesn't affect what's in the page, so this is useful for loading any dependencies you might need before your script runs.

My preference here is to simply bundle everything up with Browserify (because you get all the benefits of NPM and don't have to worry about the file management and extra requests that ensue) but you can just as easily use the native implementation.

Some gotchas

One of the biggest gotchas I've hit when using workers is scripts expecting window to exist. You've probably seen stuff like this around:

if(window.XMLHttpRequest){
    // do the magic
}

It's a handy shortcut to check if something exists, but it's a bit of an antipattern these days because often these functions may exist in another global scope. In Node you've got global and in workers you've got self, so in each of these environments your code is going to throw an error and break everything.

There's two ways you can solve this:

  • Either wrap the offending code in a closure:
    (function(window){ […] })(self);
  • or ensure window exists:
    self.window = self;

The first option is nicer because it's a less grotty-globally hack, but the second is by far the easiest and doesn't seem to cause any problems.

How fast are workers

Guillaume Cedric Marty did a bunch of benchmarks on some of their low end Firefox OS phones over at the Mozilla Hacks blog recently, so if you're interested in the details you can check that out..

The summary: firing up a new worker is the slowest part of the whole affair, everything else is blindingly fast.

Operation Cost
Initialisation ~40ms
postMessage latency ~0.5ms
Communication speed 45kB/ms

The take-out from this is that you should fire up only as many workers as you need, and reuse them for common tasks. You can do this by having all your tasks bundled into the one codebase, and then running one or more identical workers that you can share tasks across as required.

Another consideration in terms of performance is only firing up as many workers as will benefit your system. Considering your render thread is already taking up a process, you should consider firing up cores - 1 workers (or if your render thread won't be doing much, fire up a worker per core.)

You can get the number of cores in a system using the webkit-specific navigator.hardwareConcurrency or using one of the polyfills depending on your needs.

Actually writing an app with workers

So you're writing an app that will be using workers, one of the most important things to get right is the communication. postMessage is a super simple communication mmethod, so you'll probably want to build something on top to make this smoother.

  • My favourite thing to do is write a little async ‘do something’ api, so you can post commands and receive callbacks.
  • Something I've been playing with is running the whole model in a worker. This can be useful when dealing with lots of data & processing.
  • An existing library: there's a bunch of them. I like workerproxy because it gives you load balancing and some debugging for free, but I've found it can eat errors and make things difficult sometimes.

Further reading

My battery is about to run out, so I'll leave you with some more reading materials that you can go through to get you on your way:

The trials of moving house in a Telstra dominated area

My lease was running out and I was vaguely looking at apartment prices in my area when I saw it: my dream place.

My dream place turns out to be a converted loft upstairs from an organic cafe that’s never open and adjacent to an overgrown empty lot. From the outside it’s terrifying, but the inside is all natural light, high ceilings with rafters and tacky faux-wood linoleum. It was my first choice last time I moved house (and was unfortunately off the market before I got it) but this time damnit, it was going to be mine.

My new place! there's boxes everywhere and plants needing a home

So I inspected it, submitted an application, and moved in over the weekend. Couldn’t be easier!

Then I tried to get the Internet on.

Telstra Velocity Fibre Smart Community haha wait, oh dear

For those who aren’t in the know, in 2012/13 Telstra replaced the ageing copper network from the South Brisbane exchange with fibre to the premises. The caveat being that it’s still wholly owned by Telstra and has nothing whatsoever to do with the NBN.

It’s known by various names, “South Brisbane Fibre” being the preeminent one, but Telstra also calls it “Telstra Velocity” or a “smart community” just to make things confusing.

The idea is nice, but as far as the consumer is concerned it would have been better if the rotting copper was left in the ground. Since getting their “smart” on Telstra jacked up wholesale prices, started demanding exorbitant monthly line rental fees, and throttled the network to copper-comparable speeds anyway.

Since the government prevents other parties rolling out networks that compete with the NBN and there’s none of the checks and balances the ADSL network enjoys, this is an outright Telstra monopoly and they seem to be making the most of it.

Getting connected in South Brisbane

At my previous place in South Brisbane it took $300 and almost two months chasing iiNet to get online.

At my new place I figured I’d ditch iiNet because they were so useless and go straight with Telstra because surely being the operator of the network they’d have a better idea of what they’re doing.

Turns out not.

  1. On my first attempt to sign-up I was told that ADSL isn’t available at my current address and that’s that.
  2. Feeling annoyed I attempted to sign up online, where I was told that I can absolutely 100% get cable Internet and everything’s fine. Makes sense, fibre is a cable right? I signed up, submitted my order, all good.
  3. Several days later I get a call to let me know that actually I can’t get cable (HFC) in at my apartment: I can only get fibre, and do I want to continue the signup?
    As a consumer, I don’t care about this stuff, I just want to get on the Internet so of course I want to continue. The order languishes for the next couple of weeks while I’m out of town.
  4. When I call up to chase the order I get bumped through three different teams (sales, cable and finally “smart communities”). The guy doesn’t outright say they’ve lost my order, but takes all of my details again before offering me a vastly more expensive plan on a 24 month contract at which point I give him a super polite ultimatum before hanging up and punching some nearby kittens.

The plan on offer was somewhere in the vicinity of $130/month before line rental (another $30 which they don’t tell you until the price goes up at the end). This brought it to over $150/month for the most basic access to the ‘net which is totally unreasonable and I have no idea how they can get away with it.

This month’s internet bill just hit $470 not including what it’s costing to get my landline connected. When was that NBN happening again?

— Ash Kyd (@AshKyd) May 29, 2015

My next port of call was TPG who either refuse to service the South Brisbane area as a result of Telstra’s ridiculous monopoly, or just didn’t know what they were doing. I don’t blame them either way, getting online here has been one of the most frustrating things I’ve had to do as an adult and if I were a service provider I would avoid dealing with Telstra wherever possible.

Finally I called Internode who knew exactly what was going on and generally didn’t completely suck. The downside is their South Brisbane plans run between $150-200 per month for a paltry 250 GB. At this point I just don’t care because I’ve already burnt through more than double that figure this month in mobile broadband and need to get online, but it’s an extraordinary figure and I’m having trouble justifying it.

So what’s going wrong?

It’s easy to blame Telstra for being a lumbering, incompetent monopolist but how did this happen?

In both cases my address hasn’t been in whatever database they use to look things up, and both times it’s caused holdups from “we can’t find you in the system” and “you can’t get Internet” to “we accidentally disconnected your landlord instead, lol soz”.

Surely having just finished updating the network in 2013 they would have all this information? Apparently they don’t keep this around, as even my current apartment which was only disconnected the previous month is completely missing from the system.

Meanwhile I still don’t have Internet at my new place and they seem completely unwilling to help.

— Ash Kyd (@AshKyd) May 29, 2015

Further, both times I’ve had to have technicians come out to poke around to work out what’s going on. The first time took a full four hours to suss out the building connectivity, including everything from calling the helpdesk to shining lasers down the fibre to work out which cable needed to be plugged in at the basement. These visits cost $300 a pop and it’s a total rort.

That it’s the 21st century and you can’t light up an apartment within five minutes by filling in an online form is boggling, and I just don’t understand how so much human intervention is required to get the data flowing over a damn fibre network.

The clincher I think is the all-’round lack of knowledge not just within Telstra where the teams are all siloed and don’t know what they don’t know, but also within the resellers of which only Internode seem to have trained their staff. Essentially, nobody knows what’s going on.

And the NBN?

Yeah, the NBN is pretty much dead. There’s no fibre coming, no hundred megabit, let alone gigabit networking. The policy’s there in name, but the political will certainly doesn’t seem to be.

New developments (like hopefully my new new place) will get NBN fibre, but existing premises aren’t so lucky. As I understand it the current plan is to buy back Telstra’s corroded copper network and roll out HFC and VDSL tech as far as it will go. South Brisbane on the other hand, is likely stuck with Telstra for the rest of time since it’s unlikely the government will separate them or buy up the fibre network any time soon.

Meanwhile the alternatives aren’t many. I’ve currently got a $140/month, 50 GB LTE service from Vodafone which is a reasonably attractive offer by South Brisbane standards but nowhere near girthy enough for my needs. The best Telstra and Optus can offer are 10 GB and 12 GB respectively which is laughable. Beyond that there’s no alternative but to capitulate and give Telstra your firstborn.

Three weeks later

I’m still waiting to be connected. I’ve spent nearly half a grand on Internet (and that’s before the laying anything down for a wired service) and I’m seemingly no closer to having my fibre box light up than I was when I started.

I’m kinda starting to think think I should just quit tech and become a barista.

Sony Xperia Z3 Compact Review

Oh dear. That's the first thought that crossed my mind when I turned this thing on. Oh dear, what have I gotten myself into.

The hardware's fairly pleasant. The mix of glass and plastic feels a bit like an upmarket Nexus 4. It's about the same size as that generation of phones, but the screen is big, at 70.6% screen-to-body ratio (compared to the Nexus 4's 68% or the iPhone 6's 66). It's also exceptionally thin and light; you can tell it's a flagship product.

But damn, the software. The instant I turned it on I was greeted by a custom setup wizard thing. Sony has seen fit to come up with their own software for the setup, and that's probably fine. It asks me to sign in to some Sony stuff and whatever, I can skip it.

Then the phone boots and it's like we're running Android 2 again. Everything's pokey icons and stupid animated wallpapers that look like nothing anyone would ever classify as good design. The launcher's customised, the drawer's customised, the settings are customised to the point that I can't even find where to set up my Google account.

Laser eye surgery: my experience


I'd been considering getting laser eye surgery for a while, and while the idea appealed there wasn't any major incentive for me to do it.

But eventually I got frustrated. My glasses were always getting dirty, falling off, fogging up (while cycling, working out, or once getting off a bus). At work in particular I was finding myself taking them on and off all day since I don't need glasses for working at my desk but whenever someone would come over they'd be just outside my focal distance and I'd have to put them on again.

So having reached perhaps a vague not-quite-quarter-life crisis I decided to just do it and hang the consequences.

Table of Contents 👓

This post is a bit long, so here's a table of contents.

And some updates:


The Tech

There's a few types of laser eye surgeries and they're all pretty squeamish. The ABC has a high level overview of the various types.

I chose IntraLASIK (also known as Femto-LASIK) which uses a laser to create a corneal flap (as opposed to the dark ages when they used a miniature angle grinder), then another excimer laser to evaporate bits of the eye until it's the optimal shape. Amazing, totally terrifying technology, but it works amazingly well.

The alternatve, PRK, doesn't involve a "flap" but has a much longer recovery period since it effectively melts away the top layer of your cornea instead. This one probably isn't for you unless you have a special condition or are at particular risk of head injuries.

Some newer technologies are coming out that show promise, but ultimately IntraLASIK is the best, most mature option out there.


What to expect before laser eye surgery

I initially booked appointments at two places in Brisbane, but only Lasersight got back to me which was strange. The have offices in a number of major urban areas including Sydney, Melbourne, the Gold and Sunshine Coasts so it seemed reputable.

I arrived for my initial appointment not really knowing what to expect, but they were really good. I'd already researched most of the technology, caveats and read countless accounts of other people's success (and failure) stories, so none of the information was particularly new.

Lasersight offer PRK, LASIK and IntraLASIK, but only really do PRK and IntraLASIK as the traditional LASIK (angle-grinder) technology has been pretty much superseded. The nurse I spoke to in my initial consult had PRK himself due to his corneas being too thin for IntraLASIK, and was very happy with the results. Generally a good salesman.

In the initial consult I was taken through a number of machines that scanned my eyes, mapping out the various distortions and measuring the thickness of my corneas. I have a mild astigmatism as well as a mildish shortsightedness, and the machines picked this up and spat out a bunch of graphs and figures saying such. I was also given an eye exam like you get at the optometrist, which confirmed all this as well.

After all the measurements I was told about the payment options and booked in for the procedure the following week.


Lasik prices & extras

Prices I was quoted were:

  • $6600 for IntraLASIK, or $5400 for PRK (Divide by two for costs per-eye)
  • A $200 consult fee and
  • A $200 discount for payment upfront.

This includes all the drugs, consults within a year and the “for life” program in which any subsequent surgeries are free of charge (though consult fees still apply).

It's not the cheapest and some people on various forums have flown interstate or overseas to have it done, but I personally consider that to be a little far out.


On the day

Due to a mistake on the little card they gave me, I showed up expecting a consult but was actually being prepped for the full-on surgery. Thankfully there's not much you need to do to prepare other than not wearing eye makeup or fragrances, neither of which I'm wont to do in day to day affairs.

The initial consult was with Doctor Peter Stewart, director of surgery, who was friendly, answered all my questions and seemed to know what he was doing. He ran me through some of the same tests again to make sure everything was right, before sending me out to fill in some waivers.

The actual surgery was planned for a few hours after the consult, so I had lunch and sat in the stinking Brisbane heat sipping cola across the road.

O Bar mini review: they had inexplicable table service for the bar section, and it took forever to get a drink. The guy was kinda rude but the girl was nice.

At 2:30 I want back in and was ushered into the secret surgery area out the back.


The LASIK procedure

I was dressed up in a robe and hair net, given a bunch of pills to take and administered anaesthetic eye drops which stung like crazy until my eyes were completely numb and could no longer feel anything.

When it was time I was ushered into the room and laid out on the first of two beds at the femtosecond laser. There were three specialists which was really comforting, each presumably had a job to do. One wore fluorescent sneakers.

I don't remember much about the first part, although the general gist was having my eyes propped open, being slid under a machine and having it take a flap cut into my corneas. It was terrifying but vaguely surreal; there was no pain, just sensations of pressure and a primal urge to freeze and not move a muscle.

I was surprised to find they performed this on both eyes right away; the documentation suggested they would do one at a time in case something went terribly wrong, but I wasn't going to quibble because my eyeball was hanging open and I was more concerned about making sure i didn't make things worse.

Overall the procedure took a handful of seconds per eye, though it felt like an age.

After this they ushered me to the second bed. It was an interesting experience; I could still see at that point but everything was cloudy, apparently due to the microscopic bubbles the femtolaser had created.

The second bed was the hardcore stuff: the excimer laser. For each eye they propped open my eyelids and popped on a suction ring to keep the eyeball relatively in place. This was probably the most uncomfortable part, and I later found was the part that left a little bruising.

I was told to stare into the light and not to move while the doctor lifted the flap with a squidgy looking utensil. It was completely painless but silently horrifying to watch my vision distort as my optics bent and shifted with the flap. It also made it difficult to stare in the one spot since the spot kept moving.

The actual excimer laser took literally ten seconds to operate on each eye, during which there was a smell not entirely unlike cooked hair. After that, a bunch of cold water, eye drops and flap-replacement took place. The second eye seemed to require a bit more smoothing out but ultimately everything was fine.

After this I was given the all clear and ushered through another doorway.


IntraLASIK after-effects

I immediately noticed the difference. Having just had my eyes cut up and laserbeamed I expected perhaps to be completely out of it, but I was surprised that I could actually see everything. There was a very strong haze in my vision, but I could see the detail in the surgeon's eyes which would ordinarily be a complete blur without my glasses.

The nurse took me, did a bunch of tests, explained my drop regime, attached some goggles to stop inadvertent touching and suggested strongly that I go home and sleep straight away.

The initial six or so hours are the worst, so it's best to sleep through it. Basically your eyes feel really scratchy like you've got sand in them, but you can't touch or your corneas will most likely fall out (that's my nightmware anyway). They also get very watery and it's generally unpleasant. So go to sleep.

Thanks to some fantastic drugs included in the package, I ended up sleeping until midnight at which point I woke up and took a walk outside for the first time to find something to eat. Greasy pizza outlet was the best I could find, but honestly it was the best greasy pizza I've ever had. It looked good too. So did everything, really.

At this point my eyes still felt somewhat gritty, but there was no pain and most of the haze had cleared up.


The next day

The next day was pretty amazing. Even more of the haze had cleared up and everything was getting progressively better.

Here's a selfie of me looking slightly dopey, but outside without glasses for the first time in forever. You can see a bit of bruising in my left eye if you look hard enough. I'm assured this will heal in a couple of weeks.

One of the side-effects that worried me were “halos” or a “bloom” around bright things, to borrow a gaming term. Particularly things like traffic lights, signs, and (annoyingly) computer screens. This has definitely improved as it's healed, but it's still noticeable on high contrast light points. While you see results instantly, they say it takes about a week for the cornea to heal properly, and this was definitely one of the more noticeable healing issues.

I took a walk through the city the day after and it was quite windy so I definitely noticed some discomfort in my eyes and feel I probably overdid it a little. I bought myself a pair of sunglasses which has been on my list of things to do for ages now and definitely made things better.


LASIK as a programmer

I read a really fantastic overview of the procedure by another programmer who had the procedure done but still wears glasses for working. My surgeon assured me that my vision would be fine for the kind of work I do, but I'm wholly aware that this may not be entirely the case, and certainly won't be forever as presybopia eventually becomes an issue.

Thus far things seem pretty good in terms of working. The main issue now is that where previously focusing near was a zero-effort task, I now have to actively choose to focus on my phone or screens in particular. I can still read tiny ebooks on my phone screen from 10 cm away, though it's not as comfortable as it was before and there's a more sensible point further out.

My main goal is to be able to work at a regular desk with a 27" screen without having to perform acrobatics to do it. Initially there was some discomfort around the "halos" making it more difficult to do much on screens, and this continued for about a week.

I also notice it takes a bit longer to focus "out" from my work. For instance, if someone walks over I'll take a second or two to break out of computer mode and actually engage with them. Often I've instinctively reached for my glasses, so I'm not sure if this is psychosomatic.

The one disappointing thing I've noticed is that I'm having trouble with colour contrast, specifically red on black. This is arguably a terrible design decision to start with, but the super-pretty Monokai colour scheme that (I think) comes default with Sublime Text and that I use for my terminal scheme is uncomfortably difficult to read as a result. I've changed it ot a lighter, more contrasty white-pink, but apparently colour contrast issues are a potential issue, so there you go. I'll update if this changes.

Otherwise everything's great now. Initially I was really worried, but after a week or two it's perfect again.


Overview

Ultimately this was a well-researched but snap decision that I'm totally happy with. There were some initial side-effects that had me a bit worried, and I can't see distance as perfectly as I could with my glasses, but it's pretty damn good, and apparently better than 20:20 anyway.

Would I do it again? Probably. It's a freaky procedure that carries admittedly small risks, and part of me still boggles that I actually went through with it. There may be a touch of post-purchase rationalisation too, but ultimately it's just an amazing experience being able to see properly with my own two eyes.


Two Years On

It's hard to believe it's been almost two years. Life has changed a whole bunch, but for the most part my eyesight is pretty great.

The problems I initially reported are all either resolved or stuff I've gotten used to. I occasionally notice my eyes will get tired and hard to focus on screens, but I imagine that's fairly standard working at a desk all day. My distance vision is still not as perfect as when I had glasses, but again I'm more than happy with it. It's probably something I could improve with glasses, but it's not something I've a need or interest in pursuing.

Another thing I used to notice is that I used to get eyestrain and headaches watching TV for long periods. It only occurred after the surgery that this was due to context switching between my laptop and my TV through my glasses, which no longer happens. So now I don't get nearly as many headaches which is a pretty cool side effect of the surgery.

So overall would I recommend it? Sure. While it's not a complete solution, it's changed my life for the better and I certainly don't miss having to clean my glasses all the time.


Four years after laser eye surgery

It's some four and a half years later and a lot has happened. I've moved to Amsterdam for starters, which is a fair ways from home.

In terms of my eyesight things are still good.

I've noticed that I really need to take care of my eyes while working, otherwise the world is a blurry mess when I step away from my screen after work. This means fairly frequent looking out the window to change focus, and generally taking care not to stare at a screen all day.

In the Amsterdam winter my eyes dried out a lot more than they ever did back in Australia. This was easy enough to fix by making an effort to remember to blink from time to time, but I was on the verge of buying eye drops a few times. They say dry eyes is one of the side effects of the lasik, and I guess it's more of a thing in the cooler climates.

Anyway, that's about it. Just wanted to update things because I know posts like this are valuable when you're considering the procedure. Feel free to reach out on Twitter if you have any questions.

Alchemize stronger & more often

In case you missed it on Twitter, the other day I released Alchemize as a web app, and open sourced the code on GitHub.

Alchemize is a web app which lets you easily pretty-print or minify your source code. It's been a pet project of mine for a couple of years now, and it's really useful as a web developer.

Previously Alchemize was exclusively on the Chrome Web Store, and while it's still available to install as a Chrome app I'm excited to announce it's available online for even easier access.

I've gone to a bunch of trouble to fork and patched the libraries I'm using (a lot of them don't work out of the box) and included them in the NPM manifest so you can easily get to developing. If you're interested, check out the README for instructions.

If you're a web developer and haven't checked it out yet, you should absolutely bookmark the direct link: alchemizeapp.com/app

Polar Defender & js13k

Over the last month I’ve been working on a game for the #js13k game competition.

The concept is fairly simple: make a game in under 13 kilobytes with no external dependencies. The idea is to see what people can come up with on a budget, and it’s awesome to see some of the entries this year.

My game, Polar Defender, is a basic shoot ’em up on a polar coordinate system. It’s heavily inspired by space invaders, except you have to defend various planets from all sides at once. It’s heavily reliant particles and a basic polar trajectory system to provide messy, explodey space fun.

The theme of “elements: earth, air, fire, water” is optional in the contest, but I incorporated it into my level system (an earth-like planet, water planet fire and gas planet). It’s a /little/ contrived, but I think it works well in terms of playability.

I wanted to include a playable level system with a playful narrative since there’s only so much you can do in 13 kb and I felt it would make it a more personal experience. I feel it worked out well, with six levels (including an initial training level) on various planets and varying degrees of difficulty. After early feedback stating it’s too hard to finish in one go, I adjusted the menus to make each level unlockable rather than having to start over, which really improves the gameplay in a casual sense.

Touch input is significantly more difficult than desktop input because I essentially shoehorned the same concept in where it doesn’t really fit. If I had the chance to do it again I would introduce a separate tap-based firing system on mobile.

The tech

Some of the tech I used includes:

  • jsfxr for sound effects, based on Jack Rugile’s blog post.
  • Liberal use of the native Canvas rotate() method.
  • Regular CSS & JS for the menu system.
  • Gulp, Uglify, svgo and a bunch of hand-tweaks to package and minify my codebase.
  • Super rudimentary box-based collision detection.
  • A basic entity/component model through which to extend base sprites.
  • SVG for infinitely customisable graphics. (There’s only four enemy sprites in
    the game, each recoloured and resized as needed.)
  • Procedurally generated starfield & planets.

How to ultra-compress your JS

13 kilobytes is quite a lot in terms of raw code, but also a challenge to meet when including graphics, sound, polyfills and other boilerplate.

Minification of Polar Defender was done by hand and involved a lot of code tweaks.

The ultimate deliverable needed to be compressed into 13 kilobytes of zip file, which is roughly comparable to a gzipped distribution from a web server.

Some of the things I did which aren’t necessarily best practices include:

  • Strip unnecessary properties and pre-compile SVG files into a JSON file to be bundled into the main JS build process. This improves  compression because there’s less junk and the SVG gets compressed in with the JS which presumably improves duplicate string elimination in the zip format.
  • Collapse JSON structures into CSV-like strings that can be reinflated later. JSON objects are super-wasteful in terms of repeated properties, and while compression algorithms are generally pretty good with repeated content, it’s still better to remove the duplicates where possible.
  • Globalise commonly used functions. This isn’t something I’d usually recommend but considering the constraints what the hey. Things like aliasing window to w and Math to m reduces byte-level repetition. Additionally keeping everything in a local scope lets Uglify optimise away long function names.
  • Loose comparison and other sneaky tricks. For instance using 1 for true and 0 for false saves 3 bytes per bool and works in a loose JS equality operation if you’re prepared to ignore JSHint complaining a lot.
  • Reuse everything. I reused a basic set of drawing functions and sprite classes for everything in-game, meaning each new feature was an iteration on an existing one rather than a completely new piece of functionality. See also entity component system on Wikipedia.

Further reading

In addition to my jS13k entry, I’ve got a side-build available in the
Chrome Web Store which you can install and carry around with you. The main benefit is that your scores are stored in the cloud and unlocked content goes wherever you do.

Overall I think it worked quite well and I’m happy with the result. There’s some awesome games submitted so far and I can’t wait to see how everyone goes.

The source code to Polar Defender can be found on GitHub.

Getting moving with HTML5 Canvas

Initialise a canvas

<canvas id="c" width="640" height="480"></canvas>
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');

Note:

  • Width and height determine the canvas size.
  • CSS width and height will stretch the canvas.
  • 2d refers to the rendering context (API). Other options include webgl.

Basic drawing with Canvas

There are several ways of drawing on the 2d drawing context.

  • Rects (rectangles)
  • Paths
  • Text
  • Images

Drawing Rectangles

Rectangles can fill, stroke, or clear an area.

var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');

// Black rectangle ctx.fillRect(0,0,200,200);

// Black outline ctx.strokeRect(200,0,200,200);

// White rectangle (cleared area) ctx.clearRect(50,50,100,100);

See the Pen Canvas Rectangles by Ashley Kyd (@AshKyd) on CodePen.

Drawing Paths

A bit like Logo without the turtle graphic.

var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');


// Draw a triangle ctx.beginPath(); ctx.moveTo(0,100); ctx.lineTo(50,0); ctx.lineTo(100,100); ctx.closePath(); ctx.stroke();

// Draw a circle ctx.beginPath(); ctx.arc(200,50,50,0,Math.PI*2); ctx.fill();

See the Pen Canvas Paths by Ashley Kyd (@AshKyd) on CodePen.

Path Methods

You can use these methods to draw and fill lines onscreen.

Drawing Text

  • The most basic use is ctx.fillText(text, x, y, [maxWidth])
  • Use textAlign=center and textBaseline=middle to center on the specified point.
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');

// Default text ctx.strokeRect(0,0,100,100); ctx.fillText('#brisjs',50,50);

// Centered Text ctx.strokeRect(100,0,100,100);

ctx.font = '12px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle' ctx.fillText('#brisjs',150,50);

See the Pen Canvas Text by Ashley Kyd (@AshKyd) on CodePen.

Drawing Images

Use drawImage(img, x, y) to splat any image or canvas element down into your current context.

var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');

// load an image and draw it in! var img = document.createElement('img'); img.onload = function(){ // Draw the image ctx.drawImage(img,0,0);

// and some text
ctx.font = &#39;bold 40px Impact&#39;;
ctx.textAlign = &#39;center&#39;;
ctx.strokeStyle = &#39;#fff&#39;;
ctx.lineWidth = 2;
ctx.fillText(&#39;MEMES AT #brisjs&#39;,200,40);
ctx.strokeText(&#39;MEMES AT #brisjs&#39;,200,40);

}
img.src = 'http://lorempixel.com/400/400/animals/&#39;;

See the Pen Canvas Images by Ashley Kyd (@AshKyd) on CodePen.

Using Transforms

Transforms adjust the coordinate system your drawing tools use.

var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');

// Example translate ctx.strokeStyle = 'darkgreen'; ctx.strokeRect(0,0,100,100);

ctx.strokeStyle = 'limegreen'; ctx.translate(100,100); ctx.strokeRect(0,0,100,100);

ctx.strokeStyle = 'black'; ctx.rotate(Math.PI/4); ctx.strokeRect(0,0,100,100);

// Make some isometric tiles with setTransform // ash.ms/blog/2012-07-08/isometric-tile-transforms ctx.strokeStyle = 'purple'; ctx.setTransform(1,-.5,1,.5,0,0); ctx.strokeRect(0,200,100,100); ctx.strokeRect(100,200,100,100); ctx.strokeRect(0,300,100,100); ctx.strokeRect(100,300,100,100);

See the Pen Canvas Transforms by Ashley Kyd (@AshKyd) on CodePen.

  • Transforms are useful for when you have a self-contained item and want it to be able to move.
  • For more information, I've previously written on transforms for isometric games.

Animation

setInterval is so 1995. Use the requestAnimationFrame method to call back before the next screen repaint.

var gameLoop = function(){
    // Do stuff
    requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);
  • requestAnimationFrame won't fire if the browser isn't painting, for instance in another tab or minimised.
  • Unit movement should be calculable as a vector, otherwise everything will stop or slow down with the render process.

Let's get moving

This demo shows the basics of animation. The sine wave is calculable based on the current time.

var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');

function sineWave(){ var yPos = Math.sin(Date.now() / 500 ) 100; ctx.fillRect(0, yPos, 10, 10); }

var gameLoop = function(){ ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.save(); ctx.translate(150, 150);

// Let&#39;s draw some sine waves
for(var i=0; i&lt;10; i++){
    ctx.save();

    // pi</em>2 radians == 360°
    ctx.rotate((i/10)<em>Math.<span class="caps">PI</span></em>2);
    sineWave();
    ctx.restore();
}

ctx.restore();
requestAnimationFrame(gameLoop);

}
requestAnimationFrame(gameLoop);

See the Pen Canvas Animation by Ashley Kyd (@AshKyd) on CodePen.

Particles

Particles are one of the most useful things you can have in a 2D game.

See the Pen Canvas Particle Generator by Ashley Kyd (@AshKyd) on CodePen.

  • Particles can be anything you want, but gradients are slow to draw so you'll need to cache them.
  • You can plug in one of many physics engines from NPM, but it's easier to accelerate out from a center point.

Polar Defender (my entry into the 2014 #js13k)

js13k is a month-long game competition to make a game in under 13 kb.

  • Polar coordinates & .rotate() make it east to do a radial game.
  • SVG sprites: scalable, re-colourable assets.
  • "Everything's a particle" approach simplifies collision detection.
  • jsfxr for 8-bit sounds.
  • Using a bunch of Unicode emoji as game assets (gotta save space).
  • Code on GitHub

Play Polar Defender.

Where to go from here

There's a bunch of stuff already out there to make your life easier. Here's some of my favourites:

  • Pick a game engine (or do it by hand)
  • NPM is a treasure trove of amazing things
  • freenode/#bbg – browser based games
  • Learn about Juice in a talk by Martin Jonasson and Petri Purho