$NEWTON64 :: {blog|games}
 
Moonlight, Jonas Kyratzes

Jonas Kyratzes has this thing where he writes pretty good: he and his games first won me over with The Fabulous Screech, and he pretty much picked up a lifelong fan with The Sea Will Claim Everything. The games are confidently-written, incredibly original, and possessed of this crazy, carefree, despairing, empowering life-force that mixes whimsy, nostalgia, surrealism, wonder, and really, they are very, very good.

His latest — Moonlight — brings the sweetness yet again. It’s been receiving some rather nice words elsewhere, so I’ll try not to be too redundant: it’s a dreamy game to be sure (it is literally a dream), but the feeling that struck me most was that of a new, enchanted, interactive improv theatre. It’s not some wild experience over which you have no control; instead, you point the way, and the game winks and says “Why yes, why wouldn’t we?” and away you go. It’s intentional, it’s effortless, it’s joyous. That this sort of improvisation can be felt in a browser-based, text-only game is remarkable.

Play Moonlight. Go on.

Unity and the Android API

WARNING: This is a rather technical post about something completely different and not at all about Red Rover.

Several Ludum Dares ago, I made a game called Oases about seeking refuge from wifi hotspots in the environment. I built this on a Windows PC (my laptop), since it seemed the quickest way for me to bang out the network code in 48 hours.

Surprisingly, it turns out that it’s not all that easy to run around town escaping wifi hotspots while holding a laptop with an old and dying battery.

Cue the rise of mobile, wifi-enabled devices, however, and things get interesting. I’m an Android man myself, and since I’m slowly coming to terms with Unity, I started some tests in getting the latter to call functions from the Android API.

It was not straightforward.

The tutorial on Unity’s site gave a number of techniques for calling Android’s basic Java functionality from within Unity’s C# context, through JNI and C/C++. Unfortunately, even after reading it through multiple times, I still felt that, while it gave a lot of background information, it wasn’t as prescriptive as I was hoping.

Long story short: after patching that tutorial together with several dozen desperate and increasingly-confused online searches, I managed to gain access, in Unity, to the information polled from my Android device’s wifi manager.

I present those steps here for truth, justice, and the American whey. Hope it’s useful, and do call me out on the inevitable errors.

