Saturday, 26 January 2013

Making of: Parsley State

Parsley State

A 10k intro made for DemoJS. (link)

Planning

Following up the disapointment of Cyboman 5 placing so low at Stream i decided to try again with a new javascript intro. I had also recently finished work on the "Under a Seering Sky" javascript game. Another disapointing competiton result, this time from Atparty wild competition. The new target event was DemoJS, a demoparty in Paris focusing on javascript and browser technologies. DemoJS popped up last year sponsored by Mozilla during their 2011 campaign to get more demos for the browser with a few events across the world. Competition would probably be harder but atleast the attending audience would more likely know what they are voting on. Aimed again for pure canvas, no webgl. There are still lots of things on the canvas specification that folks don't seem to be using that much, i wanted to explore that a bit.

There were 4 categories at DemoJS: 1k, 10k, demo and wild. 1k is mostly for 1 trick ponies and it's typical playground for webgl experiments, not what i was looking for. Demo would require a dedicated graphician to work with, so i also set it aside. Wild would have been great for something similar to "Under a Seering Sky", but i was running out of time to make two prods. 10k seemed more appropriate to aim for. So now that i knew the target, what i was missing was a good tune with small size. Fellow TPOLM'er Kaneel was recruited for the job. Our aim was to do a haterztro, sending joyful fuckings to all the folks that enjoy talking shit about us whatever it is we do. Inspiration from the epic B.o.B. track Haterz Everywhere popularized by machine drum on lazy sunday radios of old.



Research and development

Focusing on the 10k category i did some research on available sound apis and concluded we had 4 options to chose from for our plan to world domination to have appropriate sound:
1) bytecode music. Has the advantage of taking much less size, ideal for 1k and 4k. Has the disadvantage of always sounding like crap made my coders fooling around.
2) sonant-js, a javascript port of a softsynth some other sceners been using for native and web 4k intros. Has the advantage of a gui, useful for letting the musicians do the music. Has the disadvantage of generaly sounding overly simplistic. Great for simple pads and melodies, but that has all been done before to exhaustion.
3) ahx replayer, a javascript replayer of the famous ahx amiga sound format. Has the advantage of a well tested tracker gui and established format. Great fun for chiptune / oldschool fetishists.
Has the disadvantage of the replayer being unstable and relatively large in size.
4) jsmodplayer. Has the advantage of the musician being able to use a trackers interface to compose the track and the replayer been around longer then the other options so more likely to be something stable. Has the disadvantage of easily getting too big in size if the musician is careless with selecting his samples and patterns.

In the end we decided to go for AHX. Kaneel felt motivated to try some oldschool chiptune sounds despite having had a little trouble installing the amiga emulator and learning the tracker. I had to crunch any of the players anyways so as long as it sounded good any of the options 2) 3) or 4) would be ok. The choice of AHX had it's drawbacks: mild-high learning curve to learn the format, it's replayer actually emulates some amiga opcodes and can be quite unstable when you're trying to debug things in javascript debugger. But it had sound support for both the webkit audio and mozilla sound api, which is nice, the more browsers supported the better.

Guidelines

tpolm style 1 week before the event we started having some test tunes we were both happy with. We did a couple of interactions of syncing effects and reworking the track a bit. Unconsciously we morphed the original haterztro into something more TPOLM like.

We tried to follow a few basic TPOLM guidelines:
1) being informative
2) featuring tunnels
3) greeting TPOLM
4) being short and to the point


Information on Parsley was added. Unfortunately we had to cancel the second point of compliance with TPOLM technology guidelines. Even though we actually had a tunnel effect working, it was running in much too low framerate to be worth releasing. Greetings featured TPOLM. We focused on the theme keeping it short and not boring.

So the guidelines were more or less followed, further consultancy with our vintage superhero Antti "fthr" Jadertpolm confirmed the authenticity of our alignment. We spent some more iterations polishing colors and lyrics.

Travelling

ryanair At some point in time i was spending a bored evening and checked flight prices through ryanair to Paris, it was quite cheap to go from Porto, which i would be visiting at the time, so i booked the tickets on impulse. From that point on i really had to finish something decent to present at the event despite starting to run out of time.

Then, suddenly, just a few days before the event, i heard of a planned air traffic controlers strike being announced for the dates of the event. Confirmed the clash at the Ryanair website, they only mentioned to stay tuned for more information. Unsure if the flights were still flying i carried on polishing the intro with the help and consultancy from kaneel and fthr.

Then, just as suddenly, Portugal lost the semi-finals match of the euro to Spain.

Then, even more suddenly, the air traffic controllers strike was canceled and all flights were announced to be back on schedule. Hooray! The plan to become hopsters in Paris was reinstated once more. I informed the family, swapped meet up information, set my alarm clock and packed my computer bag to go to Paris the next day.

At this point the intro still had some small things needing polish and we were deciding between an easter egg secret part or adding some vector graphics to fill up the remaining space of the intro. We had 500 bytes left to fill up with something.

I met up with Kaneel on Friday afternoon after a long travel without food and we babysitted his daughter for a while, then went shopping for beer and took her for a walk in the park before another party visitor and the babysitter showed up. The afternoon was going by quite fast, the beers also, and we hadn't even made it to the partyplace yet. But it was now just a couple of metro stops away! We exited the metro at Bastille and found our way to ISART, the partyplace.

Party coding

Upon arrival we immediately met some other foreigners and instead of working we continued our hopster beer adventure through the night. After too many beers we finally decided we should probably try to get the intro finished instead of just getting drunk.

