Cautionary Tale: Always lock your Arrays in game development - Android Software Development

Thought I would record my troubles with a game render loop and a logic engine given a particular bug has swallowed up about a week of my time. I am posting it incase anyone else happens to have the same problem/symptomns.
It originated when I wrote the LogicEngine which has an ArrayList of GameObjects and iterates through them deleting them as nessesary depending on the results of thier processStep.
The render thread would occasionally crash when something was deleted from the array while the list was being drawn but this happened quite rarely. No problem I thought, I'll just catch the out of bounds exception and it will get displayed on the next frame however many milliseconds later.
This all went well for 3 months of coding till I got to programming terrain where about 300 blocks were all displayed gradually scrolling down the screen. The blocks would flash intermittently but in sections not all at once.
At first I thought it was too many blocks for the LogicEngines collision detection so I doubled the size of the blocks. Then I thought it might be overhead allocating memory for the blocks and preloaded them in the constructor. Eventually in despair I disabled the deletion of blocks once they went offscreen and noticed the flashing stopped. This was the point I realised what was happening: The LogicEngine would delete a row of blocks because they went offscreen and the Renderer would be half way through drawing and instead of crashing it would just skip x blocks wherever it was in the for loop at the time that the LogicEngine removed them.
Wow I feel stupid, especially because of the lazy Exception catching solution I originally implemented which masked the problem for so long.
Code:
GameRender.java
//draw obstacles
theLogicEngine.objectsObstaclesLock.writeLock().lock();
for(int i=0 ; i<theLogicEngine.objectsObstacles.size();i++)
{
drawObject(theLogicEngine.objectsObstacles.get(i));
}
theLogicEngine.objectsObstaclesLock.writeLock().unlock();
LogicEngine.java
for(int i=0;i<objectsObstacles.size();i++)
if(objectsObstacles.get(i).processStep(this)) //we are to delete this object
{
objectsObstaclesLock.writeLock().lock();
//remove self if necessary
//move object returned true so delete object
GameObject toDelete = objectsObstacles.get(i);
objectsObstacles.remove(i);
toDelete.dispose();
i--;
objectsObstaclesLock.writeLock().unlock();
}
TLDR: If you have an ArrayList that can be edited by one thread, make sure you lock it rather than just catching the ArrayOutOfBoundsException

Glad you figured it out
I am still impressed that you can write Android games using these techniques. Is your game low-res or is Dalvik that powerful?
I mean, you are using Java, which is one thing, but then you use ArrayList and you delete objects as you go. I take this to mean that you do not recycle them in a pool.
Am I correct?

cyansmoker said:
Glad you figured it out
I am still impressed that you can write Android games using these techniques. Is your game low-res or is Dalvik that powerful?
I mean, you are using Java, which is one thing, but then you use ArrayList and you delete objects as you go. I take this to mean that you do not recycle them in a pool.
Am I correct?
Click to expand...
Click to collapse
ArrayList is self managing.
All of Java's garbage collection is done automatically. As a Java dev u can call System.gc but this only suggest the system attempt gc.
Dalvik is pretty good, but anything extensive I would go native...
Sent from my Galaxy Nexus using Tapatalk

jug6ernaut said:
ArrayList is self managing.
Click to expand...
Click to collapse
Right. But then there is the memory consumption issue. That's why I typically do things as described in this blog entry.
jug6ernaut said:
All of Java's garbage collection is done automatically. As a Java dev u can call System.gc but this only suggest the system attempt gc.
Click to expand...
Click to collapse
Although in System.gc()'s defense I've always observed that it was run immediately in Sun's ref. implementation. Not sure about Dalvik.
But overall I agree with your conclusion.

cyansmoker said:
I am still impressed that you can write Android games using these techniques. Is your game low-res or is Dalvik that powerful?
Click to expand...
Click to collapse
So far I have not been having any performance issues. The ArrayLists contain GameObjects which are quite lightweight memory wise as they do not contain Textures.
Textures are maintained in separate dictionary with a string key.
I did try recycling GameObjects in one location where I was spawning / destroying a lot but it didn't really seem to impact performance much.
I think my biggest area for optimisation at the moment is in collision direction. Currently there are about 5 different ArrayLists (Obstacles, Enemies, Players, Player Bullets, Enemy Bullets etc) only those that interact are tested for collision (Vector2d distance < objects collision radius). I think theres probably opportunity to split it further into quads.
I've yet to build in proper optimisation checking but it plays fine in 320x480 with ~100 enemies on screen and 4 player ships with maybe 20 bullets on screen at once with a turnover of 5/10 GameObjects a second. Even with this number though Texture memory usage is low with most enemies between 16x16 and 48x48.
I think libgdx and the behaviours library I use are pretty optimised.

