2014-04-01T00:08:27+08:00http://openaphid.github.com/Octopress2014-03-31T23:11:00+08:00http://openaphid.github.com/blog/2014/03/31/safe-type-casting-in-objective-c-with-instancetypeinstancetype is a relative new keyword in Objective-C language. Besides its general usage scenarios, it can be leveraged for safe casting. The approach is simply a category to NSObject:

For example, it’s common to store NSNull inside an NSMutableArray to indicate nil value actually. Then accessing the array normally requires extra type checking to insure NSNull is not used accidentally, which leads to crash at runtime. Using oa_cast: would make codes easier to write:

DISCLAIMER: the post contains my personal opinions on the subject. I would appreciate it if you could correct my mistakes.

Back to the time when I started OpenAphid-Engine, there were already several similar iOS/Android projects. These projects, either commercial or open source, expose their core features by JavaScript language. For instance, Titanium and PhoneGap allow developers to use JavaScript to build native iOS/Android apps; ngCore enables building cross platform games by pure JavaScript. JavaScript language has been chosen as a first-class citizen as it’s one of the most popular programming language. It eases the learning curve and easily attracts developers into a new product ecosystem.

How to Support JavaScript on iOS/Android

There are two main approaches to support JavaScript in an iOS/Android app. One method is to leverage the system browser component, UIWebView on iOS and WebView on Android; the other way is to compile and integrate a full-featured JavaScript engine.

Using the system component is easy to implement but it’s inflexible and inefficient. WebView provides addJavascriptInterface to inject Java classes into JavaScript context. But it only supports primitive data types which brings restrictions to API design; it’s also unstable and crashes on Android simulator 2.3 and some real devices according to issue #12987. Things are worse on iOS, UIWebView doesn’t have public APIs to support direct interaction from JavaScript to Objective-C (You have to use private APIs to achieve the same functionality of addJavascriptInterface).

PhoneGap is the most famous project that is built upon UIWebView and WebView. Developers are forced to use callbacks to retrieve return values from its JavaScript APIs, which is complex and inefficient especially for games.

Some earlier versions of ngCore also relied on UIWebView in order to support iOS. This mechanism has been replaced because of the awful performance.

In order to get better performance, flexibility and compatibility, it becomes popular by embedding a full featured JavaScript engine in native apps.

Choices of JavaScript Engines

As far as I know, four JavaScript engines could be built and ran on iOS or Android: JavaScriptCore, SpiderMonkey, V8 and Rhino. The table below lists their compatibilities on iOS and Android.

iOS

Android

JavaScriptCore

Interpreter only

Interpreter and JIT

SpiderMonkey

Interpreter only

Interpreter and JIT

V8

JIT only for jailbroken devices

JIT

Rhino

Unsupported

Interpreter

When I was searching for the right JavaScript engine for OpenAphid-Engine, my evaluation focused on the following metrics:

Compatibility. The engine should support both iOS and Android, and work on both simulators and devices, which requires it support both ARM and x86.

Stability. It should stably work on both platforms and supported CPU architectures.

Extensibility. Extending the engine to add native features should be easy. For example, OpenAphid-Engine required a bridge layer to access OpenGL ES from JavaScript.

Performance. It’s boiled down to two primary factors: fast JavaScript evaluation, and efficient binding mechanism with low overhead. OpenAphid-Engine may trigger hundreds of OpenGL ES calls from JavaScript to render a single frame. The rendering would be slow if the overhead is much more significant than normal JavaScript routines.

Small footprint. The memory footprint and binary size of the executable file should be small.

Rhino and V8 were out first since they don’t support iOS. I really wanted to build OpenAphid-Engine with V8, which showed great performance and elegant code structure during my preliminary experiment on Android. But I got disappointed due to the fact that V8 only employed a JIT mode while iOS doesn’t allow JIT unless on a jailbroken device. Please refer to issue #1312 if you need more technical details.