Calling the Android API from a Unity application
  1. Download and install the Android SDK. Learn it, love it.
  2. Start the Android SDK Manager, and install the SDKs you want. Make sure to also install the Android Support Library listed in “Extras.”
  3. Download and install the Android NDK. Love it, learn it.
  4. In my own setup, I’ve got the above installed at C:\Android\android-sdk-(version) and C:\Android\android-ndk. Short paths simplify things. I’ll be referring to them as ${ANDROID_SDK} and ${ANDROID_NDK}, respectively (Oh, and your Unity installation is probably something like “C:\Program Files\Unity”, to which I will refer as ${UNITY}).
  5. Download and install Eclipse; make sure to get the C/C++ variant.
  6. Start Eclipse, and install the Android Eclipse plugin as per these instructions.
  7. Create your Android library; these are the Java functions running on the Android API side of things, returning device status &c. to…”the ether” (essentially, back to Unity). In my case, these are the functions accessing the device’s wifi state. In Eclipse, go to New -> Project… -> Android Application Project.
  8. Give the app a name (what your device will visibly call it — not really important to us), a project name (for use in Eclipse’s workspace), and an Android package name (see those notes on nomenclature). MAKE SURE TO CHECK “Mark this project as a library.”. I forgot this once, and couldn’t figure out why Eclipse wasn’t compiling a .jar library for me.
  9. Leave everything else as is and continue; accept whatever clipart is shown, create a blank activity, and finish the wizard.
  10. Navigate your computer to ${UNITY}\Editor\Data\PlaybackEngines\androidplayer\bin. You’ll find classes.jar — a Unity-to-Java helper package from the Unity folks themselves — which you should copy to your Eclipse project’s libs/ directory (that directory was created automatically with your Android project in Eclipse, and should be visible in the hierarchy on the left).
  11. In Eclipse, go to Properties -> Java Build Path -> Libraries, and add classes.jar to your library path.
  12. Eclipse generated some code for your Android activity. How very kind of it. It’s called something like ProjectActivity.java. We’ll have to make some changes though; most importantly, we no longer extend the Android “Activity” class — but we do pass in an Android context. I have reasons. In your auto-generated MainActivity.java source code (you may have, and still can, rename it as you like), you can have the following (with these particular members specific only to my endeavour):

    public class MainActivity { // does not “extend” anything

      private Context m_context;
      private WifiManager m_wifiMgr;
     
      // ———————————————————- CONSTRUCTORS
      public MainActivity(Context c) {
        m_context = c;
        m_wifiMgr = (WifiManager)m_context.getSystemService(Context.WIFI_SERVICE);
        return;
      }
     
      // ————————————————————— METHODS
      public boolean isWifiEnabled() {
        return m_wifiMgr.isWifiEnabled();
      }
    }

  13. As you can see, I need the general Android context, if I am going to have access to the WifiManager class. The same is probably true for a lot of Android’s *Manager classes.
  14. In Eclipse, make sure Project -> Build Automatically is checked. If so, you should have a ProjectName.jar file in your bin/ folder (again, this folder is auto-generated).
  15. In Eclipse, in your file hierarchy, make a folder called jni/ (it should be the same level as bin/, libs/, res/, &c.)
  16. Create a .cpp file in there. Call it anything you like; ProjectCppBridge.cpp is an option, as is Sheila.cpp.
  17. You’ll also need an Android.mk file in the same directory, and maybe (but probably not) an Application.mk file. I’ll admit my Android-Fu is a bit weak, so start your learning process here. Why not. My own Android.mk looks as follows:

    include $(CLEAR_VARS)
     
    # override strip command to strip all symbols from output library; no need to ship with those..
    # cmd-strip = $(TOOLCHAIN_PREFIX)strip $1
     
    LOCAL_ARM_MODE := arm
    LOCAL_PATH := $(NDK_PROJECT_PATH)
    LOCAL_MODULE := libjavabridge
    LOCAL_CFLAGS := -Werror
    LOCAL_SRC_FILES := jni/YOUR_FILENAME_HERE.cpp
    LOCAL_LDLIBS := -llog
     
    include $(BUILD_SHARED_LIBRARY)

    And Application.mk:

    APP_OPTIM := release
    APP_ABI := armeabi
    APP_PLATFORM := android-8
    APP_BUILD_SCRIPT := jni/Android.mk

  18. Now, the actual .cpp file, where you write all your JNI code, is going to be a bit complicated, so I’m going to just include it wholesale here.
  19. A few things to note. The JNI_OnLoad() function is called automatically; just use it to initialise things. Here, I get the running instance of Unity, find Unity’s hook to the running application/activity, and use that as a context to pass to the MainActivity class (which, as shown above, requires a Context argument in its constructor).
  20. I also define a function, _cppbridge_isWifiEnabled(). This function is called from Unity, and then passes the call along to the Android API, and then returns a value back to Unity. Important to keep track of where all these calls are going, and to make sure all the names are referring to the right things.
  21. Download and install Cygwin. You don’t need any specific packages, just the command-line interface.
  22. Open Cygwin and navigate (“cd /cygdrive/c/Eclipse/workspace/…”) to your Eclipse project directory (i.e., one above jni/).
  23. In Cygwin, run “${ANDROID_NDK}/ndk-build” (with the appropriate path typed in). This creates libs/armeabi/projectname.so in your Eclipse project directory.
  24. Now, finally, create your Unity project.
  25. In the Unity project’s Assets/ folder, create a directory called Plugins/, and within Plugins/ create another directory called Android/.
  26. Copy ProjectName.jar (from your Eclipse project’s bin/ directory) and projectname.so (from the libs/armeabi/ directory) into your new Assets/Plugins/Android/ directory.
  27. Copy ${UNITY}\Editor\Data\PlaybackEngines\androidplayer\AndroidManifest.xml into the same Assets/Plugins/Android/ directory.
  28. In the Unity script where you want to access the Android API, you must declare the following private references for every function you defined in your .cpp file:

    [DllImport("your_lib_name")]
    private static extern bool _cppbridge_isWifiEnabled();

    Note that “your_lib_name” is the name of the LOCAL_MODULE variable in your Android.mk file, without the “lib” prefix; or, it’s the name of the .so file you generated with ndk-build, but without the “lib” prefix or “.so” suffix. Also, the extern reference refers to the exact name of the C/C++ function we defined in our .cpp file.

  29. God, this blog.
  30. In Unity, go to File -> Build Settings…, and build your app for Android. You will end up with a .apk file, which you can then transfer to your device for installation and testing.
  31. A great way to debug your app is to fire up the DDMS. Plug your Android device into your PC via USB; open up a terminal (in Windows: Win-R, then type “cmd”); change to your ${ANDROID_SDK}/tools directory, and run ddms.bat; you should see a running list of all messages coming from your device. You can filter these in a number of ways: for instance, I prefaced all my error messages with “bagel,” so I could just search for that string. Look at the __android_log_print() function in the .cpp file provided above to learn more about printing debug messages.