We only needed to fix some syncs in the greetings and add the coat of arms graphics, should be easy to do. Right?

Getting a place to setup was easy, everyone was watching a screening of Moleman 2 while we wrestled with the WiFi... It was supposed to exist but it didn't. We needed internet to convert the SVG into canvas code, so we bothered the organizers. After a few hours and a few more beers the internet was working again and a converted version of the SVG was now in place. The intro had just bumped from 9k to 12k. Let the optimizing begin!

Kaneel was playing demo VJ with the big screen while i tried out a few optimization tricks. First manually removing the weird animation junk code from the svg conversion. Then removing some decimals from the bezier curve data. Then removing all decimals from the bezier curve data. Then removing some of the bezier curves themselfs. Just had to make sure the quality was still acceptable.

At some point Kaneel had to leave for home and i took the wonderful opportunity to get some food. Returning to the partyplace most of the people had already gone to sleep. Our intro was still at 11k so I carried on optimizing some more. Next step was removing functionality from the AHX replayer that wasn't beeing used by the track and hacking some functions to generate data instead of using the lookup tables. Still too big.

Compress me beautiful

Re-watched p01's talk on creative coding and size optimization to remember a few tricks. Replacing all Math.floor calls with 0|, dirty trigonometry, function hashing, etc. Function hashing called for some more wrestling with closure compiler to get the intro working again.

After a long night of trying several updates and reverts i was still 500 bytes too big. Trying out JsExe instead of PNGinator would give some better results but still always 40 or 80 bytes too big from the 10240 limit.

I started comparing the code directly with the closure compiler version. I noticed that some optimizations i would do would size down the closure compiled version significantly but have little impact on the final .PNG size. This can be explained by common compression entropy, the compression takes heavy advantage of repeating elements, so the more and longer repeats you have the better it's ratio of compression. When you replace the long repeats for smaller versions you are doing work the compressor would do, and probably doing it in a less optimized way, so you end up losing compression ratio, making your optimizations worthless.

Ofcourse i could just cut the graphics out of the intro and go to sleep, but that would be cheating! I took a couple of breaks to refresh myself and went back at it. But i was still at a dead end, trying some new desperate hacks and the best result i could still get out fo JSexe was 10260. I decided to bug Gasman, asking for his opinion if i should keep trying to optimize the closure compiler to the max hoping that eventually the final size would start also decreasing or try to rearrange data in hopes it would pack better. Gasman took a look at my code and paused at the AHX track loader. I been loading the track by including a base64 encoded version of the track and decoding it on load. Gasman had the idea to replace the base64 with an url encoder. The string would no doubt be longer but the PNG compression should compress it better, also we would be able to replace the 2 functions related to the base64 utf8 decoding with an eval().

Gasman went off to write a binhexjs.rb while i forked the sourcecode and aimed for some heavier closure optimization. Half an hour later we merged both our efforts and the final size was now around the 9700 bytes. Success!

Idling with style

Entry finished and submitted! Now all that was left was one whole day of doing a bucketload of nothing.

Saturday morning was completely uneventful.

Saturday afternoon had some interesting talks, most of them in French sadly enough for us poor foreign visitors. Went outside for some beers with old scener friend Flod who was briefly visiting the partyplace. Bastille was of the centers of the Parisian gay parade happening that day, so everything was packed with colorful people and rainbow mayhem. We eventually found a bar and after a couple of beers headed back to DemoJS.

The rest of the afternoon was spent socializing with other foreigners and making some new friends. Mostly drinking beer, explaining the scene to a new musician and waiting for the compos to start. DJ Pie was playing a set but we somehow managed to miss it.

Compos

The organizers came outside to warn us the compos were about to begin. "Everybody in, everybody in, the show is about to begin."

First up were the 1k. Plenty of entries, most of them without music but still mildly interesting. The last to be shown was Matraka, a joint work of p01 and 4mat, blowing all the competition into second league.

matraka



Next the 10k, featuring only 3 entries. The first was Reborn by tmp & Adinpsz, a simple terrain generator with some 2d trees, nothing fancy but people seemed to like it. Second up was a co-op by Rift and DSS titled mwwnwormer, a dark side of the moon raytracer with some music using jssonant. The graphics looked pretty good and it quickly became clear they would win the compo. Last up was our entry, Parsley State by TPOLM, there were a couple of bugs showing, but people didn't seem to notice and veemently applauded when it ended. I was pretty confident we would get second place at this point.

Still left to show was the wild compo, only 4 entries, one of them didn't really work due to an unexpected update on chrome. The best one was clearly the Turbo Out Run clone game, even if it didn't have sound.

Last but not least was the demo compo. Not many entries, only 5. A couple of compo fillers and fast made prods. The most polished entry seemed to be BIGintro by The Matadors who oddly to me ended up placed 3rd in the final results. The democompo winner being Burnt by Games From Mars, which was nice but clearly rushed for the compo.

After a quick online voting session final results were presented with a little closing ceremony. We were granted the last place and asked to come on stage. :( I thanked the audience with an important message from the moomin: "Remember to use more parsley when you cook!"

Aftermath

The remaining night was dedicated to uploading the entry online, decompressing and getting some sleep. Next day was travelling back home day. Spent some airport time getting started on this making of report and figuring all the things i had left to do when i arrived home.

Was happy to notice people on pouet seemed to be thumbing up Parsley State. Nice not to get hated on a new release for a change. Even though we still got last place in the compo.

Next day i uploaded the source code to github.

This report was originally posted at The Herring and xDA.

No comments:

Post a Comment