Aww, my 8-week sabbatical is now over. I wish I had more time, but I feel I used it well and there are certainly lots of Firefox bugs I want to work on too, so perhaps it’s about that time now (also, it’s not that long till Christmas anyway!)
So, what did I do on my sabbatical?
As I mentioned in the previous post, I took the time off primarily to work on a game, and that’s pretty much what I did. Except, I ended up working on two games. After realising the scope for our first game was much larger than we’d reckoned for, we decided to work on a smaller puzzle game too. I had a prototype working in a day, then that same prototype rewritten because DOM is slow in another day, then it rewritten again in another day because it ends up, canvas isn’t particularly fast either. After that, it’s been polish and refinement; it still isn’t done, but it’s fun to play and there’s promise. We’re not sure what the long-term plan is for this, but I’d like to package it with a runtime and distribute it on the major mobile app-stores (it runs in every modern browser, IE included).
The first project ended up being a first-person, rogue-like, dungeon crawler. None of those genres are known for being particularly brief or trivial games, so I’m not sure what we expected, but yes, it’s a lot of work. In this time, we’ve gotten our idea of the game a bit more solid, designed some interaction, worked on various bits of art (texture-sets, rough monsters) and have an engine that lets you walk around an area, pick things up and features deferred, per-pixel lighting. It doesn’t run very well on your average phone at the moment, and it has layout bugs in WebKit/Blink based browsers. IE11’s WebGL also isn’t complete enough to render it as it is, though I expect I could get a basic version of it working there. I’ve put this on the back-burner slightly to focus on smaller projects that can be demoed and completed in a reasonable time-frame, but I hope to have the time to return to it intermittently and gradually bring it up to the point where it’s recognisable as a game.
You can read a short paragraph and see a screenshot of both of these games at our team website, or see a few more on our Twitter feed.
What did I learn on my sabbatical?
Given how positive that all sounds, why isn’t it ready? These are the top bugs I encountered while working on some games (from a mobile specific viewpoint):
WebGL cannot be relied upon
WebGL has finally hit Chrome for Android release version, and has been enabled in Firefox and Opera for Android for ages now. The aforementioned CocoonJS lets you use it on iOS too, even. Availability isn’t the problem. The problem is that it frequently crashes the browser, or you frequently lose context, for no good reason. Changing the orientation of your phone, or resizing the browser on desktop has often caused the browser to crash in my testing. I’ve had lost contexts when my app is the only page running, no DOM manipulation is happening, no textures are being created or destroyed and the phone isn’t visibly busy with anything else. You can handle it, but having to recreate everything when this happens is not a great user experience. This happens frequently enough to be noticeable, and annoying. This seems to vary a lot per phone, but is not something I’ve experienced with native development at this scale.
An aside, Chrome also has an odd bug that causes a security exception if you load an image (on the same domain), render it scaled into a canvas, then try to upload that canvas. This, unfortunately, means we can’t use WebGL on Chrome in our puzzle game.
Canvas performance isn’t great
Canvas ought to be enough for simple 2d games, and there are certainly lots of compelling demos about, but I find it’s near impossible to get 60fps, full-screen, full-resolution performance out of even quite simple cases, across browsers. Chrome has great canvas acceleration and Firefox has an accelerated canvas too (possibly Aurora+ only at the moment), and it does work, but not well enough that you can rely on it. My puzzle game uses canvas as a fallback renderer on mobile, when WebGL isn’t an option, but it has markedly worse performance.
Porting to Chrome is a pain
A bit controversial, and perhaps a pot/kettle situation coming from a Firefox developer, but it seems that if Chrome isn’t your primary target, you’re going to have fun porting to it later. I don’t want to get into specifics, but I’ve found that Chrome often lays out differently (and incorrectly, according to specification) when compared to Firefox and IE10+, especially when flexbox becomes involved. Its transform implementation is also quite buggy too, and often ignores set perspective. There’s also the small annoyance that some features that are unprefixed in other browsers are still prefixed in Chrome (animations, 3d transforms). I actually found Chrome to be more of a pain than IE. In modern IE (10+), things tend to either work, or not work. I had fewer situations where something purported to work, but was buggy or incorrectly implemented.
Another aside, touch input in Chrome for Android has unacceptable latency and there doesn’t seem to be any way of working around it. No such issue in Firefox.
Appcache is awful
Uh, seriously. Who thought it was a good idea that appcache should work entirely independently of the browser cache? Because it isn’t a good idea. Took me a while to figure out that I have to change my server settings so that the browser won’t cache images/documents independently of appcache, breaking appcache updates. I tend to think that the most obvious and useful way for something to work should be how it works by default, and this is really not the case here.
Aside, Firefox has a bug that means that any two pages that have the same appcache manifest will cause a browser crash when accessing the second page. This includes an installed version of an online page using the same manifest.
CSS transitions/animations leak implementation details
This is the most annoying one, and I’ll make sure to file bugs about this in Firefox at least. Because setting of style properties gets coalesced, animations often don’t run. Removing display:none from an element and setting a style class to run a transition on it won’t work unless you force a reflow in-between. Similarly, switching to one style class, then back again won’t cause the animation on the first style-class to re-run. This is the case at least in Firefox and Chrome, I’ve not tested in IE. I can’t believe that this behaviour is explicitly specified, and it’s certainly extremely unintuitive. There are plenty of articles that talk about working around this, I’m kind of amazed that we haven’t fixed this yet. I’m equally concerned about the bad habits that this encourages too.
DOM rendering is slow
One of the big strengths of HTML5 as an app platform is how expressive HTML/CSS are and how you can easily create user interfaces in it, visually tweak and debugging them. You would naturally want to use this in any app or game that you were developing for the web primarily. Except, at least for games, if you use the DOM for your UI, you are going to spend an awful lot of time profiling, tweaking and making seemingly irrelevant changes to your CSS to try and improve rendering speed. This is no good at all, in my opinion, as this is the big advantage that the web has over native development. If you’re using WebGL only, you may as well just develop a native app and port it to wherever you want it, because using WebGL doesn’t make cross-device testing any easier and it certainly introduces a performance penalty. On the other hand, if you have a simple game, or a UI-heavy game, the web makes that much easier to work on. The one exception to this seems to be IE, which has absolutely stellar rendering performance. Well done IE.
This has been my experience with making web apps. Although those problems exist, when things come together, the result is quite beautiful. My puzzle game, though there are still browser-specific bugs to work around and performance issues to fix, works across varying size and specification of phone, in every major, modern browser. It even allows you to install it in Firefox as a dedicated app, or add it to your homescreen in iOS and Chrome beta. Being able to point someone to a URL to play a game, with no further requirement, and no limitation of distribution or questionable agreements to adheer to is a real game-changer. I love that the web fosters creativity and empowers the individual, despite the best efforts of various powers that be. We have work to do, but the future’s bright.
17 Replies to “Sabbatical Over”
Might I suggest http://impactjs.com/ejecta to boost performance of html5 games on IOS. There is also ejecta-x for android but it’s not well tested.
See bug 625289, bug 649247, bug 537143, and bug 774655 re: transition starting.
I guess that means welcome back! o/
To quickly respond to your WebGL comments:
– WebGL context loss has little to do with what you do with your WebGL context, and is more about random things that happen on your hardware. To give just one example, on a Windows XP machine, locking the screen causes all Direct3D devices to get lost, which translates into loss of WebGL contexts.
– You absolutely can draw a *same-origin* image onto a canvas, then pass that canvas to WebGL.texImage2D, in both Chrome and Firefox, but avoid doing that with file:// URIs as the origins for such URIs are implementation-dependent (i.e. a browser might consider all file:// URIs to be their own separate origins, making this fail). Instead, serve your local directory over http (python -m SimpleHTTPServer). For cross-origin images, if you control the HTTP server, you can use CORS to serve them as if they were same-origin (both Chrome and Firefox support that).
Oh and re: 2D canvas performance: canvas 2D is an inherently hardware-unfriendly API so while browsers try hard to make it run not too slow, if performance matters, prefer WebGL.
A couple of quick response responses:
– I understand what causes a lost context and what it is, my problem is that it happens far too often, at least in Firefox on Android. You have to deal with lost contexts in native too, but on Android at least, you can pretty much guarantee it isn’t going to happen while your app is in the foreground and the phone is unlocked. On the other hand, using WebGL, it can easily occur in this situation. Obviously you should never count on it not happening, but it’s a crappy experience when someone is actively playing a game and then it has to pause and reload all its assets because the context was lost for seemingly no reason. There must be something in our behaviour that’s causing it to happen more regularly than it should.
– I know you can do this, and I do it in Firefox fine 🙂 For whatever reason, the exact same code that works in Firefox spawns a security error in Chrome (and it isn’t the local-file case, this happens from a live site and with the appropriate command-line argument specified too). I’ll be working out test-cases for the mentioned bugs.
– Agreed on canvas, but people (just me?) have come to expect that using it in a particular style is fast (i.e. clear screen, draw everything using drawImage, done) – I think this should be fast, but it appears it isn’t quite fast enough. It’s no good to say to people ‘just use WebGL’. WebGL is an awful API and it does nothing to shield you from the multitude of device-specific bugs/quirks that you’ll almost certainly trigger.
I would also like to respond on “using WebGL doesn’t make cross-device testing any easier and it certainly introduces a performance penalty”.
WebGL tries hard to be very conservative with respect to exposing device-specific functionality. For example, you have to explicitly query an extension before you can use it; many extension proposals have been turned down because they were not worth the portability degradation that they incurred; many other extensions and parts of the spec have been carefully worded to remove the implementation-defined behavior present in their OpenGL counterparts, often by choosing to offer only the subset of the OpenGL functionality that could be fully specified and portable; all of WebGL including extensions is covered by conformance tests and untestable things are generally considered a non-starter for WebGL. In these respects, WebGL is really different from OpenGL. This means that a lot of the cross-device testing work should be taken care of for you by the browser’s WebGL implementation, in exchange for sticking to the subset of GL functionality that is exposed by WebGL.
Regarding performance, did you measure a large performance degradation on some use case? The extra validation that the WebGL implementation has to do does have a cost, but all is done to ensure that it doesn’t become large on practical use cases; bug reports welcome!
Sorry, I think I could have worded what I was saying more carefully. Sure, the subset of GL that is WebGL means you are less likely to use a vendor-specific extension, but then you could just as easily use plain GLES2 and not use any extensions. What I meant is that, even within this subset, vendor behaviour differs significantly enough that you still need to test on a number of platforms. Differing behaviour, differing bugs and differing performance profiles means that this is something you will pretty much always have to do, so I don’t think it really eases the workload significantly. The point on there being a performance penalty was just to demonstrate how it looks from a developer perspective; your workload isn’t eased, and it’s slower (even if it’s negligibly so). I wouldn’t try to sell the web as a platform to a games developer because WebGL exists, I’d sell it on the fact that not only does WebGL exist, but you have an amazing and expressive layout engine that you can use in tandem with it.
DOM performance is surely a PITA, we have heard (and probably known) that for a long time. It’s apparently the main reason why SVG is really slow in Firefox (I hear it’s way faster in Chrome), and with the DOM tree being at the heart of all documents, it’s surely a pain for a lot of apps. We definitely need to work on getting that fixed.
Better DOM performance would be such a huge win. So much interesting work is being done with animated SVG that just doesn’t work very well in FF. Shouldn’t this be the focus of the ‘snappy’ initiative I’ve seen in other blog posts?
Did you file bugs on the performance issues you found?
Yes, or they existed, for the most-part. It’s hard to file things for the ‘this is generally bad’ cases though, I still need to work to break them down and provide test-cases.
Chrome/Blink has some plans including the “touch-action-delay” CSS property to improve touch latency. Here’s a (possibly out of date) design document:
This is interesting, but I more just mean that there’s a significant lag between event delivered and event processed in Chrome that isn’t there in Firefox – if I move a sprite around on a canvas in response to touch events, it tracks my finger a lot better in Firefox than in Chrome. This seems to be aside from performance, as it tracks better in Firefox even if the page is performing noticeably worse. It’s like there’s a large event buffer in Chrome that means that your touch events are only processed several frames after they’re received.
What’s the Chrome bug number for the issue you found with loading and using images from your own domain?
I still need to get test cases together for the Chrome bugs, so no bug number yet. Soon, honest!
Thank you for writing this! I’ll be interesting in any followups as you continue development on the other, more ambitious game.
I just wanted to say: Welcome Back!