I debated a lot between JavaScriptCore and SpiderMonkey. After successfully built them on iOS and Android, I applied benchmarks and experiments to find the better one.

SpiderMonkey is available under a more friendly license, but it lost in nearly all of my measurements compared to JavaScriptCore. It generated larger binary file size (about 1.3MB larger for ARMv7); JavaScript evaluation was slower and the performance overhead of bridging JavaScript and C++ was also more significant. One more reason that pushed me away was that my build of SpiderMonkey randomly crashed on iOS simulator.

The performance of a JavaScript engine can be affected by many factors, like the version of build toolchains, the version of engines, and the OS types etc. The chart below lists the running times of several micro-benchmarks with different builds of engines on an iPod Touch 4. Please check out the Google Doc if you’re interested at the precise running times.

Adventure with JavaScriptCore

The running time of 1m-native_function was over six times longer than 1m-js_function and 1m-Math.abs(0) on JavaScriptCore. I also observed the similar performance issue on accessing properties of injected native objects.

The C APIs had a clean design but was lack of flexible memory management APIs. It seemed difficult to resolve issues caused by circular references without deeper cooperation with the internal garbage collector.

I abandoned the original plan of using the C APIs in order to solve problem 1 and 2. The version of JSC from iOS 4.3.3 was used, as it’s faster than the version from iOS 5 in interpreter mode with a smaller binary executable file.

Engines Used in Other Products

During the development of OpenAphid-Engine, I always kept my eyes on other products. The table below summarizes the JavaScript engines they are using underneath.

iOS

Android

ngCore 1.6 and above

UIWebView

V8

ngCore 1.7 and later

SpiderMonkey

V8

Titanium

JavaScriptCore

V8 or Rhino

PhoneGap

UIWebView

WebView

Cocos2D-x JavaScript

SpiderMonkey

SpiderMonkey

CocoonJS

JavaScriptCore

JavaScriptCore

Ejecta

JavaScriptCore

Unsupported

directCanvas

JavaScriptCore

No clue

Next Story in Series

]]>2013-01-14T14:09:00+08:00http://openaphid.github.com/blog/2013/01/14/openaphid-engine-v0-dot-2-1f-and-discontinuation-announcementOpenAphid-Engine was born as an exploration project at the first half year of 2012 when I quit my day job. Its mission was to figure out the most efficient way to integrate a full JavaScript engine within native iOS/Android games.

The development went perfectly well as it even outperformed the commercial solution of ngCore from DeNA. I really enjoyed the pleasure brought by tackling technical problems to make the engine support both iOS and Android with high performance. I also gained precious experiences after studying source codes of JavaScriptCore and other great open source projects.

But I failed to find enough time working on it after I started a long travel plan with my family at Aug 2012. After careful consideration, I have decided it’s time to sunset the project as I’m going to find a long-term job again. For developers who are also interested at using a JavaScript engine within native apps, I’ll write two or three more articles in these days to share some pieces of knowledge collected during the development of OpenAphid-Engine.

Release notes of OpenAphid-Engine v0.2.1f

(Android) Adds libOpenAphid_JIT.so which includes a JIT enabled JavaScriptCore. It can significantly boost performance for computation intense tasks in JavaScript. For instance, the running time of fibonacci(30) drops to ~140ms from ~780ms on a Nexus 7, while Java on Dalvik VM takes 280ms～350ms to finish the calculation.

Bug Fixes

v0.9, Sep 21st 2012

First release

]]>2012-09-21T15:11:00+08:00http://openaphid.github.com/blog/2012/09/21/aphid-flipview-for-android-v0-dot-9-beta-releasedI’m happy to announce the first release of FlipView, an Android UI component which help add flipping animation in your application. Please download and install the pre-built demo APK file to check out it in action:

Core Classes

The general routine of setting up FlipViewController is straightforward:

Creates an instance of FlipViewController:

1

FlipViewControllerflipView=newFlipViewController(context);

Provides an adapter as the data source. It’s very similar to the setup logic for a ListView:

12345678910111213141516171819202122

