Android OpenGL ES объект зависает при спящем режиме / блокировке экрана
Я создал проект с OpenGL ES и успешно импортировал библиотеку jBox2D. Я сделал тестовый проект, который включает в себя два прямоугольных падения. Работает отлично! Однако, когда экран переходит в режим сна или я блокирую экран, падающие объекты останавливаются в положении, в котором я заблокировал экран, и когда я разблокирую экран, они даже не будут продолжать падать, просто остановятся, и два других прямоугольника будут созданы в исходном положении., Так что, похоже, оно сбрасывает все приложение, но предыдущий объект как-то там зависает.
Вот код:
package com.example.opengltest;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
GLSurfaceView surface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
surface = new GLSurfaceView(this);
surface.setRenderer(new SimpleRenderer());
setContentView(surface);
}
protected void onPause() {
super.onPause();
surface.onPause();
}
protected void onResume() {
super.onResume();
surface.onResume();
}
}
Рендерер:
package com.example.opengltest;
import java.util.HashSet;
import java.util.Set;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.collision.shapes.Shape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.dynamics.World;
import android.opengl.GLSurfaceView.Renderer;
public class SimpleRenderer implements Renderer {
private static World world;
private static Set <Body> bodies = new HashSet<Body>();
private Rect r;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {
world = new World(new Vec2(0.0f, -9.8f), false);
r = new Rect();
createObject(300, 500, 0.75f, 0.75f, BodyType.STATIC);
createObject(360, 1200, 0.75f, 0.75f, BodyType.DYNAMIC);
gl.glViewport(0, 0, 600, 1024);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(0, 600, 0, 1024, 1, -1);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
}
private void createObject(int x, int y, float w, float h, BodyType bType) {
BodyDef boxDef = new BodyDef();
boxDef.position.set(new Vec2(x/30/2, y/30/2));
boxDef.type = bType;
PolygonShape shape = new PolygonShape();
shape.setAsBox(w, h);
Body box = world.createBody(boxDef);
FixtureDef boxFixture = new FixtureDef();
boxFixture.density = 1;
boxFixture.shape = shape;
box.createFixture(boxFixture);
bodies.add(box);
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
Vec2 vec;
for(Body body : bodies) {
vec = body.getPosition();
r.draw(gl, vec.x * 30, vec.y * 30, body.getAngle());
}
world.step(1/60f, 8, 3);
}
@Override
public void onSurfaceChanged(GL10 gl, int w, int h) {
}
}
С классом Rect я просто рисую прямоугольник, поэтому я думаю, что проблема в этом коде. Поэтому вопрос в том, как мне "каким-то образом" сохранить состояние приложения при блокировке экрана и предотвратить зависание объекта на экране. Таким образом, в основном, чтобы продолжить приложение в состоянии, когда экран был заблокирован.
Спасибо!
2 ответа
Каждый раз, когда ваше приложение теряет фокус, или, скорее, вызывается onpause, opengl уничтожит ваши ресурсы и их придется переделывать. (по крайней мере, так было в прошлый раз, когда я использовал opengl), поэтому я думаю, что ваш движок пытается справиться с этим, а вы должны справиться с этим.
Потеря контекста Android может привести к странным вещам, если вы не знаете, что происходит. Когда вы вернетесь в свое приложение после паузы, ваш onSurfaceCreated будет вызван снова, чтобы вы могли перестроить свой контекстный контент GL.
Поведение, на которое вы указываете, вполне объяснимо. Вы добавляете свои тела в статический список, который не разрушается во время паузы (уничтожаются только объекты GL). Но вы не добавляете их в свой мир (который вы воссоздаете, поэтому он пуст). Теперь вы понимаете, почему вы получаете 4 объекта, а 2 еще? Если вы это сделаете, я уверен, что теперь вы можете легко решить проблему самостоятельно, но вот фрагмент, чтобы начать и познакомить вас с потоком GL и управления:
//e.g call this from MainActivity's onCreate. Note this will not be within the openGL
// thread, so you can't do opengl calls! (try it!)
public void my_non_openGL_stuff_initialization(){
world = new World(new Vec2(0.0f, -9.8f), false);
r = new Rect();
createObject(300, 500, 0.75f, 0.75f, BodyType.STATIC);
createObject(360, 1200, 0.75f, 0.75f, BodyType.DYNAMIC);
}
//Note this runs on the opengl thread. You should always recreate all your opengl related
//things here. This gets called at the begining, and when coming back from a pause
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {
gl.glViewport(0, 0, 600, 1024);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(0, 600, 0, 1024, 1, -1);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
}