Phil Hassey - game dev blog
Phil Hassey as Syndrome
"Look, stores don't sell
costumes like this to just anyone."

Archive for the 'android' Category

Getting ENet to work with Marmalade

Thursday, August 8th, 2013

Through a bit of Googling and whatnot, I got in touch with Joe Delgado who was able to provide a patch to fix ENet to work with Marmalade. These are modifications to unix.c. When I am making a Marmalade build of my games, I always have PLATFORM_MARMALADE defined. So you can replace that with whatever you do.

After the #ifdef __APPLE__ segment, add this to set up the correct defines, etc.

#ifdef PLATFORM_MARMALADE
#define SOMAXCONN 128
#undef HAS_POLL
#undef HAS_MSGHDR_FLAGS
#undef HAS_FCNTL
#include <sys/select.h>
#include <sys/uio.h>
#define HAS_SOCKLEN_T
#endif

In enet_socket_send, it turns out the Marmalade sendmsg is broken. So I replace:

    msgHdr.msg_iov = (struct iovec *) buffers;
    msgHdr.msg_iovlen = bufferCount;
    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);

With

#ifdef PLATFORM_MARMALADE
    // concatenates buffers together

    ENetBuffer * newBuffers;
    char* d;
    int i, totalSize;

    newBuffers = (ENetBuffer*)malloc(sizeof(ENetBuffer));
    totalSize = 0;
    for (i=0;i<bufferCount;i++) {
        totalSize += (buffers+i)->dataLength;
    }

    newBuffers->data = malloc(totalSize);
    newBuffers->dataLength = totalSize;
    d = (char*)newBuffers->data;
    for (i=0;i<bufferCount;i++) {
        memcpy(d, (buffers+i)->data, (buffers+i)->dataLength);
        d += (buffers+i)->dataLength;
    }

    msgHdr.msg_iov = (struct iovec *) newBuffers;
    msgHdr.msg_iovlen = totalSize;

    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);

    free(newBuffers->data);
    free(newBuffers);

#else

    msgHdr.msg_iov = (struct iovec *) buffers;
    msgHdr.msg_iovlen = bufferCount;
    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);

#endif

And that seems to get ENet working 100% with Marmalade. I applied this patch to ENet 1.3.6 … The original patch was written for ENet 1.3.3, and I suspect it would work for the latest version of ENet. I built this with Marmalade 6.3.2. I’ve passed on a request to the Marmalade team to fix sendmsg so that the larger chunk of the code would no longer be necessary.

-Phil

Invasion of the Blobs & dev toolkit in the works

Friday, May 20th, 2011

Hey,

A few weeks ago I entered the Ludum Dare game development contest and whipped together a fun game about defending off invading blobs using a spray can.

I spent another week getting it polished up so it works on a ton of platforms. The game is “The Invasion of the Blobs” (iBLOBS for short). You can get it here. It’s available on iPhone/iPad, Android, PC, Linux, Mac, and pretty soon the Mac App Store.

The reason for the porting frenzy with this game is I’m working towards releasing an open source C++ toolkit for supporting all these platforms (and maybe a few more). This is my first game release with this kit. It uses code from all my recent games, but it finally puts that code into a clean and organized re-usable structure. This is going to be super helpful for reducing bugs and improving game code across each platform.

Anyway, I hope you enjoy iBLOBS. It’s totally free, so you might as well give it a whirl. If you want to help out, please post a message here if there are any crashes or support issues on any platform, I want to get those ironed out best I can 🙂

Have fun!
-Phil

UPDATE: The Android port has been giving quite a few people trouble. If you are a dev with the Android dev kit, please do an “adb logcat” and post the results here, that would be a huge help!

UPDATE2: The Android build is so broken I took it down.

Android threading tips

Thursday, May 12th, 2011

Hey,

I still don’t completely understand how the Android threading works. So that explains some of why my code sometimes has trouble. Here’s a good article on deadlocking in Java.

In a Activity + GLSurfaceView there are at least two threads in operation. In my code I synchronize all my native methods. Some of my native methods have to call back to Java to load textures, play music, etc. I’ve found in certain cases a deadlock occurs. My guess is that the deadlock happens when:

– I’m receiving a touch event and I’m trying to call my native code with the event data
– I’m rendering a scene and it is trying to load a texture.

My guess is that loading a texture is trying to acquire a lock that the Activity thread has locked, while the Activity is trying to send an event to the native code which is locked.

