Objective-C to JavaScript

In bringing Cut the Rope to a new platform, we wanted to ensure we preserved the unique physics, motion, and personality of the experience. So early on we decided to approach this game as a “port” from the native iOS version (rather than a rewrite). We kicked off the project with an extensive investigation of the original Objective-C codebase. Turns out it’s a big and complex game. The native iOS version consists of about 15,000 lines of code (excluding libraries)! The most complex parts of the codebase are the physics, animation, and drawing engines. They’re complex on their own, but made even more so by the fact that all three are tightly connected and highly optimized.

It was a daunting task: get this code into a browser while maintaining the unique personality and incredible quality that gamers are accustomed to. To accomplish this, we bet on JavaScript.

In the past, JavaScript had a reputation of being a slow language. Frankly, that reputation was initially valid. Older JavaScript engines were designed for simple “scripting” kinds of tasks (hence the name). Today, however, JavaScript engines have been highly optimized. With features like just-in-time compilation, JavaScript now can execute at near native speeds.

Beyond that, we know that coding for JavaScript is different from - and requires a different kind of mindset than - coding in a compiled language. As we ported the game from Objective-C, we knew we would need to embrace the task of making these sorts of changes and optimizations.

One obvious example was the lack of structs in JavaScript. Structs are lightweight aggregations of related properties. It’s easy to use a JavaScript object to hold a set of properties, but there are important differences between that approach and a proper struct. The first difference is that structs get copied whenever they’re assigned to a variable or passed to a function. So, a function written in a compiled language like Objective-C can modify a struct passed as a parameter without affecting the value in the caller. Even within a function, assignment of a struct to a different variable will copy the values. JavaScript objects, on the other hand, are passed by reference. So when a function modifies an object parameter, the changes will be visible to the caller.

An easy way to mimic the nature of structs is to create copies of JavaScript objects for assignment or parameter passing. In native languages there is typically very little overhead to using structs. Creating an object in JavaScript is much more expensive, so we had to be very careful to minimize the number of allocations. Particularly on assignments, whenever possible we tried to copy individual properties rather than creating entirely new object instances.

Another example is the object oriented nature of the Objective-C codebase. In lieu of traditional object-based inheritance, JavaScript offers prototypical inheritance, inheritance based on the Prototype property. This is a highly simplified form of object inheritance that really isn’t compatible with a traditional object oriented language like Objective-C. Fortunately, there are a variety of class libraries that can help you write object-oriented programming (OOP) style code for JavaScript; we made use of a very simple one that was written by John Ressig (of jQuery fame). (Note that ECMAScript5, the specification for the newest version of JavaScript, also includes some support for classes but we opted not to use it in this port due to our lack of familiarity with that version of the language coupled with our aggressive development schedule).

In addition to porting from Objective-C to JavaScript, we also needed to port our graphics code from OpenGL to the HTML5 Canvas API. Overall, this went really smoothly. Canvas is an amazingly fast rendering surface, especially in a browser where that API is hardware accelerated (like Internet Explorer 9).

An example of drawing the ropes with aliased lines using the canvas API.

Surprisingly, we encountered a few areas where the Canvas provides more functionality than does the version of OpenGL ES that was used by the mobile version of Cut the Rope. One example is drawing anti-alias lines. Drawing anti-aliased lines in OpenGL requires tessellating a line into a triangle strip and fading the opacity of the end caps to complete transparency. The HTML5 canvas automatically handles anti-aliasing for lines drawn with its line API. This meant we actually needed to remove code from the OpenGL version. Unwinding the array of triangle vertices in the OpenGL code also gave us much better performance over trying to natively copy the triangle strip method of drawing lines.

In the end, we have nearly 15,000 lines of code executing in the browser (it’s been minified so if you view the source code in your browser, it will be many lines fewer than that). Anticipating the complexity associated with that much code, Denis Morozov (the Director of Development at ZeptoLab) asked a fair question early on: will HTML5 give us the speed and performance that we need for this game?

To answer that, we created an early “performance” milestone, one where we focused on getting a minimal version of the most intense parts of the game running. Namely, we wanted to see what the ropes looked like and whether we could handle the complex physics engine in the browser.

Performance

Three weeks into the project, we finally had the basics of the physics and drawing engines in place with a simple timer to bootstrap the animation. We could now render a couple of ropes, a star, and an Om Nom sprite into the game scene. Progress! By week four, we had included some basic mouse interaction and with that we could actually play the game! We were testing performance along the way, but we wanted to let the team at ZeptoLab give us their feedback.

When we shared the code with ZeptoLab, they were pleasantly surprised by the performance (particularly the speed and smoothness from the game) that we were seeing in modern browsers. To be honest, we had been holding our breath just a little. We expected JavaScript to be fast but the physics calculations were intense and had to happen in real-time. This is a great example of where common preconceptions about the “slowness” of JavaScript turn out to be wrong. The latest generation of JavaScript engines is incredibly fast.

In this case, we were previewing the game in Internet Explorer 9. When you load the game, Internet Explorer 9’s Chakra JavaScript engine pre-compiles the code on a background thread—just as a compiler would compile a language like Objective-C or C++. It then, in real time, sends the compiled code (byte-code) to the game thread for execution. The result is near-native execution speeds. Amazingly, this is something that you just get for free from the JavaScript engine—we didn’t have to do anything special in the code.

