How to detect when textures are destroyed - java

How do i detect when my textures are destroyed on android?
My Renderer class for my GLSurfaceView currently looks like this:
public void onDrawFrame(GL10 gl)
{
nativeLibrary.drawFrame();
}
public void onSurfaceChanged(GL10 gl, int width, int height)
{
if (reload)
{
library.glRecreate(); //this method reloads destroyed textures
}
else
{
nativeLibrary.init(width, height)); //this method initializes my game
reload = true;
}
}
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
}
The problem is that doesn't always work. When i press the home button from my game and then start it again, it works like a charm. But when i lock the device, and then unlock it again, all textures are just black. Everything seems to reset when I lock it too (my game always comes back in the main menu). When I quit the game using the home button, and do a lock/unlock after that, the game doesn't reset.

When doing OpenGL on Android, I highly recommend that you watch these two Google I/O talks by Chris Pruett, Android advocate, who wrote the open-source game Replica Island.
Here he talks about the exact problem you're seeing. Long story short: you don't detect when your textures (and buffers) are destroyed, but you detect when they need to be recreated. And this is exactly what the onSurfaceCreated callback is for:
Since this method is called at the beginning of rendering, as well as every time the EGL context is lost, this method is a convenient place to put code to create resources that need to be created when the rendering starts, and that need to be recreated when the EGL context is lost. Textures are an example of a resource that you might want to create here.

Related

LibGDX Music louder after switching screens

I've encountered something strange in my LibGDX project. I'm currently using a Music instance to play my ambient music, which itself is a copy of another external static Music instance. My problem comes when I swap screens and then swap back to the previous screen - the audio playback becomes noticeably higher in volume even though the music.getVolume() returns the same value. I've already made sure that I stop the music from playing and I dispose of the music object, so I don't think it's because more than one music instance is overlapping.
Code:
//In my assets class
public static final Music RAIN_AMBIENT_MUSIC = Gdx.audio.newMusic(Gdx.files.internal("music/ambient/rain.mp3"));
//In my screen's show() method
background_music_1 = Assets.RAIN_AMBIENT_MUSIC;
background_music_1.setLooping(true);
background_music_1.play();
background_music_1.setVolume(0.5f);
//In my screen's hide() method
background_music_1.stop();
dispose();
//In my screen's dispose method
background_music_1.dispose();
Any ideas?

libGDX: Moving camera in Stage Viewport

I developed a libGDX application on Android that uses a Stage with Viewport and Camera.
I wanted to change the viewport's camera position, but nothing happens. I didn't know what can cause this problem.
If I change
stage.getViewport().getCamera().position.x
or I call
stage.getViewport().getCamera().translate()
anywhere, the camera position doesn't change.
I call stage.getViewport().getCamera().update() after these methods but nothing happens.
This problem was that, when I updated my Viewport in my ApplicationListener's resize function:
#Override
public void resize(final int width, final int height) {
stage.getViewport().update(width, height, false);
}
I set the third parameter to true and this way the camera is recentered all the time, and my calls were ineffective. To solve the problem set it to false, or remove it simply because that function has a 2 paramtered signature as well.
I share this problem because it was difficult for me to find out what's going on, and this might spare some time for others in the same situation.

Thread keeps updating for a while before going to next activity and collisions are off