Here are ways to push code onto the other thread so that you can reduce the amount of synchronized type deadlocks.

Putting a item on the Activity / UI thread

            myActivity.runOnUiThread(new Runnable(){
                public void run() {
                    /* do something in the Activity UI / thread */
                }});

Putting an item onto the GLSurfaceView thread

        myGLSurfaceView.queueEvent(new Runnable(){
            public void run() {
                /* do something on the GLSurfaceView thread */
        }});

Anyway, hope that helps!
-Phil

Galcon Android bugfix update & sale

Thursday, March 31st, 2011

So I’ve been working on an Android tuneup for Galcon over the past couple days. Here’s what’s been going on:

– Some users were having the game hang on them when the phone went to sleep. There were two issues here, one was a deadlock situation because I had onPause “synchronized” and I wasn’t using the wakelock to keep the device from falling asleep. I fixed the deadlock and I added the wakelock feature so that the device does not fall asleep while you are waiting for a round to end or whatever. To sleep your device you have to press the sleep button now.

– In Android 2.3.3 the ability to scroll up and down the server list was somehow broken. It seems that the ability to track motion was somehow changed in the new version. Also, my code in the previous version didn’t handle things well anyways. So I’m just tracking motion manually and that seems to have fixed the issues in the game.

– I’ve also tested Galcon on the Xoom and it works pretty well!

I hope you enjoy the update! Please tell me if there are any odd side-effect issues that result from the fixes I’ve put in.

… And to celebrate, Galcon for Android is on sale for $0.99! So now would be a good time to spread the word about Galcon on the Android!

-Phil

P.S. A special thanks to Google for giving me a Xoom tablet at GDC! It’s great having the whole gamut of Android devices to test on now 🙂 The devices I have are the G1, Droid, Nexus One, and Xoom.

Galcon Fusion comes to Mac App Store and Mega-Sale!!

Wednesday, March 16th, 2011

Hey,

Galcon Fusion is available now on the Mac App Store at the amazing launch price of 99c – that’s 90% off the regular desktop price!

I’m also doing a Mega-Sale across many of the other versions of Galcon! Be part of the “Galcon Community Rejuvenation Project” and help get the word out about this Mega-Sale:

Galcon Fusion for the Mac – 99c – Regularly $9.99

Galcon Fusion for the iPad – 99c – Regularly $4.99

Galcon for the iPhone – 99c – Regularly $2.99

Galcon Labs for the iPhone – 99c – Regularly $2.99

Galcon for Android – 99c – Regularly $2.99

Have fun playing!
-Phil

Galcon looking for an Android publisher

Monday, November 1st, 2010

The Android market is kind of crazy! There are dozens of markets out there, and I’m only tapped into the “Google Android Marketplace”. I’d like to get a publisher or someone who could (for a reasonable cut) get Galcon onto all the other markets, and manage all those opportunities. I get lots of emails about various opportunities, but doing all that bizdev / tweaking the game to work for various other market places is just not something I can do right now.

If you know of a good one, or are a good one, let’s talk!

-Phil

P.S. if you’re an indie developer who has put their game on all these platforms and want to take on Galcon, I’d be open for that kind of option too!

P.S.S. given it a bit further thought, I think what I’m looking for is a Android bizdev person, actually.

Android Day 11 – Troubleshooting

Friday, August 27th, 2010

Hey, so Galcon has been on the market for about a week and some. I’ve gotten plenty of feedback, so it’s time to do a bugfix update to address a few issues.

Item 1 – Backspace doesn’t work with Swype keyboard.

This is because the Swype keyboard is broken. Amusingly enough in earlier betas it wasn’t broken, but the latest one that everyone seems to have is broken. If you are part of the Swype beta you should send them feedback pointing out that the backspace key doesn’t work with some applications because the Swype keyboard is failing to send onKeyDown and onKeyUp events when users press the delete key.

As a workaround, I’ve added a message on the Settings page to tell users “Tip: you may have to switch to the default keyboard to press delete” .. Another solution would be to have a dialog pop up that they can do text input into. A fellow Android dev has outlined how to do this.

Item 2 – Application won’t install

The Android Market has some oddball bugs here. Beats me what is actually going on but the advice I’ve heard is:

1. Launch “Google Talk” .. That may help.
2. Reboot your device. That may help more.