Framerate test results early in the project (note that framerates are capped at 60FPS)

Our bet on JavaScript was paying off, so we turned our attention to hardware and browsers. With Internet Explorer’s hardware-accelerated rendering stack and our experience with Disney Tron and other HTML5 sites, we didn’t have any concerns about its ability to run the game perfectly on our test machines. We were easily hitting our capped goal of 60 FPS (frames per second). We wanted to be sure, however, that the game ran well on other hardware with other browsers. Here’s what we saw after some preliminary testing.

Based on those numbers, we set 30 FPS as our minimum bar. We decided that when the browser goes below that threshold, we would notify the user. They could still play the game, but we’d inform them that it could feel a little bit sluggish. This ensures that we support the huge diversity of hardware and software that’s out there and provide the best experience we can to all of the game’s visitors.

Two things we want to point out. One, the current version of the game works best on desktop PCs and Macs with a mouse. We have not added the support for touch based input yet, but this is something we’re considering for future versions.

Second, the current version of Chrome (version 16) has known issues related to media playback that make sound unpredictable in Cut the Rope. We researched workarounds and have attempted to re-encode the media in multiple formats (including WebM), but haven't found a format or MIME configuration or anything else that will reliably fix the problem. These appear to be browser bugs and known issues. More importantly, the game continues to be playable and enjoyable in spite of the intermittent audio. In light of that, while we can say Internet Explorer 9 users get a great plug-in free experience, Chrome and some Firefox users could have run into an audio problem but will notice we fall back to a flash plugin to ensure that sound effects and music will work.

Tools

A great thing about HTML5 is that you don’t need to learn a new language to unlock the power of this new technology. If you know and understand JavaScript, you already have access to all that a modern browser can do. You could even create your own game like this!

Code Editor and Development Environment

Visual Web Developer 2010 Express is a free download and a great editor for even experienced web developers.

A screenshot from the profiler that shows the disproportionate amount of time being spent in Calc2PointBezier, a function that's used to caculate the positions of the rope segments.

There are some great free tools that make working with JavaScript and HTML5 easy. Much of our development was done in Visual Web Developer 2010 (the "express" version is available for free here). This is a really robust web editor with autocompletion for JavaScript and CSS. It’s great that the express version is free! We did most of our testing in Internet Explorer 9 on Windows 7 and from time to time we would also test on Firefox, Chrome, Safari, and in Internet Explorer 10 developer preview. In general, all major browsers have a very consistent implementation of the HTML5 features we used and, in most cases, anything we tested in Internet Explorer 9 “just worked” everywhere else.

Check out our Resource Loader!

Cut the Rope has very unique and detailed visual styling - lots of media in the form of images, sounds and video - which comes at a small cost. The result is that the whole game is much bigger than an average website. Combined, it’s around 6 MB (compared to 200-300K for a typical site). That much media can take a little while to download and we can't start the game until we know everything is there. A traditional web page is pretty forgiving if you're missing an image or two but the HTML5 canvas API (drawImage) will fail if the image isn't available.

To tackle this challenge, we wanted to create a resource loader that downloads all of the content we need for the page and gives us good feedback as things are downloaded. This bit of code does a bunch of smart things:

1. It deals with the peculiarities of how different browsers handle downloads and how they inform you of their progress.

2. It lets you make smart decisions about the order in which things are downloaded (you might want to start big files first, for example, or maybe download all of the menu images before you get the game images).

3. Finally, it gives you smart events as things arrive so that you can show the user progress or even start part of the game when the first group is completed.

Building these types of libraries is tricky to do well. Since we’re really pleased with how this all came together, we wanted to share the code for our resource loader with you. The result is PxLoader, a javascript Resource Loader library that you can user to make preloaders for HTML5 applications, games and sites. It's open source and free. You can grab it from the top of the page, or just click here.

Performance Tools in Internet Explorer

Another indispensable tool in the development process was the JavaScript Profiler in Internet Explorer 9. Profiling lets you discover hot spots and bottlenecks in your code. At one point in our first performance related milestone, we nearly called it quits when we discovered that on some machines we were stuck at 20 or 30 FPS.

We did some initial code reviews, but nothing was jumping out. We loaded the game with the profiler and immediately saw that we were spending a lot of time inside the satisfyConstraints() function. That function calculates some of the math related to the physics of the ropes. The Objective-C implementation which we had ported was written recursively, passing a new object into each successively deeper call.

With some guidance from Microsoft, we decided to replace the recursive function with an “unpacked” iterative version of the same code. The results were amazing. We saw a 10x improvement in every browser! Frankly, we would have never found that without the profiling tools in Internet Explorer 9.

What’s next?

At BUILD in September, Microsoft showed a developer preview of Windows 8. With this announcement, the HTML5 story got more interesting because Metro style applications can be created using a variety of developer toolsets, including HTML5. This means that web developers can take code that was written for the web and easily and seamlessly port it to Windows 8. The investment in immersive experiences online now can pay off in real profits later with the Windows Store.

In fact, with very little extra work, we were able to port this HTML5 experience to a Windows 8 Metro style app. Read about Cut the Rope and its integration with the Windows Store in this blog post.

We are excited to see what developers can build today with HTML5. You can download Internet Explorer 9 and find other beautiful sites at www.beautyoftheweb.com, or download the Developer Preview of Windows 8 at dev.windows.com.