How Om Nom from Cut the Rope 2 moved to Amazon Fire Phone

    Amazon recently released a new Fire Phone smartphone, and ZeptoLab received a proposal to modify the game Cut the Rope 2 for it. We added support for smartphone innovations there, and the game was included in the list of pre-installed applications.

    The device came to us long before the official release. Devkit was placed in a special box that protected the design of the device from prying eyes, and, most importantly, from the camera lens. However, all the most interesting was the "stuffing" of the phone.




    The main feature of the first smartphone from Amazon is the four front-facing cameras that monitor the user's eyes and transmit data about their position to the programs. This creates a false 3D effect: you can slightly rotate the image on the screen with your eyes, “reviving” the icons and other interface elements. A particularly impressive impression is the viewing of maps: buildings acquire volume, and they can be viewed from any direction, simply by moving your eyes around the screen.

    Other features of the phone are Hero Icon and Hero Widget. Fire Phone works on Fire OS, Android modifications, and instead of the usual home screen, there are Carousel and App Grid screens.



    App Grid is a familiar “grid” of installed applications, and Carousel is a set of recently used programs with horizontal scrolling. For each application, the screen is divided into two parts: at the top a three-dimensional Hero Icon icon is displayed, and at the bottom a set of Hero Widget elements. The widget contains a set of lines for displaying data on the application without the need to run it; these elements can also perform actions for quick access to parts of the application, even if it is closed or minimized.

    For Cut the Rope 2, widget support means the ability to start the game faster by going directly to the level selection menu, bypassing the main menu and one of the two loading screens. Achievements can also be viewed faster, because there is no need to search for the path to this element through the game menu.

    To modify Cut the Rope 2 for Fire Phone, we needed to make a three-dimensional icon, teach the game how to create a widget and add support for the commands of this widget to it.

    Creating a Hero Icon

    In Fire Phone, by default for all applications a three-dimensional Hero Icon is created - a
    flat object with the texture of a regular 2D icon superimposed.



    However, in order to make full use of the provided functionality, we also added depth to our icon and made it more suitable for the style of the smartphone.

    From Amazon we got a toolset, instructions for creating an icon in Autodesk Maya, and a ready-made sample.

    Repeating all the points indicated in the instructions exactly, we made the first version of the icon:



    As you can see, the dies here are located at a distance from each other, so that when moving we can see the displacement of some elements relative to others. Each die is
    one of the "details" of Om Nom or the background of the icon. At a great distance and when the icon is rotated at an angle of up to 30 degrees, the pupils of Am Nyam noticeably move, but remain within the eye.

    We started making the icon in parallel with the development of the widget, and did not have the opportunity to check how it would look on the smartphone screen. After the first export of the model to the .vbl format, made by Amazon for HeroIcon, we found out that the alpha channel is not displayed correctly. Therefore, we moved on to the second option and made a simple icon based on the 2D version, which we really liked.



    And when it seemed that all the problems were already behind us, the fun began.

    Firstly, errors when exporting the model to vbl format:

    1. [ERROR]: Skeleton: No bind pose specified for node AnimatedNode1 in scene ic_myappname_appsgrid that has node animation, create a "bind" animation with keys on animated objects.

    The solution to the problem was found on forums.developer.amazon.com: it turns out that it was necessary to add another empty animation called "bind". The official instructions do not have such information.

    2. [ERROR]: StateMachine: Detected self looping state with transitions that consists of empty sequence (s) resulting in infinite loops.

    This error is treated quite simply: you need to go to Tools Euclid, which you install in Maya according to the instructions, go into editing StateMachine, right-click on “State” and select “Remove Self Connection”.

    There were also several problems, the solutions to which we still could not find, nor could we determine the steps to repeat them.

    For example, our icon did not want to be displayed with the front side on the desired axis: no matter how we rotate it - on the Y, Z or X axis - in any case, the side view was displayed on the device.

    Since we could not solve the problem within the framework of the scene made according to the instructions, we took ready-made samples from Amazon and imported our icon into the scene with the template icon. To our joy, the export went without errors, and on the device flaunted a 3D-icon Cut the Rope 2 in the form we need. And this despite the fact that the sample scene did not have, for example, the animation described in the instructions.

    Secondly, such an error crawled out:

    [ERROR]: MaterialExporter: Unable to open material template “MaterialApplication.app.template”

    This error continued to be randomly repeated in the sample scene, every time we performed any manipulations on the model . To get rid of it, we took a clean sample, re-imported the finished model into the scene, and exported it again.

    Team development for widget

    On this, our work on the icon was over, but we still had to figure out what to display in the widget. If the application does not install its own widget in the system, a standard list of products in Amazon that are similar in topic to this application is displayed in its place. For Cut the Rope 2, the smartphone listed several games from the Amazon Appstore. Replacing the standard behavior, we configured the widget to display game information - the number of collected stars, medals received and recently used items, such as teleporters or tooltips. These widget lines also allow you to go to the game level map, to the Amazon GameCircle achievements screen and to several sections of the in-game store.



    As reference, we had three tutorials from Amazon on Home Screen, Hero Icon, and Hero Widget. Also at our disposal was the SDK for working with the new device and a small reference material on its installation and configuration.

    We started with installing the SDK for Fire Phone. The problem was that the SDK only works with the Android API no higher than 17, and we had to manually lower the version of the development environment (this could not be done automatically). To do this, it was necessary to delete the folders from the Android SDK and download the old versions of the components (SDK Tools 22.6.3, SDK Build-tools 19.0.1, API 17 Platform tools) using the links found on the Internet. After that, installing the Amazon SDK was not a big deal.

    Next, you had to add the library connection string to AndroidManifest:

    The widget elements themselves are created from the program text. After creation, they need to be placed in lists and groups, and then initialize the widget with them. Thus, widget elements receive style, main, secondary and tertiary text, as well as an icon and intent.
    final ListEntry listEntry = new ListEntry(context)
                .setContentIntent(heroIntent)
                .setVisualStyle(SHOPPING)
                .setPrimaryText(primaryText)
                .setPrimaryIcon(imageUri);
    listEntry.setSecondaryText(secondaryText);
    listEntry.setTertiaryText(tritaryText);
    ...
    listEntries.add(listEntry);
    group.setListEntries(listEntries);
    groups.add(group);
    …
    mWidget.setGroups(groups);
    

    The intent for the widget is created through a special class:
    heroIntent = new HeroWidgetActivityStarterIntent("com.zeptolab.ctr2.CTR2Activity");
    

    Then you need to get a request from the widget. We decided to make the project code extensible to work with possible similar widgets or intents. At the level of the ZFramework framework, which is used by our projects, the contents of intents entering the program are captured in onCreate () and onNewIntent (). We use the virtual intent processor IntentInterpreter in the framework, and at the level of this project, the Amazon widget, we use the specific WidgetIntentInterpreter class for processing widget intents.

    We also had to take into account that, unlike standard Android Intents, in the case of a widget from Amazon, only rows can be transferred as additional data with an intent. Therefore, the abstract event parsing class we got the translation methods between the lines and the event ID:
    public abstract class AbstractIntentInterpreter {
        public abstract int processIntent(Intent intent);
        public abstract int getIdForString(String stringData);
        public abstract String getStringForId(int Id);
    }
    

    It is used like this:
    int viewRequested = intentInterpreter.processIntent(intent);
    view.addEvent(viewRequested);
    

    The project code using WidgetIntentInterpreter takes the message from the intent and translates it into the requested ID:
    String extra = intent.getStringExtra(HeroWidgetActivityStarterIntent.EXTRA_HERO_WIDGET_DATA);
    result = getIdForString(extra);
    

    The second line in this code converts the text string into a request ID if the string received in the parameters matches one of the possible queries.

    At the framework level, the View class stores the request ID in the EventDispatcher class, which provides an interface for adding, reading and deleting event IDs:
    public class ZEventDispatcher {
        ...
        public ZEventDispatcher(android.content.Context context) ...
        public void clearEvent() …
        public int getNextEvent(boolean clearAfterRead) …
    }
    

    This code is independent of a specific project; it can work to parse events from other widgets or other events.

    Then it remained only to read the event ID in the project using the JNI. For example, like this:
    int getIntentEvent(bool clearAfterRead)
    {
        JNIEnv* env = JNI::getEnv();
        jclass cls = env->GetObjectClass(JNI::eventDispatcher);
        jmethodID meth = env->GetMethodID(cls, "getNextEvent", "(Z)I");
        jint jEventId = static_cast(env->CallIntMethod(JNI::eventDispatcher, meth, clearAfterRead));
        env->DeleteLocalRef(cls);
        int result = jEventId;
        return result;
    }
    

    Reading one request from the widget can be carried out several times in the program, so it occurs without simultaneously clearing the event.

    The algorithm for processing the widget request when the program starts is approximately the following:

    1. The onCreate event of the application Java class handles intent, receiving the request ID;
    2. The received ID is stored in the EventDispatcher event parser;
    3. When creating the boot screen, the request ID is read by the RootView class;
    4. The loading screen receives the request ID as a parameter and, depending on it, selects a set of resources for loading;
    5. When the loading screen is completed, depending on the request ID, a specific program screen is displayed.


    A little difficulty arose with the correct receipt of intent on the deployment of a minimized application. At first, this intent was caught using the onResume method, however, this event restores the original intent with which the application was originally launched. But we had to get a new intent with every new deployment. The solution was to add properties to the application


    It allowed to receive new intents in the onNewIntent () method. As a result, when deploying, the application began to receive its own unique set of parameters.

    Other difficulties arose when processing special scenarios, for example, when a user interrupts the loading screen, minimizing the application, and then reopens it through another widget element. In this case, it is necessary to compare the target of the current download and the request of the widget, and, if there is a mismatch, initiate a new download using the new ID. At the same time, the absence of a request when expanding (i.e. loading by the application icon, and not by the widget element) after interrupting the download should not start a new download, but simply continue the old one.

    Another difficulty arose when resetting the OpenGL context when minimizing the application and opening it using the widget. Loading a new view and restoring the context should not interrupt each other, and usually one or the other is started.

    Future prospects

    Among the possible development prospects is an improvement in the widget's instruction set. It is very simple to change it in the code, and then, using the game code, update the widget in the phone system when the game is running.

    Speaking about widget development options, it should also be noted that after adding Amazon Hero Widget support to Cut the Rope 2, we now have a code that can be easily adapted to other widgets on Android or iOS if you wish.

    It was a story about creating a modification of Cut the Rope 2 for Amazon Fire Phone. We hope our experience will be useful to you.



    Well, as for experiments with new technologies - at ZeptoLab this is a frequent practice, and in connection with this, we have to revise the requirements from time to time for people who come to technical tasks again. In particular, we have updated the test task for the position of the C ++ developer, and in order not to mislead the hawkers outdated, we are rolling out its latest version.

    You need to write a simple version of the classic Asteroids game:
    • We lead a spaceship through an asteroid field, control at your discretion;
    • The task is to hold out for maximum time, avoiding asteroids or shooting at them. When a shell hits an asteroid, it shatters into smaller fragments, and the fragments, in turn, are completely destroyed when hit;
    • Asteroids must be randomly generated polygons.


    Prototype Requirements:
    • The game is written for iOS or Android platform (strictly);
    • Rendering should be implemented using OpenGL ES version 2.0 or higher (you can restrict yourself to geometric shapes from lines);
    • If you are writing under Android, the game must be written using NDK (C ++) - the program must be entirely in C ++, in Java there can only be a code binding;
    • If you are writing under iOS, the game must be written in C ++. On Objective-C, only code binding is allowed;
    • The game should be written without using any third-party libraries like Cocos2D or GLKit.


    At job@zeptolab.com, we continue to accept your test assignments around the clock.
    We already wrote about how we check them . And a little earlier we talked a little about the system of training for developers that we introduced this year - and we will only continue to develop it, do not miss it.

    In the near future we hope to please you with new interesting things happening in Zepto-space.

    Always yours,
    ZeptoTeam

    Also popular now: