Battle Shock for Android is officially in the Android market now! The last few weeks were a challenge. We kept thinking we were close, and then we would find a hole in game play that would send us back to retune.
The first problem we found is that you just didn't need the archers to win the game. They were too expensive and weren't all that effective. Well we made the black knight and the black archers impervious to magic. So it's now required that you have enough archers to handle these menaces. But that led to a problem where you would run out of money for archers and a black knight would stroll on screen! So you were helpless and had to sit back and watch him hack up your castle. So now we notice that situation and spawn enough lite troops that you can win enough coins to buy some archers.
But then we noticed that the archers weren't all that accurate. Now that we are depending on the archers, it was super annoying when knights would march all the way to the wall unscathed when you had a full rack of archers. Well, a little work and wahlah, they were hitting knights in the helmet from nearly full screen distances. That's what I like, and archer that earns his keep!
But now the archers were updating the balance of the game. They were too powerful. And also we noticed that it would be nice in general if there were more progression to the spells of the game. So we added 10 levels instead of 3 for all the spells. This added a lot to the game and there was now more strategy in how to spend your coinage. But this had now become a tuning nightmare. The game would be hard till level 50 and and then become too easy once you had leveled up certain spells. So after a few more weeks of tuning, I think we have a gem for you.
Hope you enjoy all the hard work we put into the game. There's a lot of attention to detail. We are always interested to hear your feedback. Please let us know how you like the game!
AndroidPort
journal of a software port of an iPhone game to Android
Battle Shock
Check out Luna Sea Games to see the iPhone version of Battle Shock in the AppStore now.
Wednesday, December 29, 2010
Wednesday, December 8, 2010
Die app, die!
I think it really runs counter to the Android philosophy to actually kill your application when you leave it. That makes sense for email or web or times when you are jumping around to different lightweight tasks. However, a game is another animal. It consumes most of the resources of your phone. It's a high intensity activity and you are not doing email or mutli-tasking while you are playing. And when you are done, you're done! It's on the shelf. You will come back when you have time.
In my case, there was actually a very nasty bug that occurred when you left the app and came back. Somehow I managed to completely sieze up the phone making even the volume and power keys unresponsive. The only way out was to yank the battery! That's a hard lock. But it was actually just a pegged cpu. I could watch the usage spike on the task manager. I know it's my bug, but it's hard to believe that the os would allow a process to runaway like that.
Anyway, long story short, it was better for everyone if my app just quits when the users leaves. Accomplishing that took some research. Many people posted answers that didn't work for me. The one that worked was:
protected void onStop()
{
}
and then this would crash and throw up a dialog that my app had crashed and was ok to force quit. So to avoid that dumb message you have to add some permissions to your manifest so people know you can kill your own process.. not thrilled with the whole affair. Anyway, add this:
In my case, there was actually a very nasty bug that occurred when you left the app and came back. Somehow I managed to completely sieze up the phone making even the volume and power keys unresponsive. The only way out was to yank the battery! That's a hard lock. But it was actually just a pegged cpu. I could watch the usage spike on the task manager. I know it's my bug, but it's hard to believe that the os would allow a process to runaway like that.
Anyway, long story short, it was better for everyone if my app just quits when the users leaves. Accomplishing that took some research. Many people posted answers that didn't work for me. The one that worked was:
protected void onStop()
{
super.onStop();
//kill this process. It does not reload cleanly. And I think most users appreciate the app leaving memory.
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
String packageName = getPackageName();
am.restartPackage(packageName);
}
and then this would crash and throw up a dialog that my app had crashed and was ok to force quit. So to avoid that dumb message you have to add some permissions to your manifest so people know you can kill your own process.. not thrilled with the whole affair. Anyway, add this:
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
to your manifest, and you will have an app that behaves like 99% of the other os's out there.
Sunday, December 5, 2010
I can see the light
Just wrapped up the last of the issues I had to complete for this port. This weekend I knocked out the loading screen, memory leak on recycle, online score poster, assets larger than 1Mb, encrypting user saved files, and leaving a clean presence on the sdcard ( no sprites or temporary data ). All in all very productive. I'm lucky to have a wife that understands that sometimes I need to disappear in my office for two whole days...
There's really a lot I could share with someone doing a port. A lot of people seem to suggest that you should do a splash screen with an Activity. I didn't really want to do that because I want my main activity to keep focus. That's because it has the opengl surface - and since I want to be loading while we are staring at the pretty loading screen - I have to load textures in the thread of the opengl surface. Or rather, I need to bind them there. I guess I could load the data and bind them later. Oh well. I just made a custom dialog as a splash screen and that worked peachy.
And if you need to encrypt files it's really pretty easy. Here's an article on Sun's site that was helpful. Combine that with this and you have some really good leads on putting it all together. If anyone asks I can post the source.
In that same vein, if someone is looking to make an Android game that uses the cocos live site for highscores, I could share my port of their objective c code.
Hopefully you all will soon be able to play the finished product in an Android Market near you! Stay tuned for release dates.
There's really a lot I could share with someone doing a port. A lot of people seem to suggest that you should do a splash screen with an Activity. I didn't really want to do that because I want my main activity to keep focus. That's because it has the opengl surface - and since I want to be loading while we are staring at the pretty loading screen - I have to load textures in the thread of the opengl surface. Or rather, I need to bind them there. I guess I could load the data and bind them later. Oh well. I just made a custom dialog as a splash screen and that worked peachy.
And if you need to encrypt files it's really pretty easy. Here's an article on Sun's site that was helpful. Combine that with this and you have some really good leads on putting it all together. If anyone asks I can post the source.
In that same vein, if someone is looking to make an Android game that uses the cocos live site for highscores, I could share my port of their objective c code.
Hopefully you all will soon be able to play the finished product in an Android Market near you! Stay tuned for release dates.
Thursday, December 2, 2010
scruggly phone
I'm sure the G1 was a shining trophy of progress the day they first came out. But the one that arrived in the mail was beaten up, scratched, and eewwww.. slightly oily. I am the proud third owner of this cell phone that I bought off ebay last week. I got it just for development. And thank god, because I would hate to have to use it.
After a bath in windex, I plopped in the battery and fired it up. It wouldn't do anything without a sim card. It was stuck on an emergency dialer screen. I scrounged one from a pay per use phone I had lying in a drawer ( great for when the in-laws visit from Japan). Now it wanted me to sign up for a google account - and wouldn't let me get passed the regisration screen until I did. I had no cellular connectivity and it wouldn't allow me to setup the wireless connection. So I was stuck. I briefly worried that I had just purchased an $80 paper weight, and an fugly one at that.
Thankfully there are an army of people who have blazed this trail before me. There were online instructions on how to break into the phone without a cell account. For me it ended up being a long series of steps which was a combination of a bunch of different sites. I should probably list them all, but I don't have the energy. Basicly I had to downgrade the phone to RC29, then type in a code to enable adb connections - 'setprop persist.service.adb.enable 1', then fire up the wifi settings from an adb shell:
am start -a android.intent.action.MAIN -n com.android.settings/.Settings
Then setup wifi, go back to the phone registration and then complete the registration so I had access to the phone.
Now I had a 1.0 android phone with no attachment and no contracts! Yay. I needed to get to 1.6. This guide did the trick for me. An hour later and 4 flashes to the eprom and I had a usable phone at 1.6! I need it to be 1.6 because that's the earliest version of Android with OpenGLES support ( as far as I know ).
After that I downloaded my app and installed it on the phone. Fired it up.. and waited... and waited. Slowly the first menu came on screen. I hit the play button about 4 times. It was just slow to react. Slowly the screen changed. At about 1 frame per second, the bad guys dreamily came down from the top of the screen. I was now Flash and could issue 100 fireballs per each step of each guy. Clearly there are performance problems.
I was wondering how capable this device is. I downloaded the game Replica Island and I've tested on different phones and I know the author paid attention to performance. The game played fine. Maybe 20-30fps. And it was doing at least as much rendering as we. So clearly I'm going to need to do some digging. Good thing for me, the source for replica island is hosted on code.google.com!
After a bath in windex, I plopped in the battery and fired it up. It wouldn't do anything without a sim card. It was stuck on an emergency dialer screen. I scrounged one from a pay per use phone I had lying in a drawer ( great for when the in-laws visit from Japan). Now it wanted me to sign up for a google account - and wouldn't let me get passed the regisration screen until I did. I had no cellular connectivity and it wouldn't allow me to setup the wireless connection. So I was stuck. I briefly worried that I had just purchased an $80 paper weight, and an fugly one at that.
Thankfully there are an army of people who have blazed this trail before me. There were online instructions on how to break into the phone without a cell account. For me it ended up being a long series of steps which was a combination of a bunch of different sites. I should probably list them all, but I don't have the energy. Basicly I had to downgrade the phone to RC29, then type in a code to enable adb connections - 'setprop persist.service.adb.enable 1', then fire up the wifi settings from an adb shell:
am start -a android.intent.action.MAIN -n com.android.settings/.Settings
Then setup wifi, go back to the phone registration and then complete the registration so I had access to the phone.
Now I had a 1.0 android phone with no attachment and no contracts! Yay. I needed to get to 1.6. This guide did the trick for me. An hour later and 4 flashes to the eprom and I had a usable phone at 1.6! I need it to be 1.6 because that's the earliest version of Android with OpenGLES support ( as far as I know ).
After that I downloaded my app and installed it on the phone. Fired it up.. and waited... and waited. Slowly the first menu came on screen. I hit the play button about 4 times. It was just slow to react. Slowly the screen changed. At about 1 frame per second, the bad guys dreamily came down from the top of the screen. I was now Flash and could issue 100 fireballs per each step of each guy. Clearly there are performance problems.
I was wondering how capable this device is. I downloaded the game Replica Island and I've tested on different phones and I know the author paid attention to performance. The game played fine. Maybe 20-30fps. And it was doing at least as much rendering as we. So clearly I'm going to need to do some digging. Good thing for me, the source for replica island is hosted on code.google.com!
Wednesday, December 1, 2010
burning on both ends
Whenever my life gets busy, for some reason I take on more. No telling why. Got home, ate dinner, and worked till 1:30 on the port. But enough about me.
I tracked down the bug causing guys to get hung up in the corner. I also locked the orientation in portrait mode. This was needed. A small orientation change would issue a pause and resume and cause a reload of assets.
The most exciting development last night was the discovery of deviceanywhere. They have a large suite of mobile phones that are all wired up for a kind of remote desktop control. So you can upload your application to a real device, not a simulator - and perform automated tests. Very exciting! They even seem to be reasonably priced. If you are a one man show like me, be sure to check out their discounted rates for Independent Developers.
I was able to upload BattleShock.apk to a Droid phone in their cloud and run the application - and it worked! Unfortunately I still hadn't solved the deployment of the sprites from the package to a dir on the /sdcard so there were no graphics. So I decided to implement the simplest thing first - I copied all the assets from the internal package to the /sdcard/BattleShock dir. This is by far the simplest to implement and debug. Here's some discussions that were very helpful.
I also took the time to reduce all the audio assets to 8 bit wav and 48kbs mp3. This makes for a much smaller apk and improves turnaround time when developing. Highly recommend it.
And so, after getting the assets unpacking correctly I deployed the new app to the cloud... where it crashed. Bummer. Now I want to know if I can remotely debug. Though I can't even debug locally, at least I get a callstack. I think I will have to resort to a good old local text log file - printf debugging ahoy!
I tracked down the bug causing guys to get hung up in the corner. I also locked the orientation in portrait mode. This was needed. A small orientation change would issue a pause and resume and cause a reload of assets.
The most exciting development last night was the discovery of deviceanywhere. They have a large suite of mobile phones that are all wired up for a kind of remote desktop control. So you can upload your application to a real device, not a simulator - and perform automated tests. Very exciting! They even seem to be reasonably priced. If you are a one man show like me, be sure to check out their discounted rates for Independent Developers.
I was able to upload BattleShock.apk to a Droid phone in their cloud and run the application - and it worked! Unfortunately I still hadn't solved the deployment of the sprites from the package to a dir on the /sdcard so there were no graphics. So I decided to implement the simplest thing first - I copied all the assets from the internal package to the /sdcard/BattleShock dir. This is by far the simplest to implement and debug. Here's some discussions that were very helpful.
I also took the time to reduce all the audio assets to 8 bit wav and 48kbs mp3. This makes for a much smaller apk and improves turnaround time when developing. Highly recommend it.
And so, after getting the assets unpacking correctly I deployed the new app to the cloud... where it crashed. Bummer. Now I want to know if I can remotely debug. Though I can't even debug locally, at least I get a callstack. I think I will have to resort to a good old local text log file - printf debugging ahoy!
Monday, November 29, 2010
long day
I feel like I should have gotten more done for all the time I spent today. I did manage to get JSON queries against the cocos live service working. So the high scores are coming in. Reading JSON from Android was very helpful. As were the docs on HTTP services. Haven't gotten score posting working yet.
I was able to get the app to save and restore it's state. The key was to reload all the gl textures in the onResume - and to reset the variables that may refer to them in the onPause. You also have to be careful because the onResume will be called when the app first starts. So liberal protections from double init - double free, etc. Somehow I managed to break this in the last hour of working. Of course I don't have revision control setup. So this was the straw.
I create a git repository for all my local source. I usually always work with source control. Not sure what I was thinking. It's great to put a bookmark in when you have features working. I downloaded and built the osx client GitX. It's been a while since I used git and this made settings things up very easy.
btw, I wasted a lot of time tracking down the weird error. You find code like this in many examples. It doesn't work with Android SDK.
which will give this hoaky error:
error: request for member 'ReleaseStringUTFChars' in something not a structure or union
The fix for this is:
I was able to get the app to save and restore it's state. The key was to reload all the gl textures in the onResume - and to reset the variables that may refer to them in the onPause. You also have to be careful because the onResume will be called when the app first starts. So liberal protections from double init - double free, etc. Somehow I managed to break this in the last hour of working. Of course I don't have revision control setup. So this was the straw.
I create a git repository for all my local source. I usually always work with source control. Not sure what I was thinking. It's great to put a bookmark in when you have features working. I downloaded and built the osx client GitX. It's been a while since I used git and this made settings things up very easy.
btw, I wasted a lot of time tracking down the weird error. You find code like this in many examples. It doesn't work with Android SDK.
void Java_com_trial_filesys_SimpleTest_main(JNIEnv *env, jobject obj, jstring filename) { const char *fnameptr = env->GetStringUTFChars(filename, NULL);
env->ReleaseStringUTFChars(filename, fnameptr);
}
which will give this hoaky error:
error: request for member 'ReleaseStringUTFChars' in something not a structure or union
The fix for this is:
void Java_com_trial_filesys_SimpleTest_main(JNIEnv *env, jobject obj, jstring filename) { const char *fnameptr = (*env)->GetStringUTFChars(env, filename, NULL);
(*env)->ReleaseStringUTFChars(env, filename, fnameptr);
}
idea
The sales of BattleShock were pretty good on the iPhone AppStore but I started thinking about what could improve things, especially given the new launch on the Android Market.
I thought about different game play additions that might make things more interesting. I like the idea of building defensive burms and moats with my finger. I think the field should scorch and the grass should be burned away over time. A huge armored elephant or larger dragon should come out at some point. I'd like to see the enemy show more intelligence. Perhaps crouch behind some rocks that protect them from my magic. Then run scurrying out on the left as I attack on the right. But all these things will take a lot of time to implement.
I had a buddy who launched a free skateboarding game online about 10 years ago. It wasn't a fantastic game ( sorry man ) but he managed to get a pretty large following. The trick was to hold a weekly contest and offer free stuff from his sponsors. He got some skating gear from different companies and they in turn got some advertisement in his game. I'm not really one for advertisement in games, but I think the weekly contest could really help spread the word. I mean, how many mobile games can you play and actually win something? I bet if we put up $100 cash a week that it would attract at least that much in sales. And we could give small bonus points to referrals to encourage spreading the word. I was thinking that everyone in the top 100 point totals for the week would be in a drawing - not just the high score. And the more top 100 scores you had the better your chances.
I've never run a contest. So I know when money is involved there are rules. Gotta go do some reading...
I thought about different game play additions that might make things more interesting. I like the idea of building defensive burms and moats with my finger. I think the field should scorch and the grass should be burned away over time. A huge armored elephant or larger dragon should come out at some point. I'd like to see the enemy show more intelligence. Perhaps crouch behind some rocks that protect them from my magic. Then run scurrying out on the left as I attack on the right. But all these things will take a lot of time to implement.
I had a buddy who launched a free skateboarding game online about 10 years ago. It wasn't a fantastic game ( sorry man ) but he managed to get a pretty large following. The trick was to hold a weekly contest and offer free stuff from his sponsors. He got some skating gear from different companies and they in turn got some advertisement in his game. I'm not really one for advertisement in games, but I think the weekly contest could really help spread the word. I mean, how many mobile games can you play and actually win something? I bet if we put up $100 cash a week that it would attract at least that much in sales. And we could give small bonus points to referrals to encourage spreading the word. I was thinking that everyone in the top 100 point totals for the week would be in a drawing - not just the high score. And the more top 100 scores you had the better your chances.
I've never run a contest. So I know when money is involved there are rules. Gotta go do some reading...
Subscribe to:
Posts (Atom)