flipView.setAdapter(newBaseAdapter(){@OverridepublicintgetCount(){returncount;}@OverridepublicObjectgetItem(intposition){returnposition;}@OverridepubliclonggetItemId(intposition){returnposition;}@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupparent){//setup a view by either reusing the convertView or creating a new one. returnview;}});

Important Notes

There are some facts about the component which you should pay special attention to:

It’s recommended to use only ONE instance per activity. As the animation is implemented in a GLSurfaceView, using multiple instances in one activity may cause serious compatible problems on some Android devices.

Vertical scroll in sub-views may not work as the touch events are consumed by the animation.

I don’t have enough resources to test its compatibility across all Android OS versions and devices. Please verify it after integrating it in your project.

Please use Github issues to report any problems and request more features. Thanks in advance.

Updated at 2012-08-17: Fixed the broken links to the project and the APK file.

The new demo app adds two new features compared to the previous one:

Supports flipping over between two views. FlipCards.java takes screenshots of the front and back views, which are used to construct the textures for the translucent GLSurfaceView. The flip animation is rendered by four instances of Card. Please refer to the draw(GL10 gl) method for more details.

Flip angle can be controlled by touch events. Angle is calculated according to the relative movement of touches. The logic can be found in the handleTouchEvent(MotionEvent event) method.

Future Enhancements

The demo app is just a prove of concept. It can be enhanced to be a component for general scenarios:

To support a Adapter as its data source to load views dynamically and lazily.

To implement similar APIs like ListView

To support other fancy effects that can be implemented in OpenGL ES.

But I’m sorry that I’ll be in a long trip with my family. Both android-flip and OpenAphid-Engine will not be updated until I come back. You can still reach me via email if you have any questions.

]]>2012-07-10T14:39:00+08:00http://openaphid.github.com/blog/2012/07/10/tutorial-exposing-java-methods-to-javascript-in-openaphidOpenAphid-Engine for Android v0.1.5 supports exposing Java methods as JavaScript functions, which is helpful for integrating 3rd-party services into games. The binding APIs are similar to its iOS version.

The snippet above injects an instance of Java class BindingTest4 to JavaScript as aphid.ext.test4. Its method addInMainThread() can be accessed via aphid.ext.test4.add() in JavaScript.

The AphidJSFunction annotation supports two optional element-value pairs: name and isInUIThread. name declares a custom function name to JavaScript, the Java method name is used if it’s not specified; isInUIThread controls the thread to invoke the Java method, its default value is false. In OpenAphid-Engine for Android, JavaScript runs inside the GL thread. Setting isInUIThread to true makes the Java method run inside the UI thread; the execution of JavaScript is blocked in the GL thread until the Java method returns from the UI thread.

Type Conversion of Return Value from Java to JavaScript

Java

JavaScript

void

undefined

null

null

boolean

bool

primitive numeric types(short, char, int, long, float, double)

number

String

string

List

array

Map

object

Type Conversion of Parameter Value from JavaScript to Java

JavaScript

Java

undefined

null

null

null

number

corresponding primitive numeric type

string

String

array

List

object except array

Map

Strict type checking is performed during conversion, which throws a JavaScript exception if the types are mismatched.

Integration with Google Analytics in Boilerplate-Android

Let’s illustrate how to integrate Google Analytics SDK into OpenAphid-Engine for Android. All source codes can be found in the Boilerplate-Android project.

After adding Google Analytics Android SDK into our project as described in its official document, we create a Java class GoogleAnalyticsBinding to bridge JavaScript and Google Analytics SDK. GoogleAnalyticsBinding makes the exposed functions have identical signatures as its iOS version, which enables the same script file(main.js) to run on both platforms.

]]>2012-06-27T08:22:00+08:00http://openaphid.github.com/blog/2012/06/27/openaphid-android-v0-dot-1-releasedWe’re excited to release the first version of OpenAphid-Engine which supports Android OS. OpenAphid-Engine is now a cross platform 2D game engine with both iOS and Android support.