Related

Help with memory leak

Hey guys. I've been looking around all over for info on the problem with my app. Nothing I found was a concrete answer. here's the problem. I made an app that works really well except it force closes when I hit the back button to finish activity and then start another of the same activity as before. It force closes once in a while when I do this, throwing a log cat error that says out of memory, pointing to where I fill my bitmap cache. There's two reasons im thinking it would be doing this. 1) My bitmap factory is having a problem or 2) I have the context of my activity stored as a variable so I can close activity and that is too much memory. I'm using a panel, which also may add to the problem. Also, another phone can't even start the activity the first time. Any help would be greatly appreciated. This is only problem on app and this fix will make it market ready.
Sent from my SCH-I500 using XDA App
Did you try to explicitly clean up the bitmap references? you should call Recycle() on every bitmap in your activity's onDestroy or wherever you do your cleaning. Another issue I had was with the Bitmap.CreateScaledBitmap method - it leaks, apparently. I made a small static method that uses a transform matrix and then calls Bitmap.CreateBitmap (the overload that takes a matrix, obviously). That change alone solved half my memory issues.
The thing about not loading at all on another phone might be a heap issue. My game loaded just great on my customized SGS, but on the emulator with 24mb of heap it crashed. The reason was that I pre-load all the sprites at the beginning, and apparently 24mb isn't that much
Solution was downscaling and lowering resolution and color depth for the sprites, not much possibilities here - too many bitmaps take too much memory...
I'm guessing the phone you tested likely has a smaller heap than the phone that doesn't make your app crash.
Of course all of the above is mostly guess work, but that's what I can supply right now
i have the problem fc too, but after i upgraded to 2.2. the seem the problem fixed automatically.
Thanks so much! I made it recycle my bitmaps, along with a few minor changes, and it worked great! Thanks for your help!
Sent from my SCH-I500 using XDA App

Game development advice - Level Design

