0

我已经使用 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 类,我只绘制矩形,所以我认为问题出在这段代码中。所以问题是我如何设法以某种方式“保存”应用程序在屏幕锁定时的状态并防止冻结屏幕上的对象。所以基本上在屏幕被锁定的状态下继续应用程序。

谢谢!

4

2 回答 2

0

Android context loss may produce strange things if you don't know what's happening. When you return to your app after the pause, your onSurfaceCreated gets called again so you can rebuild your GL context stuff.

The behavior you are pointing out is pretty explainable. You add your bodies to the static list , which does not get destroyed during the pause (only GL objects are destroyed). But you do not re-add them to your world (which you do re-create, so it's empty). Do you see now why you get 4 objects and 2 are still? If you do, I'm sure now you could easily solve the problem yourself, but here's a snippet to get started and introduce you to the GL thread and management:

//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);

    }
于 2012-12-27T19:49:14.217 回答
0

任何时候你的应用程序失去焦点,或者更确切地说是调用了 onpause,opengl 都会破坏你的资源,并且必须重新制作它们。(至少我上次使用 opengl 时就是这种情况),所以我认为您的引擎正在尝试处理这个问题,我们应该处理它而不是处理它。

于 2012-12-25T04:51:43.953 回答