Several github repositories have been updated, please check them out for more details:

Highlights and Limitations of OpenAphid-Engine Android v0.1

It’s the beginning of cross platform support of OpenAphid-Engine. Please consider it as an alpha release. But we’d like to summarize some implementation highlights here:

The core runtime shares the same code base with the iOS version, which makes new features can be added to both platforms in the future.

The same JavaScript engine is used on both platforms, which saves us from building a proxy layer to support different engines on different platforms as other solutions do. It also brings better performance which we’ll prove later.

The project is built with the standard Android NDK, no private or undocumented APIs are used.

This release is lack of several important features comparing to the iOS version. We’re planning another release to make it catch up in the near future.

The native library is built for armeabi-v7a only in this release. armeabi support will be included in the next release.

JavaScript JIT compiler is not enabled. We’ve done some experiments to enable it on Android OS, which shows promising performance gains for computation intensive tasks and regular expressions. But we decided to disable it now as we didn’t spend enough time on evaluating its stability.

JavaScript to Dalvik Java binding is not implemented. XMLHttpRequest and multitouch supports are absent too.

This version doesn’t reload textures automatically when the GL context is destroyed. It simply finishes the activity if GL context is lost. We’re working on a better way to handle it.

Performance Benchmark

The same tank program as introduced in our previous post is used to evaluate the performance of OpenAphid-Engine on Android OS. Several other Android 2D game engines are chose as references:

Ngcore 1.8, a commercial game engine from DeNA which also uses JavaScript and OpenGL ES.

The benchmark is performed on a Motorola DEFY+ MB526 phone, which has a 1GHz processor and a 854x480 sized screen. Its Android OS version is 2.3.6.

We captured the average FPS in 5 seconds for displaying different number of tanks with each engine:

OpenAphid-Engine shows great performance again as we can tell from this chart. It’s on par with cocos2d-x, and faster than others.

cocos2d-android-1 suffers from the frequently GC pauses of Dalvik VM as observed from logcat. Ngcore is the slowest engine once again, and its rendering is also buggy in this test. The dirty area in black color should have been cleared in the screenshot below, we’ve filed a bug report about it to Ngcore:

About the Next Release

The next release will make the Android version have all features as the iOS version does. JavaScript to Dalvik Java binding APIs will be introduced to make integrating 3rd-party services become cross platform too. We’ll add new features simultaneously on both iOS and Android versions after that release.

Updates at 2012-12-12: Please check out FlipView for an improved solution.

The demo in this post was born when we’re working on the Android port of OpenAphid-Engine. One of our engineers is a huge fan of Flipboard iOS. He decided to implement its page flip animation on Android.

If you don’t know about the effect, please install the APK file of our demo app to see how it looks:

Overview

The Flipboard animation is easy to achieve on iOS by using Core Animation. Things get a bit difficult on Android:

The view animation framework on Android is not flexible and efficient for versions prior to 3.0;

The Android layout system makes it even harder for advanced animation;

In order to apply flip effect for views with arbitrary structures and make the animation run smoothly, several tricks are used in our approach. OpenGL ES is used to render the animation for efficiency; a special view container is implemented to grab content of a view to OpenGL ES. Let’s go through them one by one.

View Hierarchy

The first page is displayed over the second page. We took a screenshot when the first page flipped by 75 degrees:

When the first page is flipping, its top half stays still while the bottom half flips around the horizontal center axis of the page; part of the second page is visible during the animation.

Custom ViewGroup

A custom ViewGroup, FlipViewGroup, is used to manage the visibility of the two pages and serve content to OpenGL ES. Besides using a LinkedList to manage normal sub-views, it also contains a GLSurfaceView to play animation:

As in line 14 to line 16, when a change of view dimension is detected and flipping is on, the OpenGL render updates the texture by taking a screenshot of the top view; then the top view is hidden while the GLSurfaceView will display its content with flip animation.

GrabIt

