I have a GameScreen class that renders my game.
but before starting to render the game, it needs to reading files and initializing that is time consuming.
So I need to show/render another Screen class called LoadingScreen in order to spending some time and concurrently read my files and do initializing process for my GameScreen, and after initializing completed changing the screen by calling setScreen(gameScreen).
I need to use thread for making this concurrent work, now the problem is that if I use a thread to read files and initializing; When switching to the GameScreen the openGl gives me this error:
javax.media.opengl.GLException: Error: no OpenGL buffer object appears to be bound to target 0x8892
at com.sun.opengl.impl.GLBufferSizeTracker.setBufferSize(GLBufferSizeTracker.java:118)
I am aware of not both of threads use the graphic resources simultaneously.
I have found that the problem causes with Meshes. Initializing a Mesh in initializer thread and rendering in main thread causes this error. But I don't know how to solve it.
Do you have any ideas to solve this problem?
As suggested in the comments, the AssetManager is the way to load most libGDX resources (audio, textures, etc) asynchronously while showing a splash or loading screen.
For other operations, running them in a background thread (or using one of the other Android or Java background task execution facilities) should be sufficient. To invoke libGDX routines like setScreen or others that need to be executed on the libGDX render thread, use Gdx.app.postRunnable, like this:
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
// Do something on the main thread
myGame.setScreen(postSplashGameScreen);
}
});
Depending on the visibility of myGame and postSplashGameScreen it may be easier to construct the Runnable in a different context and then pass it over to the background thread to post when its done.
My workouround is using Actions in my loading screen method:
#Override
public void show() {
stage.addAction(Actions.sequence(Actions.delay(0.5f), action_loading_assets_and_other_stuff, Actions.delay(0.5f), action_setScreen));
}
Actions.delay(0.5f) makes the magic - game not freezing
The action delay did it for me, too. I just sequence a delayaction with 0.2f and a runnable action on the stage in the loading screens show() method. Now the loading screens render method is called a few time while while the 0.2 sec delay which draws the screen and i can proceed stuff in the runnable action.
Related
I'd like to clarify using of view, propery, etc. animations in Android.
Usually, I create animation without any Tread's things - directly within my Activity/Fagment/ViewClass:
AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
alphaAnimation.setDuration(100);
mView.setAnimation(alphaAnimation);
alphaAnimation.start();
I understand this as an animation executing within main UI thread.
But if I will create an animation within a worker thread - will it be normal way?
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
alphaAnimation.setDuration(100);
mView.post(new Runnable() {
public void run() {
mView.setAnimation(alphaAnimation);
alphaAnimation.start();
}
});
}
}).start();
}
Your thread has no real effect here. The call to mView.post() essentially schedules that runnable to execute on the main thread in its next available cycle. You might as well save the effort of starting a new thread and do it all on the main thread. There is not much going on here.
Animations work by scheduling lots of tiny bits of work to run on the main thread with each frame, which is about every 16ms. This is very typical. Unless you are seeing a very specific problem that you need to optimize, there is no reason to avoid doing this kind of work on the main thread.
Expanding on Doug's answer, and the explanations in the comments to his answer -
For maintaining a frame rate of 60 fps for smooth transitions and animations, we have ≈ 16 ms/frame to bring a frame to the screen. In these 16 ms, all sorts of things need to be done, including but not limited to processing user input, processing animations, measurement & laying out of different views, preparing and issuing display lists to the GPU, compositing windows, and finally displaying the output on the screen. And there is no time limit specifically for the animation stage (or any of the stages).
Also, only a specific amount of work needs to be done per frame per animation. For example, to rotate a view by 180 degrees in 1 s, we need to make calculations to rotate it by 3 degrees per frame. And this calculation is not interrupted in case it exceeds some time limit (even 16 ms). However if the entire process of frame rendering is unable to execute in 16 ms, then we see a frame drop.
Now if one of the stages takes too long to execute, it is possible to run them in a worker thread to free up the UI thread for other stages. But there's a catch - you cannot manipulate components from the Android UI toolkit (components from the android.widget and android.view packages) from a worker thread. So Android provides a post() method, to schedule methods from the worker thread to run on the UI thread.
Refer to https://developer.android.com/guide/components/processes-and-threads for more on this topic.
Now what you are doing is not helping much, because as Doug said, you're scheduling the animation runnable to execute on the main thread. The only work done in the worker thread is
final AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
alphaAnimation.setDuration(100);
which is not particularly resource intensive, hence there is not much to gain by putting it in a separate thread.
I've got a problem with creating gameloop for my first game. I've read a lot about it but still can't figure it out. It's based on OpenGL so I've used onDrawFrame as a game loop and it works fine on my phone. Problem is that onDrawFrame is refresh time depends on hardware so it runs way too fast on some devices. So what I want is adding a separate game loop that will refresh itself at constant period of time on all smartphones. (and onDrawFrame will only take care of graphics as it should)
As for now I have:
myGameRenderer class with all openGl stuff an onDrawFrame
myGLSurfaceView that supports touch events
myGameActivity
onDrawFrame activates myGameUpdate function that controls changing positions of all objects in game depending on info from myGLSurfaceView
I've tried with creating new Runnable but it doesn't seem to work, I can't figure out how to start that runnable and where i should place it (I've tried to place it in myGameRenderer class, but it didn't seem to work, nothing was moving:
private final Runnable mUpdateDisplay = new Runnable() {
#Override
public void run() {
update();
}};
private void update() {
//some update stuff blablabla
//some update stuff blablabla
mHandler.postDelayed(mUpdateDisplay,40); //to refresh at 25 fps
}
but I guess I don't get the idea of it - I mean I create this runnable.
I've tried to place it in onCreateSurface to start it but no effect.
So - is the generall idea ok? And how to start the loop? Where to place it? Or should I use any other way?
Ok it was simple - I was just missing r.run();
But as allways there's something. Now it works as i wanted - I mean frames doesn't depend on hardware, but everything is not as smooth as it was - and part of objects in 3d are flickering. Seems like some objects visibly are drawn faster, some later and it looks ugly.
So what am I doing wrong? Is there a better way?
when I start my game black screen comes for a while because resources are being loaded.
I went thorough a tutorial which show how to show progress bar while leading resources I followed it and now I can see progress bar. But the problem is this when progress bar is visible every thing else is stopped. And nothing happens. Only a black screen and a progress bar on it. Can any one tell me why every thing is paused and why loadresources and loadscene methods are not working? Please provide a solution.
You need to load your resources in a worker thread. A nice utility for doing this is AsyncTask. The guide topic Processes and Threads has an explanation of why you need something like this, as well as sample code showing how to do a simple AsyncTask that might be just what you need.
From Engine.java:
public void onDrawFrame(final GLState pGLState) throws InterruptedException {
final EngineLock engineLock = this.mEngineLock;
engineLock.lock();
try {
engineLock.waitUntilCanDraw();
this.mVertexBufferObjectManager.updateVertexBufferObjects(pGLState);
this.mTextureManager.updateTextures(pGLState);
this.mFontManager.updateFonts(pGLState);
this.onUpdateDrawHandlers(pGLState, this.mCamera);
this.onDrawScene(pGLState, this.mCamera);
engineLock.notifyCanUpdate();
} finally {
engineLock.unlock();
}
}
And that's why the engine hangs and the UI gets stuck. It's possible to display a loading screen while the textures are being loaded into hardware, without freezing, let's say, a ProgressBar. It's not easy and requires a lot of code, but it's possible and doesn't require crazy hacks, just some logic.
You need to have a Resources Manager (RM) and a Scene Manager (SM) who work together (with AsyncTasks) and are responsible for loading the textures for the current scene. Since you've a BaseGameActivity you can use this Activity instance to show a fullscreen Dialog with the progress bar. The logic is:
SM is asked to show Scene A
SM shows the loading Dialog
SM asynchronously tells the RM to load all Scene A resources into hardware (for each texture for Scene A, texture.load)
RM "onSceneTexturesLoadComplete" tells SM that all textures are loaded
Since texture.load doesn't guarantee the texture is actually loaded you'll need to have a TryToDismissDialog that extends TimerTask. This TryToDismissDialog from time to time will query the Scene A textures and check if they are actually loaded:
if (texturePack.getTexture().isLoadedToHardware()) {
texturesLoaded++;
}
If all textures are loaded you dismiss the Dialog and voilá you'll see the Scene ready.
Hope it helps
ps: this actually involves some lines of code, I've just posted here a quick steps/guide/pseudo-code. I'll not post the final solution because it's quite heavy and "project related".
I am developer of Android game.
I have create an GLSurfaceView and draw something in OnDrawFrame(GL10 gl)
like below
void OnDrawFrame(GL10 gl)
{
frame_limit_wait();
game_logic();
draw_game();
}
Everything is good, but onething is strange, when drawing n-frame(Occur at GC_EXPLICIT/paused 92ms) will cause game a bit pause, in appplication it's ok, but not in a smooth game.
Original game I was use SurfaceView and Thread update works and smooth.
If add a line below draw_game() like 'system.gc()' it seems work but I feel a bit slow.
Compare to another game engine, my game endinge is running slow.
How to resolve the latency problem ?
Edit : I have solved the issue.
Just initial native Float Buffer once, and use put and position(0) to modify the Buffer content.
The garbage collector is running and holding up your frame. I would recommend taking a close look at the code that executes in the functions frame_limit_wait(), game_logic(), and draw_game() and do everything possible to prevent initializing new objects.
The most common techniques for this include:
use fields instead of local variables
use for(int i; i < x; i++) instead of for(variable : list)
making sure no extra processing is done while drawing frames.
If that still doesn't work then you can try offloading some processing to a separate thread or consider using the NDK and writing native code. With C++ you don't have to worry about the GC at all. However both of these methods will complicate your code quite a bit.
Try running your game_logic(),draw_game() code in a separate thread so that when its waiting in frame_limit_wait() , GC can be serviced in a better way.
I mean instead of using the main thread try running your rendering/update code in seperate thread.
I have created an animation drawable and image view in my main game thread which is configured from the activity that handles the game thread (starting it etc.). My code in this handling activity looks like this:
mDistractionsThread.animation.addFrame(getResources().getDrawable(R.drawable.one), 1000);
mDistractionsThread.animation.addFrame(getResources().getDrawable(R.drawable.two), 1000);
mDistractionsThread.animation.addFrame(getResources().getDrawable(R.drawable.three), 1000);
mDistractionsThread.animation.setOneShot(false);
mDistractionsThread.imageAnim =(ImageView) findViewById(R.id.img);
mDistractionsThread.imageAnim.setBackgroundDrawable(mDistractionsThread.animation);
mDistractionsThread.animation.start();
And as you can see the variable mDistractionsThread is a handle to the thread itself. This compiles fine but only displays the first frame (R.drawable.one) and does not animate at all. What is it I have missed?
I tried to set animation.start() from run() within mDistractionsThread but that just gave me an fatal exception because the View can only be altered from the class that alters its fields - which in this case is not the game thread.
How can I resolve this and get it animating through the frames, and for bonus points, moving across the x-axis?!
Many thanks
It matters where you start the animation. Try starting it in onFocusChanged() in the activity. It should help