📜 ⬆️ ⬇️

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

Recently, Amazon has released a new Fire Phone smartphone, and ZeptoLab has 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, which protected the design of the device from prying eyes, and, most importantly, from the camera lens. However, the most interesting thing was the “stuffing” of the phone.




The main feature of the first smartphone from Amazon - four front cameras that monitor the user's eyes and transmit data about their position in the program. This creates a false 3D effect: you can slightly rotate the image on the screen with a glance, “animating” 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 the view around the screen.
')
Another feature of the phone are Hero Icon and Hero Widget. Fire Phone runs 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: the three-dimensional icon Hero Icon is displayed at the top, and the set of Hero Widget elements at the bottom. The widget contains a set of lines for displaying data on the application without having to start 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 that you can start the game faster by going straight to the level selection menu, bypassing the main menu and one of the two loading screens. Achievements can also be viewed faster, because the need to search for the path to this element through the game menu disappears.

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

Create Hero Icon

In Fire Phone, the default 3D Hero Icon for all applications is created -
flat object with the texture of the usual 2D icons.



However, in order to better utilize the functionality provided, we also added depth to our icon and made it a more appropriate smartphone style.

From Amazon, we got the toolset, instructions for creating icons in Autodesk Maya, and the finished sample.

Exactly repeating all the points specified in the instructions, we made the first version of the icon:



As you can see, the dies are located at a distance from each other, so that when we move we can see the displacement of some elements relative to others. Each die -
This is one of the “details” of Om Nom or the background of the icon. At a great distance and when turning the icon at an angle of up to 30 degrees, Om Nom's pupils noticeably shift, but remain within the eye.

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



And when it seemed that all the problems were over, the most interesting began.

First, errors when exporting the model to the vbl format:

1. [ERROR]: Skeleton: No bind up for the junction, create a ind keys keys keys keys keys keys keys.

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”. In the official instructions there is no such information.

2. [ERROR]: StateMachine: Detected self looping state transitions with 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 StateMachine editing, right-click on “State” and select “Remove Self Connection”.

There were also several problems, solutions to which we did not find, as well as we could not determine the steps to repeat them.

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

Since we could not solve the problem within the framework of the scene that was made according to the instructions, we took the ready 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 there was a 3D icon Cut the Rope 2 in the form we needed. And this is despite the fact that the sample scene was not, for example, described in the animation instructions.

Secondly, this error got out:

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

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

Developing commands for the widget

This is where our work on the icon ended, but we still had to figure out what to display in the widget. If the application does not install its own widget into the system, the standard list of products in Amazon that are close in subject 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 set up in the widget the display of game information - the number of collected stars, received medals and recently used elements, such as teleports or hints. These lines of the widget also allow you to navigate to the game level map, to the Amazon GameCircle achievement screen, and to several sections of the in-game store.



As reference materials, we had three Amazon training documents on the 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 the installation of the Fire Phone SDK. The problem was that the SDK only works with Android API not higher than 17, and we had to manually lower the version of the development environment (we could not do this automatically). This required deleting folders from the Android SDK and downloading 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 SDK from Amazon was not a big problem.

Next, you had to add the library connection string in AndroidManifest:
<uses-library android:name="com.amazon.device.home" /> 

The widget elements themselves are created from the program text. After creation, they need to be placed in lists and groups, and then they initialize the widget. Thus, widget elements get style, main, minor and tertiary text, as well as 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); 

Intent for a 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 framework ZFramework, which is used by our projects, the contents of the intents coming into the program are caught in onCreate () and onNewIntent (). We use the virtual intent handler IntentInterpreter in the framework, and at the level of this project - the widget from Amazon - a specific WidgetIntentInterpreter class for processing the intents of the widget.

We also had to take into account that, in contrast to the standard Android Intents, in the case of a widget from Amazon, only strings can be transmitted as additional data with an intent. Therefore, the abstract class of parsing events we got methods for translating between strings and event IDs:
 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 to the 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 event IDs and erasing them:
 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 only remained to calculate the event ID in the project using 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<jint>(env->CallIntMethod(JNI::eventDispatcher, meth, clearAfterRead)); env->DeleteLocalRef(cls); int result = jEventId; return result; } 

Reading a single request from a widget can be done several times in the program, so it happens without simultaneously clearing the event.

The algorithm for processing a widget request when the program is started is something like the following:

  1. The onCreate event of the Java class of the application processes the intent, receiving the request ID;
  2. The resulting ID is stored in the EventDispatcher event resolver;
  3. When creating the bootstrap screen, the request ID is read by the RootView class;
  4. The load screen receives the request ID as a parameter and, depending on it, selects the set of resources to be loaded;
  5. At the completion of the loading screen, a specific program screen is displayed, depending on the request ID.


We had a little difficulty with getting the right amount on deploying a collapsed application. At first this intent was caught by the onResume method, however this event restores the original intent with which the application was originally launched. We needed to receive new intent at each new deployment. The solution was to add properties to the application.

 <activity … android:launchMode="singleTop"> 

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

Other difficulties arose in processing special scenarios, for example, when the user interrupts the loading screen, minimizing the application, and then opens it again through another element of the widget. 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 by 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 loading should not start a new download, but simply continue the old one.

Another difficulty arose with dropping the OpenGL context when the application was minimized and opened using the widget. Loading a new view and restoring the context should not interrupt each other, and usually either one or the other is started.

Future prospects

Among the possible prospects for development is improving the set of commands for the widget. It is very easy to change it in the code, and then, using the code of the game, update the widget in the phone system when the game is running.

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

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



Well, as for experimenting with new technologies, this is a frequent practice in ZeptoLab, and in this regard, we have to reconsider the requirements for newcomers to technical tasks from time to time. In particular, we updated the test task for the C ++ developer position, and in order not to mislead the obsolete ones, we roll out its most recent version.

You must write a simple version of the classic game Asteroids:


Prototype requirements:


We are still accepting your test tasks at job@zeptolab.com around the clock.
We already wrote about how we check them. A little earlier, we talked a little about the developer training system 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 the Zepto-space.

Always yours,
Zeptoteam

Source: https://habr.com/ru/post/236867/


All Articles