GrabIt is a small utility to convert the content of a view to a Bitmap. The result bitmap will be used to construct the texture for GLSurfaceView.

Setup of GLSurfaceView and Renderer

The GLSurfaceView instance is setup to use the following configurations:

A RGBA_8888 surface with 16-bit depth buffer;

It’s displayed on the top of the window;

A custom renderer: FlipRenderer;

The desired PixelFormat of the surface should support translucency;

The rendering mode is set to make the renderer be called repeatedly;

The FlipRenderer maps the OpenGL pixels to 2D screen pixels one-by-one which is similar to what OpenAphid-Engine does for 2D games. And the origin of the coordinate system is bottom left.

The actual drawing process is managed in the instance of FlipCards.

FlipCards

FlipCards manages the content and structure of flip animation. It accepts a bitmap, which should be the screenshot of the first page, to build the texture for rendering. The texture is binded to two instances of Card object. topCard renders the top half, which stays still; bottomCard draws the flipping effect of the bottom half.

Card

Card represents a quadrilateral in OpenGL space. Its angle property controls the flip angle, which is accomplished by the following OpenGL codes:

The vertices of topCard are set to make the card at the top half of the application screen. And its texture coordinates are set to render the top half of the first page.

In order to make the flip effect more realistic, a gray rectangle is rendered to cover the appealed area of the second page, which looks like a shadow of the flipping card casting on the second page.

123456789101112131415161718192021

if(angle>0){gl.glDisable(GL_LIGHTING);gl.glDisable(GL_DEPTH_TEST);floatw=cardVertices[9]-cardVertices[0];//shadow widthfloath=(cardVertices[1]-cardVertices[4])*(1f-FloatMath.cos(d2r(angle)));//shadow heightfloatz=(cardVertices[1]-cardVertices[4])*FloatMath.sin(d2r(angle));//z index of the top side of shadowfloat[]shadowVertices=newfloat[]{cardVertices[0],h+cardVertices[4],z,cardVertices[3],cardVertices[4],0f,w,cardVertices[7],0f,w,h+cardVertices[4],z};floatalpha=1f*(90f-angle)/90f;//shadow alphagl.glColor4f(0f,0.0f,0f,alpha);gl.glVertexPointer(3,GL_FLOAT,0,toFloatBuffer(shadowVertices));gl.glDrawElements(GL_TRIANGLES,indices.length,GL_UNSIGNED_SHORT,indexBuffer);gl.glEnable(GL_DEPTH_TEST);gl.glEnable(GL_LIGHTING);}

The snippets above should cover the core concepts of our approach. You can fork the project to support more effects as we can see in Flipboard iPhone, like page flip following touch moves, flip over of a page, and book flip effect etc.

BTW, we’re tackling some technical problems of OpenAphid-Engine Android version. Will keep you posted if a stable version is ready.

]]>2012-05-16T10:06:00+08:00http://openaphid.github.com/blog/2012/05/16/tutorial-exposing-objective-c-methods-to-javascript-in-openaphidOpenAphid-Engine 0.2 was shipped with a new binding system which can bridge JavaScript functions to Objective-C methods on demand. It’s useful for games to integrate analytics services, monetization solutions, and social services, etc. In this tutorial, we’ll go through the binding system by demonstrating how to integrate Google Analytics iOS SDK into OpenAphid-Engine.

How to Access Objective-C Methods in JavaScript

The OABindingProtocol protocol, defined in OABindingProtocol.h, defines a method bindSelectors: that you can implement in your Objective-C classes to expose their methods to the JavaScript environment. To make a method valid for export, its return type and all argument types must be the supported types below:

Type Conversion of Return Value from Objective-C to JavaScript

Objective-C

JavaScript

void

undefined

nil or NSNull

null

primitive numeric types(int, float, double, etc)

number

NSNumber

number

NSString

string

NSArray

array

NSDictionary

object

Type Conversion of Argument Value from JavaScript to Objective-C

JavaScript

Objective-C

undefined

