On cocos2d-x's game. When I pressed the home button to quit the game. The next time, how can I make the game must start over again, but not followed by the last exit scene
Ideally in applicationWillEnterForeground you should simply replace the scene with a new instance of it to start over e.g. if the class of scene you were running is called GameLevelScene you should simply tell CCDirector to replace the running scene with a new instance from it's class. For example:
CCDirector::sharedDirector()->replaceScene(GameLevelScene::create());
But while I was doing something similar to pause my game on resuming from background I noticed that it wasn't quite working (it should've, maybe this is some problem with cocos2d-x). So, as a work around, I created a sequence with a delay time of zero at it's start and then called my game's pause function. I guess the game needed to take one tick to process this after resuming from background. For you, if the above doesn't work just try this:
someNode->runAction(
CCSequence::create(CCDelayTime::create(0.0f),
CCCallFuncO::create(CCDirector::sharedDirector(),
callfuncO_selector(CCDirector::replaceScene),
GameLevelScene::create()),
NULL));
someNode can be any node in your game which is living in the game i.e. it hasn't been destroyed; it must be an alive object. You can have a game manager node which is alive at all times during your game. The game manager node can be made responsible for such game management issues.
Related
In my android app, there is a SurfaceView. Whenever user touches it a short( 1 sec) animation is rendered on the SurfaceView by a AsyncTask. I face force close problem in two scenarios.
When used presses Back key while the animation is running.
In the arcade mode game duration is of 60 seconds. At the end of game, new activity is started. If at the end of the game , the animation is still running while the new activity is started, I get force close error message.
How can I check if the AsyncTask is complete i.e. the animation is over, before Back key press takes effect or new activity is started ? Using AsyncTask.getStatus() in a while loop is freezing the app. Or is there any alternative way to do this?
One of the way to wait for it to finish is like asyncTask.execute().get() ;
with this your main thread will wait this to finish
Our game requires that several large textures are built up dynamically from small images, and we don't keep a data copy of the textures, we just use OpenGL with glTexSubImage2d to update the actual textures.
When Back is pressed, or the game loses focus, we want to save these textures to ram, so if the user then goes back to the game, we can recreate/reload them in onSurfaceCreated. We already reload from 'disk' all static textures.
However, its proving hard to find out where we can get a message to know that we are about to lose the EGL context. If we set a flag in the main activity's onBackPressed then check that flag in the main render loop, we can save the textures there, but we can't access the textures from the main activity, so putting the call in the main activity's onStop callback is too late. There is no subsequent render loop to save the textures, as, well, its stopped by then. We need to do this as there will be other ways where onStop is called other than pressing the Back button.
Supposedly I can't delay onStop to get one more "render" in either. Any other ideas ?
Since you already generate this textures dynamically during the cold start of your application, it may be a good point just to part this textures dirty and regenerate them just as if your application was starting cold.
If you want to save those textures then don't wait for onStop() to be called. Just save them once you have generated their content.
It sounds as a problem of synchronising threads. The button pressed event or the onPause event (in case another app goes to the front) runs on the main (UI) thread, while the opengl render has his own thread. When the events on UI thread are triggered, you set a flag and wait on a condition_variable. the render thread checks always the flag, and when it is set then saves the textures, changes the condition of the condition_variable and notifies the UI thread.
I am using this for some signal processing. It all works fine except when the screen goes off and the display was rotated at the time. Normally screen off just produces an Activity onPause(), but when the screen is rotated it goes: onPause(), onStop(), onDestroy(), onCreate(), onStart(), onResume(), onPause(). Ie it appears that Android 'unrotates' the screen first.
Unfortunately this seems to make AudioRecord crash or freeze in some unknown way.
The basic way I have it all operating is that in the onResume() a new thread is started and this instantiates an AudioRecord instance, sets it up, starts recording and then sits in a loop:
keepProcessing = true;
while (keepProcessing)
// read a block of data and process
In the onPause() in the UI thread keepProcessing (a volatile variable) is cleared, and it then waits for the worker thread to stop.
if (thread.isAlive()) {
keepProcessing = false;
thread.join();
}
thread = null;
When the other thread drops out of the keepProcessing loop it stops recording, releases the AudioRecord resources, drops the AudioRecord instance and terminates.
As a general start / stop mechanism this all works fine. Checking with breakpoints and adb everything seems to happen in the right order. It just doesn't work in this screen rotated scenario. I can only think it is because of the very rapid new Activity onCreate() etc after everything stops in the old Activity. Ie there is something in the AudioRecord that is still busy. What happens is everything freezes up when one tries to turn the screen on again.
If I dummy the AudioRecord code so that it doesn't actually start recording, the loop just sits and sleeps, and then doesn't stop recording again, it is all OK. It only goes wrong once the recorder has gone into recording mode.
Any advice?
When you rotate the device, your activity is actually stopped and destroyed. If you have background threads doing work, this totally screws you over. The best way to fix it is to tell Android not to do that, by adding android:configChange="orientation" to your manifest for that activity. Yeah, it's a bad architectural decision by Google and annoying to the point where I almost suggest adding that for all activities.
Yes, I can see that, and I've just found what was happening, which was sort of that.
Owing to an error where the keepProcessing flag was initialised, there was a race condition that could leave the background thread running when the Activity stopped.
"If you have background threads doing work [when the activity stops], this totally screws you over"
You are dead right. It does.
I am experiencing a very strange phenomenon (test device: HTC Desire HD, Android 2.3.5). I know that System.gc() is needless and discouraged, and I don't try to suggest otherwise, but the point is that it shouldn't cause issues either (i.e. it should be useless at most).
I have an application which contains a GLSurfaceView in its view hierarchy. The GLSurfaceView is instantiated and added in the Activity.onCreate(). Normally, the application works like this:
User starts the app and goes to mainmenu
User chooses a mainmenu item which sets the GLSurfaceView to View.VISIBLE
User plays with the in-built game on GLSurfaceView
User goes to mainmenu and exits the activity (=> Activity.finish() is called)
My Activity.onPause() looks like this:
mGameThread.pause(); // gameThread is my custom thread class for the in-built game
mGLView.onPause(); // pause the renderer thread
So far so good, everything works fine. However, issues appear after I add the following code to onPause() (for the case when the user exits the game from the mainmenu):
mGameThread.pause(); // gameThread is my custom thread class for the in-built game
mGLView.onPause(); // pause the renderer thread
if (isFinishing()) {
System.gc();
}
In details: if the Activity is started for the first time (= i.e. the app process didn't exist before), everything works fine. However, starting from the 2nd start of the activity (= after the first exit from the mainmenu, i.e. after the first Activity.finish()), the framerate of GLSurfaceView is reduced by 40-50%, the in-built game becomes slow.
If I remove the System.gc() call, the problem disappears. Moreover, if I do the following, it also gets rid of the problem:
mGameThread.pause(); // gameThread is my custom thread class for the in-built game
mGLView.onPause(); // pause the renderer thread
if (isFinishing()) {
// 1. get layout root of View hierarchy
// 2. recursively remove (detach) all Views
// 3. call GC
System.gc();
}
I didn't add concrete code because it's complex, so I used comments. If I just detach the GLSurfaceView via removeView(), it is not enough. The entire view hierarchy needs to be cleared.
Note that I couldn't find any memory leaks (no Activity leak via drawables/statics etc.). Moreover, of course, the gameThread properly exits when the app is closed (I just didn't include its source code).
Any ideas, guesses? Apparently, System.gc() seems to cause some issues for the Activity/layout destroying mechanism of Android. Again, as I said, if I remove System.gc(), the problem disappears.
I have experience of Android Game Programming. I used to clear all the view in hierarchy because when running threads if you call System.gc() sometimes it happens that your thread has a reference to some of your view, even if you call system.gc() this view won't get removed and if you keep playing again and again this game you will notice that your heap memory is started growing.
It depends upon the memory leak, if you are leaking some KB memory it will take more time to crash your game. The best way it to use Eclipse Memory Anlyser (Eclipse MAT) and compare your stacks.
Step1:
take memory snap shot when you start your game for first time
Step2:
take memory snap shot when you start your game second time
Step3:
Now compare your both stacks of snapshots it will tell you the difference.
It is a very useful tool. I was having huge memory issues in my game Apache Attack. I fixed them using this awesome tool.
Follow this ECLIPSE MAT TUTORIAL
I have a game, at the end i show a "Game Over" if the player does not follow some instructions.... the problem is android seems to stay on that state, when i go back to the menu and come back in.. i still dont have a way to play again, the game is coded in the main activity and has Runnables and OnTouch events, also I have a splash screen that when click it goes to the other activity where the game starts.... I am new to Android, what is the best way to terminate the Thread and then send them to the first Activity or splash screen?
Thank you in advance
It's very difficult to help without seeing any code. However, an Activity can self-terminate by calling finish(), if that's what you're asking.
If you use static variables they will be 'remembered' unless explicitly set in the View constructor or onSizeChanged etc. For example x = x + 5, can increase x every time you start the same game if x is static, because it 'remembers' x from the previous play - one needs to be aware of this.