I have a little Android game I've been working on and have also implemented some pixel perfect collision checking based on code here (I say based on, the only thing I changed was the class name). This used to work fine a few months ago but I stopped development for a while, came back and had to rebuild a lot of code including that. Now when I implement it to collisions seem horribly off. If the large weight is on the left of the player, there's a significant distance and yet it still counts as a collision. I have also noticed that the player can pass through some of the smaller weights but not all the way through. I know the player has some non-transparent white pixels which don't help, but I tried with a transparent smaller image and the same thing happened. I edited the player image to remove the white pixels, but I'm still getting the odd collision detection. Any ideas?
The second issue, when the player collides with a weight, it goes to the next activity (which it does) however it jerks all the objects on screen for about a second, and then proceeds to the next activity. Any ideas on this? I have a feeling it's to do with the way I handle the threads, or the way I close them. Check GitHub link below for the GameThread class which handles the main operations on my surface thread.
Collision code can be found in above link, my calling of the class can be found below:
// handles game over circumstances
if (CollisionUtil.isCollisionDetected(player.getBitmap(), player.getX(), player.getY(), weight.getBitmap(), weight.getX(), weight.getY())) {
Intent gameOverIntent = new Intent(this.getContext(), GameOverActivity.class);
player.setTouched(false);
this.getContext().startActivity(gameOverIntent);
((Activity) this.getContext()).finish();
save(score, time);
try {
gameTimers.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
gameOver = true;
}
The rest of the classes and all my other code can be found here: https://github.com/addrum/Francois/tree/master/src/com
Thanks for your help in advance.
Edit: Forgot to mention that if you need to test it (you probably will to see what I'm talking about) you can download it here: https://play.google.com/store/apps/details?id=com.main.francois
Edit: I've now uploaded a short recording on YouTube to make it easier to see what I'm talking about: http://youtu.be/vCjKmTmhabY
Thanks for the video; now I understand the "jerk" part.
The explanation for that is simple: your code is doing this (simplified):
while (running) {
canvas = this.surfaceHolder.lockCanvas();
this.gameLogic.update();
this.gameLogic.render(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
}
public void render(Canvas canvas) {
if (!gameOver) {
...draw...
}
}
If gameOver is true, your render() function doesn't draw anything, so you get the previous contents of the buffer.
You might expect this to show whatever was drawn from the frame just before this one. However, the SurfaceView surface is double- or triple-buffered. So if you just keep calling lock/post without drawing anything, you'll cycle through the last two or three frames.
Simple rule: if you lock the surface, you need to draw. If you don't want to draw when the game is over, you need to put your "game over" test back before you lock the canvas.

Application loading the wrong textures on opening again

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.

Camera and SurfaceView - Video Distorted / Artifacting

Screenshot: http://imgur.com/r7EpSpx
I have a very specific issue regarding the operation of a SurfaceView and a Camera. I am using the SurfaceView as the preview surface for a camera in an IntentService (to allow background operation).
After a lot of trial and error, I almost have the code working as desired. However, when I am using MediaRecorder to record video, whenever I resume my activity (thus the SurfaceView is re-created) the video is extremely distorted/artifacted in what seems to be rainbow colors with a large black rectangle in the middle. Also the video effect seems to be in a "tile" arrangement. If you look closely, the camera is still working and the video records as normal, but the SurfaceView preview is broken.
Normally, I would re-instantiate the Camera object in the surfaceCreated methods of my SurfaceView callback, but whenever I use Camera.stopPreview(), or several other Camera functions, it causes my MediaRecorder.stop() to hang indefinitely (this is another separate issue). Due to this, I must use the same Camera object in my IntentService when the surface is re-created.
Everything works as normal except this strange video distortion, even the resulting video that the MediaRecorder produces. Only the preview is affected. I am unable to determine whether this is a code issue, software issue, TouchWiz issue, or hardware issue. It occurs in all orientation configurations. Moving the code to surfaceChanged results in the same thing. Thanks in advance for any help or insight into this!
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (isRecording) //Only run this code if MediaRecorder is recording
try {
recordingCamera.setPreviewDisplay(rHolder); //This works, but causes the aforementioned distortion
//recordingCamera.startPreview(); //Removes distortion, but causes MediaRecorder.stop() to freeze app indefinitely
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
//recordingCamera.stopPreview(); //Removes distortion, but causes MediaRecorder.stop() to freeze app indefinitely
}
Running this on a Galaxy Note II | Android 4.1.2 (TouchWiz)

Categories

Resources