nil or NSNull

null

nil or NSNull

number

primitive number or NSNumber

string

NSString

array

NSArray

object except array

NSDictionary

For any method to export, it must be explicitly declared in the implementation of bindSelectors: in your Objective-C class. For example, the snippet below exports [DatastoreBinding saveString:] to JavaScript environment as int saveString(string):

OpenAphid-Engine injects an instance of DatastoreBinding as a JavaScript object of [object DynamicBinding] into JavaScript environment. And its name is datastore. The iOSOnly argument manages the namespace which contains the injected object. If it’s YES, then the injected object can be accessed via aphid.extios.datastore; otherwise it can be accessed via aphid.ext.datastore.

Notes: the iOSOnly argument is actually designed for future compliance when OpenAphid-Engine supports both iOS and Android.

Integration with Google Analytics in Boilerplate-iOS

Let’s see a more concrete example about integrating Google Analytics in Boilerplate-iOS.

A new tutorial is coming in this week to introduce the new binding system for exposing Objective-C functions into JavaScript. Please stay tuned!

]]>2012-05-06T21:54:00+08:00http://openaphid.github.com/blog/2012/05/06/tutorial-handling-touch-events-in-openaphid-v0-dot-1-1We are glad to release OpenAphid-Engine v0.1.1, which adds multitouch support and fixes several issues about touch handling. The detailed change log is following:

Fixes incorrect values of event.touches and event.targetTouches in ontouchend callback

Adds a new constructor function to Color: new Color(color, [alpha])

Basics of Touch Event Handling

Any instances of the Node class can be the EventTarget of touch events in OpenAphid-Engine. This is different from cocos2d-iphone, in which CCLayer is usually the target of touch event.

Several attributes affect how a node handles touch events: multipleTouchEnabled of the Director class; userInteractionEnabled, visible, touchEnabled, and contentSize of the Node class.

Flow of Touch Event

The flow of a touch event goes through 2 phases: hit-testing and event bubbling.

Hit-Testing

When a touch happens on the device screen, OpenAphid-Engine follows the routine below to locate its event target:

Hit-testing is used to find the sub-node of the running scene that is under a touch. This method proceeds recursively on each node in the node hierarchy.

Hit-testing fails on a node and doesn’t proceed on its children if either userInteractionEnabled or visible is false.

The testing fails on a node but proceeds on its children if its touchEnabled is false

If the contentSize if a node is zero, hit-testing is delegated to its children nodes; otherwise it proceeds when the touch took place inside the rectangle area defined by the contentSize.

A node becomes the event target when it meets the following conditions: its contentSize is not zero and the touch location is inside it; hit-testing fails on any of its children but succeeds on it.

Event Bubbling

Once the event target of a touch is found by hit-testing, a touch event object is passed to its callback functions, and bubbling up to its ancestors of which touchEnabled is true. event.stopPropagation can be used to stop bubbling.

Interfaces of Touch Event

The APIs of touch event handling in OpenAphid-Engine are implemented to follow the specification of W3C DOM Touch Event Version 1. There are already lots of guides about handling touches in DOM, which can be used as references for OpenAphid-Engine too. We’ve updated the Demos of OpenAphid-Engine to include a TouchTest application, which demonstrates three scenarios of touch handling:

Handling a single touch event to drag a sprite.

Handling multitouch events to move multiple sprites.

Detecting pinch gesture to zoom in/out a sprite.

Please checkout the Demos project for more details. We’re also going to implement gesture detection APIs in the future.

]]>2012-05-02T14:52:00+08:00http://openaphid.github.com/blog/2012/05/02/develop-mode-of-openaphidDeveloper Mode is a feature to speed up developing games with OpenAphid-Engine. The behavior of OpenAphid-Engine changes if the developer mode is turned on.

How to Enable Developer Mode?

Open your project with Xcode and locate the following lines in OAAppDelegate.m:

Setting the value of the developMode parameter to YES enables the developer mode of OpenAphid-Engine;