Hello everybody,
I am currently developing my first Android game and had some questions about the best way to implement my levels. The game in question is a basically a space shooter (with some twists... but that's a surprise ), and the levels are like most in this genre: a ship is at one end of the screen (with some wiggle room) and enemies and debris come from the other towards the player.
Currently, I have an abstract Level class that extends Runnable, I am passing children of this class to a thread to handle all of the movement updates. Every object that extends Level is tied to a certain level in the game (there are few enough that this isn't too unmanageable), and the run() method is continuously checking if it needs to start moving any enemies onto the screen.
My current method is passable, but it seems a little ridiculous and inefficient (especially since all enemies for a level are contained in an array the WHOLE time).
I am looking for a way to make my code more flexible and manageable.
I would prefer a new way to send objects on screen, but I am drawing a blank for the most part. Does anybody have any suggestions or ideas that I should take a look at?
Thank you,
-Roflha
Shameless bump...
Why not make a "LevelEvent" class that contains a "time" and whatever other information is needed for you to identify what type of enemy is to be added to the screen. Then make your level an ArrayList (or similar structure) of these LevelEvents.
Then in your game loop (i.e. in your thread), keep track of what position you are at in your Level array. Peek at the next item to see if its .time has passed yet. If so, add a new Enemy object to an ArrayList which contains all of the current enemies on your screen. Increment the int that holds your current position in the Level ArrayList.
In your draw(), iterate through your ArrayList of visible enemies and draw them all. Similarly, iterate through this ArrayList when you update the game state. If the user shoots and kills one, simply remove it from the ArrayList.
Of course, ArrayList is probably not the optimal structure to use. You just need something whose size can be dynamically changed without to much work. I guess linked list or something of that sort could work well.
I hope this makes sense...good luck.
Edit: for clarification, I am suggesting two main data structures. The first is your Level, which simply contains all of your LevelEvents. The LevelEvent class can be very small, e.g. with an int for its time and an int for its enemy/debris type.
The second data structure is the one that needs to be very dynamic. As LevelEvent's occur, you push new Enemy objects onto this second structure. These Enemy objects can contain more specific information such as what bitmap to draw, the current frame of their animation, their life, their position, velocity, etc. When the enemies are destroyed, you remove the Enemy objects from this data structure, and let Java's garbage collector do the rest.

[Q] responding to screen lock/sleep

Hi everyone
I have an irritating dilemma. Whenever the screen goes to sleep/locks, SOMETHING happens and then it crashes when you turn it on again.
let me clarify a bit.
My app is an opengl game. Textures are loaded on the game(logic) thread. the game thread is started by the main thread in the onCreate method.
However,
when the screen wakes up from sleep or 'unlocks' the main threads onCreate gets called again, and therefore textures are loaded again and this make the app run out of memory and crash.
and this ONLY happens when the screen locks, switching between applications works just fine.
----
my question is this:
what happens when the screen goes to sleep or locks? Why does onCreate get called multiple times, and why the hell is there like no information about this specific thing in the Android docs?
EDIT:
also, what happens to threads when the screen is off. Are they terminated or frozen or something?
THANKS!
I would assume your activity is being destroyed/torn down, threads continue to run but become eligible for GC AFAIK.
You should really plan for this in your life-cycle. Do cleanup in onPause, onStop and onDestroy. And check to see if threads/ textures exist in onCreate() onResume() and onStart()
This is actually a generally good habit to be in when writing methods. If you design them in such a way that if they get called multiple times your app will react correctly anyways.
hth
alostpacket said:
I would assume your activity is being destroyed/torn down, threads continue to run but become eligible for GC AFAIK.
You should really plan for this in your life-cycle. Do cleanup in onPause, onStop and onDestroy. And check to see if threads/ textures exist in onCreate() onResume() and onStart()
This is actually a generally good habit to be in when writing methods. If you design them in such a way that if they get called multiple times your app will react correctly anyways.
hth
Click to expand...
Click to collapse
definitely is a good practice to assume nothing and always check for pre-existing textures, values, threads and to either decide to destroy and recreate them or to use the pre-existing values. its a good way to minimize memory leakage and values without pointers, though the vm does a good job of cleanup.

[Q] a guide to "non-convoluted android game programming"?

this question is actually about a small network of things: what the default android framework permits, how users use it and what engines can do.
after getting into android programming, it soon seemed to me that the android framework would require me to manage a lot of things i simply don't want to put up with for a simple game (e.g. i don't care about managing intents, creating xml-layouts and stuff like that... slap a couple of images on the screen and i'm fine - well... basically), i started looking for game engines.
after almost a month of research and tests (with default framework, andengine and libgdx), i finally whipped up a little prototype of the game i want to program using libgdx in just two days.
but then i noticed something...
the following issue might make the last third of this post irrevelant:
this game runs at 70% cpu usage on my desktop. even though i would only need to render on user input (it's a puzzle game). so i'm guessing it would use 20 times (or whatever) the battery of the phone it actually should.
since it seems to me "render on demand" isn't possible with libgdx, i figured i'd take another stab working with the default android framework and hope that this doesn't redraw like crazy even though it's not needed.
if such a thing is simply impossible, please tell me and i'll just keep on working with libgdx.
now, the most compact open source game example to learn from that i found is this:
http://code.google.com/p/asqare/source/browse/#svn/trunk/a2
after i tried it out and studied the code, i was stunned by how much stuff is being handled for this very, very simple game (pretty much as simple as mine). so i counted the lines of code... ~4200! while my libgdx prototype has roughly 800. sure, it doesn't have a preferences menu, no about screen and doesn't handle what happens on things like pause/resume but even with those things i highly doubt i'd get anywhere near that amount of code.
so:
IF it is indeed possible to produce a full-screen android app that draws images only on demand, is it possible to do that in a less convoluted fashion than in that 4200 line example?
i'm hopeful that this guy has simply overdone it and i've just been looking in the wrong places for slim examples.
Fyi I did not read 100% of your post, but I think I can help you out.
Imo do not waste your time with game engines. If you are serious about game dev then learn opengl. Its worth it.
With the glsurfaceview you can ether render on demand or as fast as possible. Also as with all opengl u have full control over what is rendered. If need be I can provide an example but it will have to wait a few days.
Sent from my MB860 using Tapatalk
actually, i've learned opengl in the past (but forgotten a lot already - didn't use those skills much) but a) i'll only do 2d games anyway and b) opengl isn't really the problem. getting to where i can actually render things is. and engines allow you to focus on gameplay/rendering without dealing too much with the whole setup and management of things.
i don't feel like libgdx takes control away from me, since i can still use all the opengl-commands i want. and i will definitely look up glsurfaceview and see how it fits into what i currently have. thanks!!
btw - i'm not really "serious". i'm a fulltime artist who happened to have learned about eight years of programming in the past and just wants to try to make a little extra on the side. and create some games i'd like to see but simply aren't out there yet.
and i don't want to spend more time programming all the management nonsense around it than the gameplay itself and working on the design.
I wouldn't rely on the cpu usage on the desktop. The emulator isn't efficient at all...
libgdx is a multiplatform engine, so that cpu usage is based on the desktop-version.
but it does use continuous rendering and can't be switched to on demand. tried to extend the classes of the engine and adapt them so that it renders in on demand for the last three hours without success...
but i've found a neat blog post on the android developers website called "The Simplest GLSurfaceView Application" and hope that i'll be able to find my way from there. after all, i now already at least have a nice full screen canvas with just 54 lines of code... that's something i did not expect i would ever see happening.

Feature unlock: true multitasking

I chanced upon an app that could enable android users the ability to true multitask. Android is designed to cleverly close apps in the background that it deems unimportant. This feat is brought to fruitation through the assigning of minfree values. The higher the minfree value, the more seceptible the app is in being axed to conserve ram and computing space which inturn conserve battery.
With this in mind, theoretically, if we assign an app with a minfree value of 0, the apps will not be killed even when kingdom come. Pardon my attempt at humour if you aren't chuckling.
Now to the crux of this post. There is an inherent difficulty to assign minfree values and not everyone is a coder. Luckily there is an app on the market which let users assign minfree values and better yet, filters the apps into hidden apps and stuff. Simply download this free application from the market:
https://play.google.com/store/apps/...t=W251bGwsMSwxLDEsImNvbS5ycy5hdXRva2lsbGVyIl0.
Go to settings, enable advanced mode to get access to the first three values. One simply inputs "0,0,0,0,0,0". And voila, theoretically all hidden/background apps will not be killed and true multitasking is achieved.
A quick test of some programs that are designed to close after home button is pressed does not close now. Am happy to report that this trick does not close any background app. Only downside is user has to manually close the apps, which for me is more than ok. Hope this helps!!
[Update] I have changed all fields to 0. So technically what I am telling the GSIII is "do not have coffee breaks,toilet breaks and oh, "I own your sorry ass".
Am excited to report that N.O.V.A. 3 still continued running after opening maps with GPS, XDA, Maps, Internet browser. All of which are running.
[Update 2] Edited the values to "0,0,1,1,1,1" as a failsafe in case all rams have been used up. E.g. NOVA3 and MC3 concurrently running due to carelessness. Will report any drastic behaviour or successfully implementation without much drawbacks.
Sent from my GT-I9300 using xda premium
I'm interested to know how this affects battery life.
jiggytom said:
I'm interested to know how this affects battery life.
Click to expand...
Click to collapse
I am pretty sure this will suck the bejesus out of the battery. : ) Plus we aren't using the software for its intended use.
I did the same
Interesting to try...
sebarkh said:
I did the same
Interesting to try...
Click to expand...
Click to collapse
If in the event u have reached a satisfactory value do share! I was inspired by the "backgrounder" program of jailbroken IOS devices. It does the same thing except our way is different. From my Iphone days I have fetishes of true multi tasking. : )
Sent from my GT-I9300 using xda premium
The Linux/Android kernel WILL run OOM-Killer (Out-of-memory) with SIGKILL (removes the process from RAM and CPU without letting it any chance to save data or report) when the memory is full and it cannot continue operation otherwise.
Dalvik _should_ work around a full memory but by disabling this feature it won't so you might experience some data loss.
Consequently it is necessary to have a sufficiently large Swap-Partition on your SDcard to allow the kernel to get more memory whenever needed. It won't be fast when it hits the limit but at least it still works.
d4fseeker said:
The Linux/Android kernel WILL run OOM-Killer (Out-of-memory) with SIGKILL (removes the process from RAM and CPU without letting it any chance to save data or report) when the memory is full and it cannot continue operation otherwise.
Dalvik _should_ work around a full memory but by disabling this feature it won't so you might experience some data loss.
Consequently it is necessary to have a sufficiently large Swap-Partition on your SDcard to allow the kernel to get more memory whenever needed. It won't be fast when it hits the limit but at least it still works.
Click to expand...
Click to collapse
Well on top of that, the Minfree was programmed so that the CPU doesn't have to overwork and so it can run at lower frequencies.
Interesting app, but I'm going to leave the programming to the experts.
Plus prog is too much of a hassle for too little gains in this case. Hahaha.
I have to say that I miss the way the Palm Pre multitasked the best. I also like how pre handled contacts with multiple numbers/IM/google etc (something that ios6 is finally going to attempt to do). It would incorporate all of them into one message window using icons. If only some of that could be incorporated into Android!

Categories

Resources