Thursday, August 30, 2012

sounds good: hacking through the jungle of html5 audio

Audio is a more difficult thing for computers to get right. Even the humble(?) task of providing low-latency (i.e. quick response) audio clip playback is a challenge for some systems (I saw this first with using the minim library in Processing). And I'm talking basic audio, not heavily processed stuff, or even strictly "real time"-- enough so that in a game you can easily tell what onscreen event triggered the noise, not that you can base a "Guitar Hero" clone off of it.

tl;dr: Introducing lowLag.js Sounda simple wrapper for low-latency, high-compatibility, html5-friendly audio. 

It gives you three comands: init(), load(), and play(), and provides nice speedy sound across most browsers. See its official homepage or its github page for more.

The background:

I asked my buddy Darius Kazemi if had a recommendation- he helped Subatomic Studios make an HTML5 port of their iOS game Fieldrunners (You might want to his New Game 2011 Post Mortem on the porting process) and his quick answer was
Soundmanager2 is the standard. Definitely use that.
SoundManager 2's turned out to be a decent recommendation, thanks in part to the online documentation: even though the primary download seems to be a whole source tree, you just need to pluck a few files out for use, as outlined on the template example page (the API and Demo code page was also helpful.)

So SoundManager2 (with its two-fisted Flash-object with html5 fallback) worked on most browsers, it had much lag, especially on Chrome. I mentioned this to Darius and he told me that on chrome he usually goes straight to the Webkit Audio API, and sent me his example page.

So now I had 3 different techniques for audio. I made 3 test pages: one for the <audio> tag cloning technique, one using soundmanager2, and one using webkitAudio. Each page has a high pluck sound button, a low pluck sound button, and a button to play both at once.

Anyway, the webpage shows the detailed work I did in finding out what techniques worked best in which browsers, and then how I wrapped those in a single easy-to-use wrapper js object. I know I'm going to use it on upcoming game projects.

Enjoy!

Thursday, August 16, 2012

simple labeled percentage bars in CSS

So at work the spec called for a percentage complete bar... one of my coworkers came up with something like the following (I reinvented the CSS, but the idea was his)

The css and HTML is a bit more fiddly than I like, but I've seen worse:

<style>
.percentage {
width:200px;
height:20px;
background-color:#CCCCCC;
text-align:center;
color:black;
position:relative;
font-family:tahoma,arial,sans-serif;
}
.percentage .bar{
position:absolute;
top:0px;
left:0px;
overflow:hidden;
width:100px;
}
.percentage .inner{
width:200px;
background-color:#000055;
color:white;
}
</style>

<div class="percentage">
<span class="val">50%</span>
<div class="bar">
<div class="inner"><span class="val">50%</span></div>
</div>
</div>


The basic idea is to have 3 nested divs. The outer div has a fixed width and the percentage, with a dark text color. The middle div is set to the desired visible width of the bar (multiplying the current percent value times the width of the outer bar, divided by 100) It has its overflow set to hidden, so that the final inner div (set to the full width of the outer bar) displays its darker shade, lighter text for only as far as it needs to-- then the duplicate text of the outermost div shows behind it. The innermost bar obviously doesn't have to be a set color, it can be a repeating background image or whatever.

I then added a demonstration of an animation technique. As far as I know, there's no easy way of knowing how far along a jQuery animation is (for updating the % text) so I used setTimeout with a function that incremented the value and then called itself (in something a bit like tail recursion) until finally the displayed value was the same as the goal value.

(Wrapping this as a jQuery object or applying it to a specific need is left as an exercise for the reader...)

So that was the UI side of things. On the UX side, I thought we had a problem. At work we are introducing a point-and-level system and were using the progress bar to to show the user's current level along with how the points total and how long until the next level. The display for that was something like this:
 Level 3 was achieved at 700 points, and at that point I had 850. Take a look and answer this question: about how many points do I need to be at Level 4? 




To me it looks like Level 4 is around 2500 or so -- the bar indicates that I'm only 1/3 of the way there. But that's not the case. Level 4 is 1200 points, and what the bar is showing me is that I'm about 1/3 of the way up from when I hit Level 3.

So, I found that counter-intuitive, and unlike how other point systems (like the unlock system in the game Just Cause 2) do things. Instead, I thought this display was more clear:

Here, it looks like I am most of the way to the next milestone, which is in fact the case.

An alternate display might be something like:

I think this does a clearer job than the first example of showing Level 3 as a baseline, and that Level 4 as what is being worked to.

The jury is still out on which display we'll use. It deserves some user testing, but I'm pretty sure either of the alternatives are a better form of data visualization than the original setup.