An HTTP server should be used to host the content inside the bundle folder specified by configBundleName. The value for the baseURL parameter should be set to the server address too. A ruby based tiny HTTP server is included in our boilerplate project, please refer to the web_server.rb and start_dev_server.sh files for more details;

The application should be built and re-deployed to devices with the new settings.

And for the Boilerplate-iOS project, UIApplicationExitsOnSuspend is YES in its info.plist file; which makes the app terminate automatically when the Home button is pressed.

Changes in Developer Mode

The main benefit of using developer mode is that it makes the game development speedy like developing for web:

JavaScript files are fetched from the HTTP server. If you want to see the result of your changes in the game script, you only need to re-open the app;

Graphics resources are fetched remotely too. For example, a texture can be created by using new aphid.g2d.Texture2D("player.png"); the player.png file is fetched via http://129.158.217.36:18080/player.png in developer mode. OpenAphid-Engine Runtime also prints a log about it as following:

Internal warning and error messages are displayed as on-screen notifications besides logging in device console. Warning messages are in blue background color and errors are in red color. The screenshot below shows a notification about a syntax error at line 17 in main.js:

Messages produced by console.warn and console.error are also displayed as notifications;

Demos: https://github.com/openaphid/Demos. This repository includes several demos of OpenAphid-Engine. PortedDemos contains four iOS applications which are ported from Cocos2d-iPhone: NodeTest, SpriteTest, EffectTest and AdvEffectTest. They demonstrate how to manipulate nodes, sprites and actions in JavaScript APIs. TankBenchmarks is the benchmark described in our previous post. The implementation by using ngCore is also presented for your reference. You can build and run them on your iOS devices to reproduce the benchmark results.

Boilerplate-iOS: https://github.com/openaphid/Boilerplate-iOS. It’s a template project for developing iOS games with OpenAphid-Engine. It’s a good start point if you want to play with the APIs of OpenAphid-Engine by yourself.

The JavaScript API references of OpenAphid-Engine v0.1 is also available. It’s a bit rough right now. We promise that it’ll be improved in the future.

Highlights of OpenAphid-Engine v0.1

v0.1 is the start of OpenAphid-Engine. We admit that it’s not ready for real product yet, but we’d like to present some characteristics of the project here.

OpenAphid-Engine APIs can be considered as the “DOM” APIs for 2D games on mobile devices. The internal binding layer is implemented in the similar approach as WebKit does for binding native objects to the JavaScript engine;

The memory occupied by native objects is managed automatically. Compared to some other script based game engines, OpenAphid-Engine doesn’t have destroy API at script level for any native objects. Native objects that are created in JavaScript are managed by the JavaScript garbage collector as other pure JavaScript objects.

OpenAphid-Engine follows the standard specifications to implement some core features. Although the rendering system of OpenAphid-Engine is ported from Cocos2d-iPhone, which is not supported in browsers; the other APIs in OpenAphid-Engine are designed to follow W3C standards. For example, the console object in global scope is provided as it is in browsers; the XMLHttpRequest APIs are partially implemented in v0.1, and will be fully compatible to its W3C specification in a future release. And the touch event handling in OpenAphid-Engine is implemented as the same as in DOM, which is totally different from Cocos2d-iPhone.

OpenAphid-Engine is fast and efficient. The benchmark result in the previous post has been updated by using v0.1, which is slightly faster. We also evaluated the memory usage of OpenAphid-Engine with the same benchmark (lower is better):

The data are captured by using the Activity Monitor of Xcode Instruments. The memory usage of the benchmark on ngcore v1.6 is presented for reference only.

What’s Next for OpenAphid-Engine

We’re working hard to improve OpenAphid-Engine. Most efforts are spent on the following tasks:

Ports more features from Cocos2d-iPhone, like physics support, audio support, etc;

Supports Android OS;

