OpenGL ES SensorManager粒子位置更新

时间:2012-03-30 07:41:10

标签: android opengl-es orientation sprite sensor

我正在开发一个精灵实验,其中涉及由于方向变化而在屏幕周围移动一组球。但是当我在Renderer课程中渲染(创建和定位)粒子时,如何在我的SensorManager课程中实现Activity更新他们的动作。以下是代码。这可能很长,但我已经减少了多少冗余以使你理解它。

由于这种情况往往很长,请让我澄清一下您理解的问题,我会通过编辑解决这些问题。

public class MyGLCubeTouchActivity extends Activity implements SensorEventListener  {

   private GLSurfaceView myTouchSurface;
   private SensorManager sm;
   public float xPosition, xAcceleration,xVelocity = 0.0f;
   public float yPosition, yAcceleration,yVelocity = 0.0f;
   public float xmax,ymax;
   public float frameTime = 0.666f;
   private List<MyGLBall> ball;


  @Override
  protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
       myTouchSurface=new TouchSurfaceView(this);
       setContentView(myTouchSurface);
       sm=(SensorManager) getSystemService(Context.SENSOR_SERVICE);

     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    sm=(SensorManager) getSystemService(Context.SENSOR_SERVICE);
    if(sm.getSensorList(Sensor.TYPE_ACCELEROMETER).size()!=0){

       Sensor s=sm.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
       sm.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);   
      }

    if(sm.getSensorList(Sensor.TYPE_ORIENTATION).size()!=0){

     Sensor s=sm.getSensorList(Sensor.TYPE_ORIENTATION).get(0);
     sm.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);

      }

     myTouchSurface.requestFocus();
     myTouchSurface.setFocusableInTouchMode(true);
     Display display = getWindowManager().getDefaultDisplay();
     xmax = (float)display.getWidth() - 50;
     ymax = (float)display.getHeight() - 50;

     ball=new ArrayList<MyGLBall>(36);
     for(int i=0;i<=35;i++){
     ball.add(new MyGLBall());
      } 
   }

    @Override
    protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    myTouchSurface.onPause();
    //sm.unregisterListener(this);

    }

    @Override
    protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    myTouchSurface.onResume();
    // Register this class as a listener for the accelerometer sensor
    sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
            SensorManager.SENSOR_DELAY_GAME);
    // ...and the orientation sensor
     sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ORIENTATION),
            SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1) {
    // TODO Auto-generated method stub

    }

    @Override
    public void onSensorChanged(SensorEvent arg0) {
    // TODO Auto-generated method stub
      if (arg0.sensor.getType() == Sensor.TYPE_ORIENTATION) {
        //Set sensor values as acceleration

        yAcceleration = arg0.values[1]; 
        xAcceleration = arg0.values[2];
        updateBall();
       Toast.makeText(getApplicationContext(), "onsSensorChanged executed", Toast.LENGTH_SHORT);
     }


}


    private void updateBall() {
    //Calculate new speed
    float xSpeed = xVelocity + (xAcceleration * frameTime);
    float ySpeed = yVelocity + (yAcceleration * frameTime);

    //Calc distance travelled in that time
    float xS = ((xVelocity + xSpeed)/2)*frameTime;
    float yS = ((yVelocity + ySpeed)/2)*frameTime;

    //Add to position negative due to sensor 
    //readings being opposite to what we want!
    xPosition -= xS; 
    yPosition -= yS;

    if (xPosition > xmax) {
        xPosition = xmax;
    } else if (xPosition < 0) {
        xPosition = 0;
    }
    if (yPosition > ymax) { 
        yPosition = ymax;
    } else if (yPosition < 0) {
        yPosition = 0;
    }
    }

     public class TouchSurfaceView extends GLSurfaceView  {

    private MyGLRenderer mRenderer;

    public TouchSurfaceView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub

            mRenderer=new MyGLRenderer();
            setRenderer(mRenderer);
            setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

    }

     class MyGLRenderer implements GLSurfaceView.Renderer{

        private Random r;
        private MyGLCube mCube;
        public float mAngleX;
        public float mAngleY; 

        public MyGLRenderer(){
            r=new Random(); 
        }

        @Override
        public void onDrawFrame(GL10 gl) {
            // TODO Auto-generated method stub


            gl.glDisable(GL10.GL_DITHER);
             gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);   

             gl.glMatrixMode(GL10.GL_MODELVIEW);
             gl.glLoadIdentity();
             gl.glClientActiveTexture(DRAWING_CACHE_QUALITY_HIGH);


            for(int i=0;i<=35;i++){

             float randX=(float)((r.nextFloat()) *(1.0f - (-1.0f)) + (-1.0f));
             float randY=(float)((r.nextFloat()) *(1.0f - (-1.0f)) + (-1.0f));
                gl.glPushMatrix();
                     gl.glTranslatef(randX, randY, -3.0f);
                     gl.glScalef(0.3f, 0.3f, 0.3f);
                     gl.glColor4f(r.nextFloat(), r.nextFloat(), r.nextFloat(), 1);
                     gl.glEnable(GL10.GL_TEXTURE_2D);


                     ball.get(i).draw(gl);
                gl.glPopMatrix();
            }
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            // TODO Auto-generated method stub
            gl.glViewport(0, 0, width, height);
            float ratio=(float) width/height;
            gl.glMatrixMode(GL10.GL_PROJECTION);
            //gl.glOrthof(-2, 2, -2, 2, -1, 1);
            gl.glLoadIdentity();
            gl.glFrustumf(-ratio, ratio, -1, 1, 1, 25);

        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // TODO Auto-generated method stub
            gl.glDisable(GL10.GL_DITHER);
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
            gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);


       }            
     }

    }       
}