Anyone got any other tips on this sort of problem?

Item 3 – The License check fails

So it seems that when the network isn’t on, the licensing check sometimes fails. This causes user rage. To remedy this, I’ve adjusted the dialog that pops up to include a Retry button and further explanation. “Tip: if you have purchased this application, press Retry a few times. It may take a minute to connect to the licensing server. If that does not work, try rebooting your phone.”

Item 4 – Crashes when starting up the browser

I’ve gotten reports from a few users about the game crashing when receiving calls or when they go to a browser. I have been unable to reproduce this issue locally. If anyone has more details on this, I’d appreciate whatever they can come up with. If you can send me a copy of the Android log, that would be helpful too!

Item 5 – Screen stretched

Since this is an exact port of the iPhone (480×320) version of the game, this was a choice I had to make. It was either a stretched screen or letter-boxing. I decided a stretched screen would be the better of the two evils. The reason this is an exact port of the iPhone version is that makes it cross-platform compatible with the iPhone for multi-player games! No matter what option I take here, it isn’t going to be ideal because everyone has to have the same map on their screen to be able to play against each other. This is the cost of being on a platform with no standard screen sizes or aspect ratios.

Anyway, I’m pleased with the update. I wasn’t able to fully correct everything since most of these issues are out of my hands, but at least I’ve added some textual tips that should help people get through the main issues (#1, #3). #2 unfortunately I’ll have to continue to handle via support emails since the game isn’t even starting at that point. And again, if anyone has #4 affecting them, I’d appreciate more feedback.

-Phil

Android Day 10: Implementing License Server

Wednesday, August 18th, 2010

So .. License Server came out about a week ago. When I heard about that I was all, “eh, more DRM, why bother, the users won’t see any benefit, so it’s not worth my time.” Turns out I got that wrong! There are actually several concrete benefits to the user by using the License Server (which I found within a day of releasing Galcon due to the quantity of emails from users explaining my failure to care about them!) If you use the “Copy Protection” feature of the Android Marketplace publisher, you do two things to the user:

– The app will take up twice as much room.
– The app cannot be stored on the user’s SD card.

I covered some of this in a previous blog, but the users memory is very limited, so over utilizing it is a “bad thing”!

The documentation for the Licensing Server is really really long looking, but there isn’t that much you have to do, actually. You’ll probably want to read it, but if you want the synopsis of what you actually end up having to do, here it is:

Step 1: Install the LVL SDK.

You just power up the SDK installer software and find the “Market Licensing package” and install that.

Step 2: Copying the LVL SDK into your project.

Just copy path/to/android/market_licensing/library/src/* into your local src/ folder. The SDK isn’t part of the Android platform, so you have to include it in your own codebase.

Step 3: Get your app to check the license using a Policy.

You can do some complicated things, but the documentation says, “… don’t do that. Just use the included ServerManagedPolicy or StrictPolicy.” I’m going to use the ServerManagedPolicy because that doesn’t require the user to ALWAYS be on-line to use your App. The StrictPolicy only works when the user is on-line and checks the license every time.

At this point, you’ll want to just go find path/to/android/market_licensing/sample and check out the source there. It includes an example that will pop up a dialog to send the users off to buy your app if they don’t have it licensed properly. This seems to be pretty much what I want, so I’ll just copy-n-paste from that.

Tips:

– To grab your public key go to http://market.android.com/publish/ and click on “Edit Profile” and your key is at the bottom of the page.

– You’ll (maybe) want to grab the example res/values/strings.xml and paste the Licensing related strings into your own strings.xml

– applicationError(ApplicationErrorCode errorCode) should call dontAllow()

– add finish() after the app goes to the market Intent. This way, they can’t go back to the app and get pestered about buying it again. They will have to restart the app and the license will check out fine.

Step 4: Testing it out

You can test out your app by again going to http://market.android.com/publish/ and clicking on “Edit Profile” .. at the bottom you can add market user emails that are being tested and you can change what license response you want to force out to the user.

Tip: be careful not to hit the licensing server too often, or you’ll start getting 503 errors which indicate overuse of resources. These take a while to reset.

Step 5: Adding a demo mode

You may want to add a demo mode to your game if licensing fails. Or somehow stop the game entirely, because the AlertDialog seems to be full of “holes”. That dialog will disappear and reveal your game under a number of scenarios. So don’t count on it blocking the user.

I just recall showDialog(0); in onTouchEvent if the game is in demo mode to keep bringing up the dialog again. I suppose a less annoying way to do it would be to respawn the dialog every minute or something. But maybe I’ll do that later!

Step 6: Applying ProGuard code obfuscation

This step is highly recommended by the Android developer guide. It would be nice if this were built into the Android toolchain, but it isn’t. Here’s a blog post that tells you how to do this.

However, I found that the binary that got build crashed. I’m not sure what is going on, but I’m guessing the NDK and ProGuard just aren’t getting along somehow. I’m going to leave out ProGuard for the time being. (I gave this a few hours effort. Again, this is where having support as part of the Android developer’s kit would be great!)

Update: this blog post explains what you need to do. Beyond that, you also need to handle your native methods and callbacks properly.

Step 7: Enabling Install on SD Card!!

This step is basically the whole point of this entire blog post. This gets the app out of the main memory on the device and onto the SD card for the user’s improved happiness.

To do this, add android:installLocation=”preferExternal” to the manifest tag in AndroidManifest.xml

Also change target=android-8 in default.properties.

And that’s that!
-Phil

Galcon for Android has ARRIVED!

Monday, August 16th, 2010

Hey, it’s been a wild ride, but the Android edition of Galcon has ARRIVED!

newandroidshot

qrcode

Have some fun! Be sure to tell your Android toting friends that this is the real deal! This now puts Galcon available on about 70 new types of phones! Crazy!

-Phil

P.S. If the links don’t work, just search for “GALCON” in the store :)

P.S.S. I’ve updated the links so they should work now :) Thanks to everyone who emailed me how to do that!

Android Day 9: Taming the G1

Saturday, August 14th, 2010

The G1 is the baseline Android phone. I found that users who tested with one of them were getting low framerates and crashes. Since the G1-level-devices are about 20% of the market, I wanted to be able to support them. Here’s the journey I took:

Step 1: Getting and activating a G1

Getting one was relatively easy. They are no longer produced, but I found a good one on eBay and with shipping and everything it was only $137 to get it. Activating was another matter altogether. The phone is locked so that you have to sign into your Google Account upon startup to activate the phone in order to get to the Home screen. After reading numerous tips on the internet, the way I was able to activate it was by borrowing a friend’s SIM for a few minutes to activate my phone. Then I put a dummy SIM back into mine and things worked fine.

Step 2: Fixing crashes

As I’ve found, the event loop and the graphics loop are in two separate Java VM’s on the phone. Some tweaks I had added to get it working on the Nexus One / Droid were not working on the G1. Again, global variable hacks coming back to haunt me. I adjusted some of my hacks and it seems to be working on the G1 now, so I’ll have to re-test on the Nexus One / Droid later. The lesson here, again, is avoid using globals in C if you can, because a lot of how the whole Android setup is makes it a real pain.

Step 3: Graphics performance improvements

The graphics were going at about 2 FPS. Which was not acceptable. I did a lot of investigating and I found that this one thing got me from like 2 FPS to an acceptable (though not blazing) 15 FPS or so. I changed my bitmaps from their default format to ARGB_4444. I do this during my load_texture method:

Bitmap bitmap = BitmapFactory.decodeStream(stream).copy(Bitmap.Config.ARGB_4444,false);

That was all it took! However, I’d like to have it be ARGB_8888 on higher-end phones if possible. I’ll see if I can figure out a way to do that. It’s a bit of a tough call, because on the Droid the 4444 improves the framerate, but if you look closely you can see a difference from the 8888.

One way would be to detect the SDK version, however, I hear rumors that older devices might be getting an update to 2.x. So that wouldn’t be foolproof either. I think I’ll be sticking with 4444 for now. It improves the framerate on most devices and the visual change is pretty minor in the larger scheme of things.

Step 4: Removing warnings about “call to OpenGL ES API with no current context”

These warnings are just annoying. Basically they happen anytime you do a gl call when you aren’t within your rendering method. It took some hunting but I found a few calls that were doing this in my Pause pop-up screen. This was simply a job of decrufting my code a bit. (I had OpenGL code that was from the very first version of Galcon for the iPhone that was being called in code that isn’t supposed to have any rendering in it anymore.)

I think I’m getting pretty close to releasing this game. I’m going to run this build by the testers again and see how they like it. I hope to launch soon!

-Phil