Provides binding APIs for integrating 3rd-party services. The binding system in OpenAphid-Engine Runtime is designed for the performance requirement of OpenGL ES rendering, but it’s not suitable for general purpose. Another binding system is planned to bridge JavaScript codes and Objective-C(or Java on Android in the future releases) easily. The Boilerplate-iOS project will also be improved by integrating 3rd-party services, like analytics, in-app purchase, advertisement;

Please feel free to contact us with your questions and suggestions via openaphid At gmail.com. We’d appreciate it for your kind help.

Special Thanks

We’d like to express our appreciation to Oana Dobre, who designed the cute aphid graphics and allowed us to use them for free.

]]>2012-02-20T23:26:00+08:00http://openaphid.github.com/blog/2012/02/20/javascript-and-cocos2d-a-sneak-peekWhat is OpenAphid-Engine?

OpenAphid-Engine is our secret OSS project to combine the power of JavaScript and Cocos2d-iPhone for native game development on mobile devices. It allows developers to write fast and native quality games in JavaScript language. The architecture of OpenAphid-Engine can be summarized as below:

A set of Cocos2D-style JavaScript APIs are provided for composing scenes, applying actions on nodes, handling events, etc. The core runtime of OpenAphid-Engine is wrote in C++, which adopts the architecture of Cocos2d-iPhone. The JavaScript binding module bridges the C++ runtime and the JavaScript engine, which allows games to use native features in pure JavaScript.

We decided to implement the core of OpenAphid-Engine in C++ instead of reusing the Objective-C code base from Cocos2d-iPhone. The first reason is for portability. The current WIP version is for iOS only as Cocos2d-iPhone, but we’d like to support Android and other platforms after the iOS version is stable. The other consideration is for faster JavaScript binding. We want to reduce the performance overhead introduced by the script layer as small as possible.

Why use JavaScript?

JavaScript is one of the most popular programming languages in the world. OpenAphid-Engine enables developers using a familiar language for mobile game development, and it can also make the development cycle in a web speed.

At the development stage, developers can save the script and reload it on devices to see the changes instantly. No need to compile and re-deploy anymore.

OpenAphid-Engine is not the first one to bring JavaScript into native game development. There are several other frameworks which take the similar approaches. The most famous one is ngCore from DeNA Co., Ltd.

Performance Benchmark Setup

We adopt a benchmark program introduced in a presentation of ngCore SDK. The program is modified a bit and implemented in Cocos2d-iPhone, ngCore and OpenAphid-Engine. The benchmark is composed by several parts, let’s describe them using APIs from OpenAphid-Engine:

Updates at 2012-04-28: code snippets were updated according to the API changes in v0.1 release.

Run the scene

Benchmark Environment

The same benchmark is implemented in Cocos2d-iPhone, ngCore and OpenAphid-Engine. We tried to run it using the latest stable version of each:

Cocos2d-iPhone 1.0.1. CCSpriteBatchNode is not used to make sure the benchmark share the same behavior in each framework. CC_DIRECTOR_FAST_FPS is also turned off for the same reason. CC_DIRECTOR_FPS_INTERVAL is set to 1.0f.

The benchmark is performed on an iPod Touch 3rd generation (32GB). The hardware specification can be found from its wikipedia page.

Benchmark Results

The FPS data are recorded for running different number of tanks on each framework. The FPS of ngCore is not consistent, so we tracked both the high and low FPS data.

Updates at 2012-04-28: benchmark results are updated by using OpenAphid-Engine v0.1 release.

OpenAphid-Engine gives a pleasant result. It’s faster than ngCore and keeps 60 FPS when there are less than 200 tank sprites. The FPS is lower than Cocos2d-iPhone’s when adding more tanks, it’s acceptable as there are hundreds of native-to-JavaScript update callbacks to invoke during each frame. And we’ll keep working to improve its performance.

When will OpenAphid-Engine be released?

OpenAphid-Engine is still under development. We’re working hard to make the first public release available in the middle of April. All source codes will be public then. Please feel free to mail us with your questions and suggestions via openaphid At gmail.com. We’d appreciate it for your kind help.