以下是 MyGLBall

的实施方式
       public class MyGLBall {

private final float degToRad=(float) (3.14159265358979323846 / 180.0);  
private int points=360;
private float vertices[]={0.0f,0.0f,0.0f}, colorVals[]={0.2f,0.6f,0.3f,1.0f};
private FloatBuffer vertBuff, colorBuff, alBuff, dlBuff, slBuff, lPosBuff, lDirecBuff;
private float[] al = {0.03f, 0.07f, 0.03f, 1.0f}, dl={0.3f, 0.8f, 0.2f, 1.0f}, sl={0.6f, 0.4f, 0.8f, 1.0f}; 
float shineness = 0.4f;
float[] lPosition = {0.5f, 0.8f, 0.3f, 0.4f};
float[] lDirection = {0.0f, 0.0f, -1.0f};

//centre of circle

public MyGLBall(){

    vertices=new float[(points+1)*3];
    colorVals=new float[(points+1)*4];
    for(int i=3;i<(points+1)*3;i+=3){
      double rad=(i*360/points*3)*(3.14/180);
      vertices[i]=(float)Math.cos(rad);
      vertices[i+1]=(float) Math.sin(rad);
      vertices[i+2]=0;    
    }

    for(int i=4;i<(points+1)*4;i+=4){
      float colorVal=r.nextFloat();
      colorVals[i]=colorVal;
      colorVals[i+1]=colorVal;
      colorVals[i+2]=colorVal;
      colorVals[i+3]=1;
    } 

      ByteBuffer bBuff=ByteBuffer.allocateDirect(vertices.length*4);    
      bBuff.order(ByteOrder.nativeOrder());
      vertBuff=bBuff.asFloatBuffer();
      vertBuff.put(vertices);
      vertBuff.position(0);

      ByteBuffer bColorBuff=ByteBuffer.allocateDirect(colorVals.length*4);
      bColorBuff.order(ByteOrder.nativeOrder());
      colorBuff=bColorBuff.asFloatBuffer();
      colorBuff.put(colorVals);
      colorBuff.position(0);

      ByteBuffer bAlBuff=ByteBuffer.allocateDirect(al.length*4);
      bAlBuff.order(ByteOrder.nativeOrder());
      alBuff=bAlBuff.asFloatBuffer();
      alBuff.put(al);
      alBuff.position(0);

      ByteBuffer bDlBuff=ByteBuffer.allocateDirect(dl.length*4);
      bDlBuff.order(ByteOrder.nativeOrder());
      dlBuff=bDlBuff.asFloatBuffer();
      dlBuff.put(dl);
      dlBuff.position(0);

      ByteBuffer bSlBuff=ByteBuffer.allocateDirect(sl.length*4);
      bSlBuff.order(ByteOrder.nativeOrder());
      slBuff=bSlBuff.asFloatBuffer();
      slBuff.put(sl);
      slBuff.position(0);

      ByteBuffer bLPosBuff=ByteBuffer.allocateDirect(lPosition.length*4);
      bLPosBuff.order(ByteOrder.nativeOrder());
      lPosBuff=bLPosBuff.asFloatBuffer();
      lPosBuff.put(lPosition);
      lPosBuff.position(0);

} 

public void draw(GL10 gl){

    gl.glEnable(GL10.GL_CULL_FACE);
    gl.glEnable(GL10.GL_SMOOTH);
    gl.glEnable(GL10.GL_DEPTH_TEST);     
    gl.glTranslatef(0, 0, 0);
//  gl.glScalef(size, size, 1.0f);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertBuff);
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, points/2);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

 }  

  } 

1 个答案:

答案 0 :(得分:1)

嗯,这是一种代码审查。我希望这能让你开始。

  1. 球是物体(有点),有自己的位置,速度和加速度。必须在传感器更改时更新此状态。这有点摆弄价值观。不要忘记向GLSurfaceView询问redraw。然后绘制逻辑需要使用该位置将球移动到正确的位置。
  2. 我根本没有研究传感器校准,实施了一个简单的校准,在前五秒测量传感器输出,然后设置一个基准值。方向传感器为deprecated
  3. 考虑为球的初始状态设置一些随机值。
  4. 考虑抛弃那些杂乱无章的代码。例如,你有任何纹理吗?