I'm developing a game using libgdx library.
When I load the program for the first time, the textures load perfectly and everything is fine
When I close the application, and load it again (I'm assuming Android is somehow caching it from memory) - the wrong textures get loaded.
If I clear the game from history, and try again, it works perfectly.
--
The way it works currently is as follows - I use a SpriteBatch to draw the actual game. I have seperate SpriteBatches to draw the background and Interface (which are loading just fine). On disposing a level, I dispose the SpriteBatch.
for (Block block : world.getDrawableBlocks(this.width, this.height))
{
spriteBatch.draw(block.getTexture(1f), block.getPosition().x, block.getPosition().y, block.SIZE_X, block.SIZE_Y);
}
--
The textures I load using a cache I wrote myself to prevent the same image being loaded more than once. I clear the cache upon the creation of the application. I then keep a Texture / TextureRegion in the object itself, which is obtained through .getTexture()
And here's my code which I use to load the Textures
public static Texture loadTexture(String path)
{
//Do we have the texture cached?
if (textures.containsKey(path))
{
//return it
return textures.get(path);
}
else
{
//load it from the filesystem
Texture texture = new Texture(Gdx.files.internal(path));
//cache it
textures.put(path, texture);
//return it
return texture;
}
}
I attached a debugger and the textures being loaded DO have the correct path.
In the picture example, the texture being swapped happens to be part of the font, which is nothing which is EVER stored in my cache.
--
So, I'm rather stuck here.
Right now I'm using the naughty solution of killing the process manually on dispose:
#Override
public void onDestroy()
{
super.onDestroy();
this.finish();
android.os.Process.killProcess( android.os.Process.myPid() );
}
This works but is pretty dirty.
When the process fails due to an exception, the bug does not occur.
I'm guessing that somehow the library is caching its own textures which are somehow getting corrupted, but I have no idea how to check, nor how to clear them.
So, any ideas?
You need to Dispose() all Textures you have created, for textures loop through all its value() and dispose it on a separate method then use that method in main game's screen dispose() function.
the switched texture seems is BitmapFont, and if those font textures used in UI, then you might have wrong in UI scene or so, also are you loading with JSON file?
seems to me that when you close the game your last texture is font texture is used, and it fills the texture is used on scene.
"new Texture", TextureAtlas, BitmapFont, etc are automatically reloaded after pause/resume or when the OpenGL context is otherwise lost.
I'm guessing your problem must be on the way you handle the manual reloading.
If you want to make sure that no texture is loaded more than once, use AssetManager instead. No need to do all that manually.
Related
In short - I have an OpenGL texture which I need to copy into a FBO or another texture in the most efficient way possible under OpenGL ES 2.0.
At the moment I'm simply drawing the first texture into an FBO.
Is there a more efficient way? E.g. some sort of pixel copy that doesn't involve pulling the pixel data back to RAM and then buffering over to another texture - in ES 2.0 profile.
To give you context - this is video rendering related:
I have an OpenGL texture being buffered with video frame data from LibVLC, but due to timing issues between my app redraw rate and the decoder refresh rate, its possible that the OpenGL texture has no new frame to update & very oddly if I were to draw the texture to the screen without a frame to update - instead of it containing the previous frame's data, it draws some weird image of its own ( it looks like a space invader ?? ) - hence why I need to 'cache' the previous frame's content.
Specifically, this is an OpenGL texture, used to create an Android SurfaceTexture, which I have to call updateTexImage and releaseTexImage manually to either update the Texture's content and then to mark that I'm done with the SurfaceTexture's content once I've drawn it. If I don't release it then no new frames can be updated to it. If I release it I can't redraw the same frame more than once. Which has lead me to caching the texture once it's updated so the decoder is free to write to it & I still have the previous frame if when I come to draw again & there hasn't been an update yet.
Thanks.
This solution is based on having worked out how to properly interface with the Android SurfaceTexture to avoid having to cache its contents altogether.
If anyone wants to share an answer regarding efficient texture copies in OpenGL ES 2.0 please feel free - that would befit my original question.
For anyone interested, this is what I did:
My GLPaint class for rendering video on Android contains the SurfaceTexture instance, it's created from a JOGL OpenGL Texture ( using it's ID ) - This enables me to draw the texture as part of my GLPaint.paint function.
This GLPaint implements the onFrameAvailable method of the SurfaceTexture.OnFrameAvailableListener interface. I have a private boolean to flag when the first frame has been 'written' - this is needed to avoid releasing the SurfaceTexture prematurely.
The class GUIThreadLock is my extension of a ReentrantLock - I extended it for additional debugging info and to make a static singleton. This lock in my 'one in - one out' controller for threads in my UI, ensuring only a single thread is active in my UI at a time ( usually just the main renderer looper ) but also handles getting the OpenGL context bound or unbound to the lock owner thread whenever one acquires and relinquishes the lock respectively.
#Override
public void onFrameAvailable( SurfaceTexture pSurfaceTexture )
{
try
{
GUIThreadLock.acquire();
if( written )
{
pSurfaceTexture.releaseTexImage();
}
pSurfaceTexture.updateTexImage();
written = true;
}
finally
{
GUIThreadLock.relinquish();
}
}
This means that when a new frame is ready, the SurfaceTexture releases the old one & updates to the new one - it is then buffered with the current frame for any point I wish to draw the video until the next frame is ready. The GUIThreadLock protects the SurfaceTexture from updating the content while I may be drawing it but also acquires my GL Context so that the callback thread can actually perform the update here.
My Redraw thread would also require the GUIThreadLock before it could draw my app - thus the GL context is protected and the relationship between frame updates and frame draws cemented.
My program packs a series of images and outputs them into an aste.png, and an aste.atlas. My code for packing is as follows:
public void pack(){
System.out.println("Packing should not be ordinarily called! If you did not have explicit intentions of Packing, please check ImageAtlas constructor.");
Settings settings = new Settings();
settings.maxWidth = 512;
settings.maxHeight = 512;
TexturePacker2.process(settings, "E:/Files/Eclipse Projects/StarFighters/StarFighters-android/assets/sprites/" + name,
"E:/Files/Eclipse Projects/StarFighters/StarFighters-android/assets/sprites/", name.substring(0,4));
}
I will not need to pack EVERY time I run the program which is why I can get away with absolute file paths(I'll only pack when I'm running desktop and have added new images), however, I only used absolute file paths because I cannot figure out how to do it otherwise. I am using the android assets folder. (The desktop is linked to the android assets folder) As I am running it from the desktop version, it's trying to goto the desktop path, when I need it to use the assets path, which Gdx.files.internal handles for me. (This problem is not essential to the function of my program)
Once I have packed the images I do as follows:
atlas = new TextureAtlas(Gdx.files.internal("sprites/aste.atlas"));
public Texture getTex(String imgname){
return atlas.findRegion(imgname).getTexture();
}
I pass in "sma_a2" as the imgname when I try and getTex();
my assets/sprites/asteroids directory has the following images:
big_a1.png
big_a2.png
med_a1.png
med_a2.png
sma_a1.png
sma_a2.png
Which were all successfully packed into the aste.png and aste.atlas
My problem is, no matter what fname I pass in the image I receive is the entire aste.png
I also was curious as to why I would use a pack instead of just the images, as I start with images, and then pack them, only to get images again..
Don't call getTexture() on the TextureRegion returned from findRegion.
The whole point of an atlas is that all of the textures you look up in it are in the "same" texture, but at different regions within that texture. This way you can "bind" one large texture in OpenGL (which is somewhat expensive) and then render lots of different pieces out of the texture.
Most of the other APIs in Libgdx that take a Texture should also work with a TextureRegion.
**My solution:**
Using "getTexture" returns the entire image, and texture regions store basically a rectangle which represents the regoin of the packaged image that is the individual image. So, basically drawing TextureRegions isn't much different then drawing Textures, so I just drew the TextureRegion. In my case that involved adding to a superclass, so that it supported Textures, and TextureRegions in subclasses. Subclasses specified whether to use Textures or TextureRegions using a boolean, and different SpriteBatch.draw() methods were called for each.
As for why to use them P.T. posted above as follows:
The whole point of an atlas is that all of the textures you look up in
it are in the "same" texture, but at different regions within that
texture. This way you can "bind" one large texture in OpenGL (which is
somewhat expensive) and then render lots of different pieces out of
the texture.
Most of the other APIs in Libgdx that take a Texture should also work
with a TextureRegion.
So sounds to me like it is more effcient/faster.
Currently I am having static reference to all my sprites and loading and initializing them in my OnCreateResource mthod of SimpleBaseGameActivity, But now I have to override onAreaTouched listener on spirtes and the way I can override it while Initializing the Sprite. But I have a static method creating Atlas and Texture Region for every sprite. And I am using these sprites in my scene class and I want to override onAreaTouched there. I can registerTouchArea for that specific sprite in my scene so that can be done But I want to Override OnAreaTouched in a way so that Code reusability can be done.
Here is how I am currently creating and loading sprites.
defualtCageSprite = createAndLoadSimpleSprite("bg.png", this, 450, 444);
And this is my Method createAndLoadSimpleSprite.
public static Sprite createAndLoadSimpleSprite(String name,
SimpleBaseGameActivity activity, int width, int height) {
BitmapTextureAtlas atlasForBGSprite = new BitmapTextureAtlas(
activity.getTextureManager(), width, height);
TextureRegion backgroundSpriteTextureRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(atlasForBGSprite, activity, name, 0, 0);
Sprite sprite = new Sprite(0, 0, backgroundSpriteTextureRegion,
activity.getVertexBufferObjectManager());
activity.getTextureManager().loadTexture(atlasForBGSprite);
return sprite;
}
Now How Can I override onAreaTouched for some sprites while not losing the code reusability.
Is there any reason you need to load the textures at runtime? The normal way is to load the required textures all onto a single atlas while loading the application so that you can then quickly use them later.
As for the code reusability, Todilo's idea about enums seems to be pretty much what you need. Say for example that you have two kinds of objects - objects that disappear when you touch them and objects that fly up when you touch them. You enumerate both categories and put a piece of code into the touch event handling code that checks whether the object should disappear or fly up.
If you don't know what the objects should be doing on touch before running the application, there is a more dynamic way of achieving the same result. Just create two lists at runtime and put a reference to the object in one of the lists according to what the object should do when touched. Then in touch event handling do something like this:
if (disappearList.contains(touchedObject)) {
disappear(object)
}
if (flyUpList.contains(touchedObject)) {
flyUp(object)
}
Too bad AndEngine does not allow users to set listeners on sprites, it would make things a bit easier.
EDIT:
Added explanation of the use of BlackPawnTextureBuilder:
Your Atlas must be of type BuildableBitmapTextureAtlas, then you add all textures like this
BitmapTextureAtlasTextureRegionFactory.createFromAsset(buildableAtlas, this, "image.png"));
and after that
try {
this.buildableAtlas.build(new BlackPawnTextureBuilder<IBitmapTextureAtlasSource, BitmapTextureAtlas>(1));
} catch (final TextureAtlasSourcePackingException e) {
Debug.e(e);
}
I don't know whether this will work for animated Sprites or not, you will have to try it.
Also, there is no overriding onTouch, you will have to do that in the onAreaTouched method. One example of such condition is
if (pSceneMotionEvent.getAction() == MotionEvent.ACTION_DOWN && disappearList.contains(pTouchArea)) {disappear();}
Are you sure you dont want more functionality than override ontouch? How about creating a class inheriting for sprite for those that need onarea to be overriden and all other needs.
I am using libgdx and I am loading all my textures as shown below,
Texture objTexture=new Texture(Gdx.files.internal("imagename"));
This code was inside my ApplicationListener. But, I want to load all my images at the start of my game. I don't want to load them inside of ApplicationListener. I have tried accessing texture object outside the scope of OpenGL and failed. Can anyone suggest me on this?
I think that the soonest you can load those textures (it involves uploading them into the VRAM, so I guess that the Graphics module has to be initialized and all the GL stuff done) is in the create function of the ApplicationListener.
Also, you may consider using the new AssetManager to manage your resources. Or write a simpler asset manager.
I was wondering if anyone could advise on a good pattern for loading textures in an Android Java & OpenGL ES app.
My first concern is determining how many texture names to allocate and how I can efficiently go about doing this prior to rendering my vertices.
My second concern is in loading the textures, I have to infer the texture to be loaded based on my game data. This means I'll be playing around with strings, which I understand is something I really shouldn't be doing in my GL thread.
Overall I understand what's happening when loading textures, I just want to get the best lifecycle out of it. Are there any other things I should be considering?
1) You should allocate as many texture names as you need. One for each texture you are using.
Loading a texture is a very heavy operation that stalls the rendering pipeline. So, you should never load textures inside your game loop. You should have a loading state before the application state in which you render the textures. The loading state is responsible for loading all the textures needed in the rendering. So when you need to render your geometry, you will have all the textures loaded and you don't have to worry about that anymore.
Note that after you don't need the textures anymore, you have to delete them using glDeleteTextures.
2) If you mean by infer that you need different textures for different levels or something similar, then you should process the level data in the loading state and decide which textures need to be loaded.
On the other hand, if you need to paint text (like current score), then things get more complicated in OpenGL. You will have the following options: prerender the needed text to textures (easy), implement your own bitmap font engine (harder) or use Bitmap and Canvas pair to generate textures on the fly (slow).
If you have limited set of messages to be shown during the game, then I would most probably prerender them to textures as the implementation is pretty trivial.
For the current score it is enough to have a texture which has a glyph for numbers from 0 to 9 and to use that to render arbitrary values. The implementation will be quite straightforward.
If you need longer localized texts then you need to start thinking about the generating textures on the fly. Basically you would create an bitmap into which you render text using a Canvas. Then you would upload it as a texture and render it as any other texture. After you don't need it any more, then you would delete it. This option is slow and should be avoided inside the application loop.
3) Concerning textures and to get the best out of the GPU you should keep at least the following things in your mind (these things will get a bit more advanced, and you should bother with them only after you get the application up and running and if you need to optimize the frame rate):
Minimize texture changes as it is a slow operation. Optimally you should render all the objects using the same texture in a batch. Then change the texture and render the objects
needing that and so on.
Use texture atlases to minimize the number of textures (and texture changes)
If you have lots of textures, you could need to use other bit depths than 8888 to make all your textures to fit in to the memory. Using lower bit depths may also improve performance.
This should be a comment to Lauri's answer, but i can't comment with 1 rep, and there's a thing that should be pointed out:
You should re-load textures every time your EGL context is lost (i.e. when your applications is put to background and back again). So, the correct location to (re)load them is in the method
public void onSurfaceChanged(GL10 gl, int width, int height)
of the renderer. Obviously, if you have different textures sets to be loaded based (i.e.) on the game level you're playing then when you change level you should delete the textures you're not going to use and load the new textures. Also, you have to keep track of what you have to re-load when the EGL context is lost.