Right. I think that’s just about complete, but feel free to give me a shout if something is missing/unclear/incorrect.

Now excuse me whilst I go rest my eyesies.

Blinking Totoro animated gif

Screenshot Saturday

I’ve been doing a lot of work on the back end of Red Rover lately (as usual), with a few digressions for various jams and Princes.

Most of the work was pretty much FPS fundamentals: that is, walking and pointing at things. This week, however, I finally got around to merging the old planetary rendering code from the teaser into this new framework.

Feels good to be back.

Image of Mars' terminator with the atmosphere trailing off to the night side. Stars shine above.

Stars shine above.

Screenshot Saturday

Physics and physics and physics again.

My calculations indicate that for a Stanford torus with a radius of 20m, simulating Martian gravity (3.711m/(s*s)) requires an angular velocity of around 2RPM. Which is right stately.

And walking around inside of one presents all sorts of interesting challenges to a physics engine.

Ship thumb

Nick Rudzicz; ‘Ship Study’
Programmer art on canvas, ESA star data. 2012.

Progress Resupply

So that’s a month then, is it. Strangely, Red Rover is not yet finished.

Work has been steady, if less than glamourous. At first, there was about a week of trying out new IDEs (I claim that MonoDevelop, faults aside, has probably the best autocomplete ever) and attempting to get a 64-bit Linux distro to compile 32-bit dependencies for a 32-bit OGRE library — with a few days to give up and just install a 32-bit Ubuntu on the laptop (and come up against the same linker problems regardless); a week or so of trying out physics engines — I desperately wanted to use Newton (for obvious reasons), but Bullet turned out to be a bit more mature and actively maintained (and more easily integrated with OGRE); a week of re-familiarising myself with Blender for eventual content creation (I swear, I’ve learnt the tool around five times already — at least now I have a longer-term reason to stick with it); &c &c &c.

In short, it’s been yet another sequence of black triangles commingled with the shaking of fists at the majority of things.

Fist shaking

Otherwise, KO-OP business is moving along briskly. Saleem is essentially constantly engaged with bankers and bureaucrats, and/or sweeping cat hair (note to self: Disney movie/game tie-in called Bureau-Cats, digitised Tony Jay voice as Cats); Bronson has been cutting his teeth on Pure Data and Unity; and we’ve had a number of artists hanging out in the office and producing some fantastic concept and promotional art (more on that in The Future).

So while the tasks are a bit mundane, this is still the first “steady” “job” I’ve held down with like-minded people. That’s motivating in its own right, and the fact that I’m seeing progress on the ground (however low-level) is the gravy on top of the cherry on top.

Blender tests