2012-03-30 68 views
0

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

因为这往往很长,所以请让我澄清一下你不理解的位,我会通过编辑来解决它们。

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

} 

    } 
+0

请添加'MyGLBall'的实现。它是否包含其位置,速度和加速度? – 2012-03-30 14:01:26

+0

@StefanHanke更新了我的答案。不,我不知道。这是一个问题吗? – jmishra 2012-03-30 15:49:31

+0

这取决于你想达到什么;)当用户倾斜设备时,球应该像移动设备一样移动? – 2012-03-30 16:23:47

回答

1

好实施,这是怎样的一个代码审查的。我希望这能让你开始。

  1. 球是物理对象(有点),并有自己的位置,速度和加速度。此状态必须在更换传感器时更新。这是有点摆弄的价值观。不要忘记询问GLSurfaceViewredraw。绘图逻辑然后需要使用该位置将球移动到正确的位置。
  2. 我还没有看过传感器校准,实施了一个简单的校准,即在第一个五秒内测量传感器输出,然后设置一个基准值。方向传感器是deprecated
  3. 考虑设置球的初始状态的一些随机值。
  4. 考虑抛出只是混乱的代码。例如,你在这里有任何纹理?