What I learned (and what you should know) about Luxe on Android

sign up sign in

Hi, for those of you who are not aware, I've recently released my next made-with-Luxe project, profectus.4. Needless to say, I've learned a lot, especially about working with Luxe on Android. So here's my share of newly found knowledge that I think all Luxe devs should be aware of, especially if you are going to taking your game onto Google Play Store.

Luxe.screen is not window.size

Contrary to HTML5 Web (in which screen size is the canvas size) and Windows (in which screen size is the window size, unless fullscreen), Luxe.screen is totally the entire screen of your Android device. Which means, without optimization, a game running on a resolution of 640 x 360 will run on only a small fraction, on the top left corner (according to engine's coordinates), leaving the majority of your screen likely to be blank, covered in whichever Luxe.renderer.clear_color is.

What you should do:

  • Pick an appropriate resolution you and your game is comfortable with.
  • Run the game in that resolution.
  • Cover only this area in your camera.
  • And change the camera viewport to the entire screen of your device.
class Main extends luxe.Game {

    // Game design resolution
    public static var w: Int = 1280;
    public static var h: Int = 720;

    override function ready() {
        // The following line changes the content of Luxe.camera
        // to the previously picked design resolution,
        // which is 720p
        Luxe.camera.size = new Vector(Main.w, Main.h);
        // [the rest of your ready() code here]
    }

    override function onwindowsized ( e:WindowEvent ) {
        // While I'm not an expert to understand the system under the hood,
        // I believe this line overrides one of luxe.Game callbacks,
        // resetting the camera viewport (a.k.a. what you see from it)
        // to the entire screen width and height
        Luxe.camera.viewport = new luxe.Rectangle( 0, 0, e.event.x, e.event.y);
    }
}

I wrote these lines a long time ago, and can no longer remember the details, but the idea is there, and I believe that it is useful if you want to make a HTML5 game that adapts to the window size as well. Let me know if I made any mistake.

Your package name must be unique

This should be on developer's note 101, but I just want to mention here for the sake of completeness. Whichever your package name is, com.mycompany.mygame, it must be unique across the entire Google Play Store to be accepted. So if you are going to modify an open-sourced project and release your own version, do not make the embarassing mistake of releasing the same package name.

To set your package name, change it in the project.app.package node in project.flow

{
    project : {
        name : 'My Art Game',
        version : '1.0.0',
        author : 'New indie dev',

                app : {
                    package : 'com.newindiedev.artgame'
                }
        },
}

(A handful of years ago, to my horror, I found a game with the package name, something like com.badlogic.drop. To those who are not aware, this is the beginner's example for the renowned engine LibGDX. Whoever felt proud, of his minor modification to the game's graphic, enough to release the game as his own, didn't even bother to change the package name to his own. Yuck.)

Your submitting version code must be higher than previous submissions

If you are new to Android without any experience of publishing an app before, you are likely to run into a rejection from Google Play when trying to update your app for the first time. This is not the user-end version number (usually in the form of 1.x.x), but an integer and a part of Android package info.

A version code is an incremental integer value, natively designated in AndroidManifest.xml (an info sheet for Android app, if you are curious). Your version code is 1 by default to Luxe, and without modification, submitting an update with version code of 1 will not be accepted by Google Play Store.

(In OpenFL, according to my experience, this is automatically added up everytime you compile the Android version, so your first submission will likely to be in the hundreds, and your next update will be much higher, depending on how frequent you are testing)

In Luxe, this can be set manually, but this is a feature entirely undocumented (well, still alpha, people). Not until I spoke to Sven himself, did I find out that this is supposed to be set manually by the gamedevs ourselves.

So here you go, the magic hidden secret, the property number of node build in project.flow:

{
    project : {
                [...]
                app : {
                    [...]
                },
                build: {
                    number: 4,
                    [...]
                },
        },
}

You need to sign your app before submission

Unless you're a first-timer, you're already likely to have your own keystore (I won't delve into the basic, since this is universal everywhere as long as you need to be on Android), and in case you're not sure what it is for, your submission package must be constistently signed by you. Think of it as a highly protected company stamp to confirm an app that it is authentically yours. You may use multiple keystores, but managing them would be painful. Also, an app cannot be updated if keystores between versions are inconsistent.

Well, the tricky part is, how get Luxe to sign it. Fortunately, you've got that documented this. So I'm just trying to make clearer here.

If you want to test a new feature or something new on your device, flow run android will do just fine. But you'll be doing about 80% of debug builds and the rest 20% for release build, so it's not ideal to back and forth modify your project.flow for such purpose, and this is where defines comes in.

Here's the important bits:

{
    flow: {[....]},
    project: {[....]}.

    if: {
        android_release: {
            app: {
                mobile: {
                    android: {
                        build_type: "release",
                        keystore_path: "NewIndieDev.keystore",
                        keystore_alias: "NewIndieDev"
                    }
                }
            },

            build: {
                defines: ['no_debug_console']
            }
        }
    },

}

To use this define, run flow build android --d android_release. What it does is to build with the parameters and properties set under the define of android_release in project.flow. What this define android_release does is to set the build_type (which is essential), assign paths to your keystore for signing purpose, and remove the debug screen (togglable with a four-point touch, and I didn't remove that for my first final version of my game as well).

Speaking of keystore and signing thingy, here comes the next part.

How to store passwords

Sigh, reminded me of the agonizing session I had with Sven again

Setting your build_type and paths to your keystore is not enough. Your keystore has a password (passwords, actually). Upon building, flow will look for a file named passwords.sensitive.properties to automatically pass the passwords onto ant. If that fails, the you're likely to end up with a release-type package, but unsigned (and definitely ineligible for submission, but you can still use jarsign to manually sign it yourself, if you know how to that is). That or some type of errors.

You may avoid entering passwords everytime by leaving your password in a properties file. For the sake of simplicity, the file I'm talking about is called passwords.sensitive.properties (which is a plain text file) and is left in your project root folder, the same with project.flow (you can certainly change that once you've understood how things work).

Here's the kind of the content of passwords.sensitive.properties :

#high security risk
#do not share this
#do not make this public
#do not commit this onto any repo
#keep it to yourself

key.store.password=newindiepassword  
key.alias.password=newindiepassword  

(I accidentally had two spaces after my passwords last time and had a wrong password error message, so make sure it does not happen to you either)

To make this file work, you'd have to ask flow to copy this onto output android project folder. Do this by adding a file property under the node build:

{
    project : {
        [...]
        app : {
            [...]
        },
        build: {
             files: {
                keystore_things : 'passwords.sensitive.properties => project/passwords.sensitive.properties'
        },
    },
}

If everything goes right, and together with the flow build android --d android_release, you should have a fully signed yourgame-release.apk in the bin folder of your project root folder. If it doesn't, well, read this and the previous heading again and especially Sven's guide again.

Closings

So that's it so far. Except for the first (which is important as well, to be fair), all the headings I wrote are essential to publishing and maintaining an Android apps. And here's hoping that your Android launch is less bumpy and angonizing than all of mine have been :D

If you have a question or something to share or I made some mistakes or whichever it is, leave a comment below, and I'll see what I can do.

Also, I'd have a full post-moterm from a general developement for profectus.4 soon, so stay tuned :D

Postscript: SDK; apache-ant; hxcpp and NDK

Following the Android launch of profectus.4, I started working on the iOS version, which got me into buying a Mac and setting up everything all over again. The processes of setting up on Mac or Windows are not that distinctive, but doing this again did and remind me of how much all of an anguish it had been. No one should be suffering that much, and here I am, giving these fellows a deserving header in this post.

So here's your free DLC.

SDK and ant

This has been documented in the official guide. Whether you are on Windows or Mac, the processes involve downloading the correct platform versions, extract them to preferrably-not-very-complicated directory paths, and leading flow to them.

I did mention many times over, and even in my Luxe template, that you may use the node flow.build.android to specify paths to Android SDK and ant. However, once I've worked from multiple machines, I realised that it was very inconvenient, since setup paths are different in each working location, especially when they are running on different platforms.

So, the solution is to setup a default setting for flow look for these things. This can be done by:

flow config build.android.sdk /path/to/sdk/without/quotes  
flow config build.android.ant_path /path/to/ant/bin/without/quotes  

(On Windows, you need to point ant_path to apache-ant\bin\ant.bat instead of just /apache-ant/bin/ant like on Mac)

Once set, you can check for config settings with the same command, but without argument:

flow config build.android.sdk  
flow config build.android.ant_path  

What these commands do is to create a .flow.config.json in user directory (C:\Users\yourusername\ for Windows and /Users/yourusername/ for Mac. Once created, it will always check for custom settings upon building (and upon you asking to see them).

For some reason, on my Windows machine, I ran into a localised problem that prevented me from successfully. So far, no one else reported of the same problem, but the workaround is simple: to create the customised settings yourself without going through flow. In fact, this is the method that is more bug-proof than official way. Simply create a .flow.config.json at the respective directory (depending on your platform) I've mentioned above with the following content:

{
    "build": {
        "android": {
            "sdk": "C:/Android/android-sdk-windows/",
            "ant_path": "C:/Android/apache-ant-1.9.4/bin/ant.bat"
        }
    }
}

Naturally, this is an example for Windows. Change the paths accordingly to your platform and setup.

(If you are on Mac, do note that TextEditor will change those quotes into fancy characters, which will ruin the whole format (very visible with syntax highlights on). Use a decent text editors, preferrably with the one you code with. There are plent of them. There I was, wasting two hours, believing that Windows' Notepad was the only thing that sucked)

For you references, those quotes, created and edited by Mac's TextEditor right before my eyes, were what ruined my day. The contents were not wrong, just the wrong kind of quotes. Sigh.

{ "config": "1.0.0-alpha.1", "build": {
        "android": {
            "sdk": “/Users/mtngx/AndroidDev/android-sdk-macosx",
            "ant_path": "/Users/mtngx/AndroidDev/apache-ant-1.9.6/bin/ant”
        }
    } }

Those two should be easy. Here's our next man.

hxcpp (and prologue to NDK)

Here's the part that went undocumented. If you attempt to build Android, flow will ask for hxcpp, something that should be familiar with those who were with OpenFL at some point. Simply ask haxelib to get it:

haxelib install hxcpp  

Problem: you need to configure hxcpp, specifically with Android NDK. More problem: there is no built-in configuration tool for hxcpp. Sigh.

You know what I did last time, as a noob coming from HaxeFlixel? I got the whole openfl thingy from haxelib. I run the configuration for Android as if I was building something with HaxeFlixel or OpenFL. Then forgot about it. Just for hxcpp to know where I keep my Android SDK and stuff. Totally overkilled. Sigh. Also, if you're moving in from HaxeFlixel or HaxePunk with hxcpp well configured, you have most likely got this covered.

How config in hxcpp works: it looks for a file named .hxcpp_config.xml. This file, ironically (probably Sven's intention), is found in the same place with .flow.config.json mentioned above, in your user directory (again, C:\Users\yourusername\ for Windows and /Users/yourusername/ for Mac).

If this file is happened to be missing, this is likely because you have not ran hxcpp ever. Simply haxelib run hxcpp once for this file to be generated.

Are you done? Of course not. Flow will throw error about some ANDROID_NDK_DIR. Well, because Android. So here we go again.

(true) Android NDK

I am a bit too tired for fanciful literary narrative, so here is the story skipped to the ending, with much anguish and journey of a hero: In .hxcpp_config.xml, there are two important lines, or variables you should be caring about:

<set name="ANDROID_NDK_ROOT" value="/some/paths/" />  
<set name="ANDROID_NDK_DIR" value="/moar/weird/paths/" />  
  • ANDROID_NDK_ROOT sets the path to use a very particular version of Android SDK, and point straight to the potus himself, in format of value="C:\Android\android-ndk-r10e\".

  • ANDROID_NDK_DIR on the other hand, in attempt to act smart, points to a folder contains many versions of NDK, so it can pick one from many contenders. value="C:\Android\ndks\" whose contains android-ndk-r10e; android-ndk-r9d; android-ndk-r6c; etc.

Even though the error points to ANDROID_NDK_DIR, focusing on it was got me into the wrong direction (figuring out what it was was the hard part). If you are just happened to be so stuck and desperate that, you are now scrutinizing every word I'm writing here, trust me, just comment out that line about ANDROID_NDK_DIR, and forget that it exists.

At the time of writing, which is August 2015, Android is still a messy place with incompatible Android NDK versions here and there. There are lots of bugs. Things are in uncertain transitions. I can tell you that android-ndk-r10e did not work for me, and I published my first luxe game (probably even first published made-with-luxe Android game) with android-ndk-r9d.

If you are not some hardcore and competent C++ geek (whom I don't think would be reading me this closely), you are not from very distant future (Android is still messy and r9d is still relevant), you make sense of the [nonsenses] I have been talking about, and you just want to get your game compiled to Android, here's what you should do:

  • Get android-ndk-r9d (I don't think Google still keep it on their servers. Well, just google it.) and extract it reasonably.
  • Edit that variable in .hxcpp_config.xml into <set name="ANDROID_NDK_ROOT" value="C:\Android\android-ndk-r9d" /> or something that make sense for you. Comment out the rest.
  • Hope that nothing more will go wrong.

So there you go. That will get your game compiled. You may now enjoy a spinning orange square against a grey background on your phone.

Also, painful, isn't it? Such journey of a hero. I'm just too tired for a second closing. Shoot your question down there or wherever you manage to find me.

Tags
luxeflowandroid