Friday, August 10, 2012

js singleton boilerdish

(Improved version as of early 2014)

This is mostly just for future reference for myself (hence the cutesy name "boilerdish" that I can Google on...)

There are several patterns for making JS objects. One of my favorites is:

var someObject = new function(){
    this.someVariable = undefined;

    this.init = function(){
        alert("started up");
        someObject.someVariable = true; //don't rely on meaning of "this" too much!
    };
}

$(document).ready(someObject.init);

(Also sometimes I like to throw in the diagnostic logging stuff I wrote about here)

Caveats: this pattern doesn't provide much "privacy" for members, so it's not good for defensive coding. It's also kind of assuming a "singleton" use, but I find that pretty common and useful. (Also, given how frustrating "it depends on what this 'this' is this time" can be, the fall back of being able to refer to  "someObject.someVariable" out of the global space, rather than relying on delegates so that something like "this.someVariable" can work, is extremely helpful...) It does mean that there can just be a single entry in the generic Window namespace, which is always a plus.

Monday, August 6, 2012

processing.js porting gotchas

I've been porting entries from my Java Advent Calendars (both the 2009 and 2011 editions) into HTML5, via the wonder that is Processing.js. The original Processing (a Java based IDE and API, geared at students and artists) is amazing enough -- I really credit it with enabling me to make some really fun stuff in folks' browsers (not to mention effortlessly generated native Windows and Mac apps) but it feels like applets are kind of on their way out. So Processing.js allowing what is basically straight Java code to be run as Javascript (using the Canvas object) is super amazing. I don't know what black magic preprocessing they do to get 90% of my Java classes to work in a Javascript context, but it's great work, and less problematic than I thought.

Still, there are lots of gotchas, so here's my list of things to look out for, as determined by my personal experience. (Which involved some Processing code against the older version of Java that didn't use typed collections, and might not be using the latest and greatest release of Processing.js.)

Environment Gotchas

  • Speed. Some of my code that runs fine as an applet runs a bit slow in the browser, or at least with  some browsers javascript engines. I haven't yet isolated what operations slow things the most, but it seems like the line drawing isn't as quick.
  • Error messages. When you're coding up new stuff, the error messages can be a bit opaque, and generally don't have the line number of the original .pjs file. 
  • Chrome and running things locally. Chrome tends to balk at running code loaded locally from the file system. (Might be a good excuse for that Python webserver trick I mentioned earlier.)
  • 3Dness. One of my first attempts at porting a simple 3D app ended in failure, I haven't researched if there's an easy way around this.
Coding Gotchas
Most of the coding problems I've run into involve collections.
  • Collections & Inheritance. I had a big problem with this early-on, with an overly ambitious engine project I was doing for the Boston HTML5 Gamejam. It used a lot of object subclassing, and it seems like items in a heterogeneous collection of subclasses weren't being cast to quite the right types when it came time to call function names that they had in common.
  • The .removeAll() function for Collections is late to the party. I'm not sure if later version of the library fix this, but it was a known issue.
  • HashSet is not implemented. I liked to use HashSets for collections where order didn't matter but I wanted to be able to remove specific member items efficiently. ArrayList is a pretty good substitute.
  • In the bad old days of Java, before it's implementation of "foreach", you had to use iterators, and the best way to remove an item if you were in the loop itself was through the Iterator.remove() method (which removes it from the container the iterator is based off of.) .remove on the Processing.js iterator doesn't seem to propagate up to the main collection. (Combined with the .removeAll() lack, this was a little annoying.)
  • Apparently in Processing,
    ArrayList<SomeClass>things = new ArrayList<SomeClass>();
    is fine, but Processing.js gets confused, and wants spaces before the collection name. (For a while this led be to be unfairly pessimistic about the porting from Java, because the error message wasn't clear, and I was writing lines like that without spaces all over the place.)
So despite this list, in practice I've been increasingly impressed with what Processing.js can do. It's an awesome set of training wheels for people looking to go from Java to Javascript, and sometimes I wonder if it might not be a solid tool in its own right, as crazily ambitious as "run Java classes in Javascript" seems.

Followup: one other class of error involve java being strict about its types, but js being loose:

 int spotToYcoord(int s){
     return s / 3;
   }
This returns int values only in Java, but the equivalent of floats in javascript. (In this case the fix was to explicitly return floor(s/3) instead.

Wednesday, August 1, 2012

png compression for windows

Previously I wrote about ImageMagick, a Mac-only wrapper for several different near-lossless image compression programs. Today I discovered PNGGauntlet which is a PNG-only version for Windows. (I think it will also convert JPGs etc to PNGs, which might not be what you're looking for.