2014-03-25 60 views
0

我試圖讓一個球彈跳到動態球彈跳。例如:這裏圈數是50. 但是我在嘗試使圓圈動態(模型)時出現錯誤。如何使它工作並使模型/圓圈動態。在這種情況下,有50個圓圈?我非常感謝任何幫助。提前致謝。無法將圈子動態添加到畫布上

package com.stuffthathappens.games; 

import static android.hardware.SensorManager.DATA_X; 
import static android.hardware.SensorManager.DATA_Y; 
import static android.hardware.SensorManager.SENSOR_ACCELEROMETER; 
import static android.hardware.SensorManager.SENSOR_DELAY_GAME; 

import java.util.concurrent.TimeUnit; 

import android.app.Activity; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.hardware.SensorListener; 
import android.hardware.SensorManager; 
import android.os.Bundle; 
import android.os.Vibrator; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.SurfaceHolder.Callback; 

/** 
* This activity shows a ball that bounces around. The phone's 
* accelerometer acts as gravity on the ball. When the ball hits 
* the edge, it bounces back and triggers the phone vibrator. 
*/ 
@SuppressWarnings("deprecation") 
public class BouncingBallActivity extends Activity implements Callback, SensorListener { 
    private static final int BALL_RADIUS =20; 
    private SurfaceView surface; 
    private SurfaceHolder holder; 

    private GameLoop gameLoop; 
    private Paint backgroundPaint; 
    private Paint ballPaint; 
    private SensorManager sensorMgr; 
    private long lastSensorUpdate = -1; 


    private Paint ballPaintyellow; 

    private BouncingBallModel[] model; 

    int Totalcircles=50; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.bouncing_ball); 

     for (int i = 0; i < Totalcircles; i++) { 
      model[i] = new BouncingBallModel(BALL_RADIUS); 
     } 

     surface = (SurfaceView) findViewById(R.id.bouncing_ball_surface); 
     holder = surface.getHolder(); 
     surface.getHolder().addCallback(this); 

     backgroundPaint = new Paint(); 
     backgroundPaint.setColor(Color.WHITE); 

     ballPaint = new Paint(); 
     ballPaint.setColor(Color.BLUE); 
     ballPaint.setAntiAlias(true); 

     ballPaintyellow = new Paint(); 
     ballPaintyellow.setColor(Color.YELLOW); 
     ballPaintyellow.setAntiAlias(true); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 

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

      model[i].setVibrator(null); 
     } 

     sensorMgr.unregisterListener(this, SENSOR_ACCELEROMETER); 
     sensorMgr = null; 

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

      model[i].setAccel(0, 0); 
     } 


    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 

     sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE); 
     boolean accelSupported = sensorMgr.registerListener(this, 
       SENSOR_ACCELEROMETER, 
       SENSOR_DELAY_GAME); 

     if (!accelSupported) { 
      // on accelerometer on this device 
      sensorMgr.unregisterListener(this, SENSOR_ACCELEROMETER); 
      // TODO show an error 
     } 

     // NOTE 1: you cannot get system services before onCreate() 
     // NOTE 2: AndroidManifest.xml must contain this line: 
     // <uses-permission android:name="android.permission.VIBRATE"/> 
     Vibrator vibrator = (Vibrator) getSystemService(Activity.VIBRATOR_SERVICE); 

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

      model[i].setVibrator(vibrator); 
     } 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 


     for (int i = 0; i < Totalcircles; i++) { 
      model[i].setSize(width, height); 
     } 
    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     gameLoop = new GameLoop(); 
     gameLoop.start(); 
    } 

    private void draw() { 
     // thread safety - the SurfaceView could go away while we are drawing 

     Canvas c = null; 
     try { 
      // NOTE: in the LunarLander they don't have any synchronization here, 
      // so I guess this is OK. It will return null if the holder is not ready 
      c = holder.lockCanvas(); 

      // this needs to synchronize on something 
      if (c != null) { 
       doDraw(c); 
      } 
     } finally { 
      if (c != null) { 
       holder.unlockCanvasAndPost(c); 
      } 
     } 
    } 

    private void doDraw(Canvas c) { 
     int width = c.getWidth(); 
     int height = c.getHeight(); 
     c.drawRect(0, 0, width, height, backgroundPaint); 

     /// 

     float ballX[]=new float[50], ballY[]=new float[50]; 

     for (int i = 0; i < Totalcircles; i++) { 
      synchronized (model[i].LOCK) { 
       ballX[i] = model[i].ballPixelX; 
       ballY[i] = model[i].ballPixelY; 

      } 
     } 

     // 

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

      c.drawCircle(ballX[i], ballY[i], BALL_RADIUS, ballPaint); 
     } 
     } 


    public void surfaceDestroyed(SurfaceHolder holder) { 
     try { 

      for (int i = 0; i < Totalcircles; i++) { 
       model[i].setSize(0,0); 
      } 
      gameLoop.safeStop(); 
     } finally { 
      gameLoop = null; 
     } 
    } 

    private class GameLoop extends Thread { 
     private volatile boolean running = true; 

     public void run() { 
      while (running) { 
       try { 
        // don't like this hardcoding 
        TimeUnit.MILLISECONDS.sleep(5); 

        draw(); 

        for (int i = 0; i < Totalcircles; i++) { 
         model[i].updatePhysics(); 
        } 

       } catch (InterruptedException ie) { 
        running = false; 
       } 
      } 
     } 

     public void safeStop() { 
      running = false; 
      interrupt(); 
     } 
    } 

    public void onAccuracyChanged(int sensor, int accuracy) {  
    } 

    public void onSensorChanged(int sensor, float[] values) { 
     if (sensor == SENSOR_ACCELEROMETER) { 
      long curTime = System.currentTimeMillis(); 
      // only allow one update every 50ms, otherwise updates 
      // come way too fast 
      if (lastSensorUpdate == -1 || (curTime - lastSensorUpdate) > 50) { 
       lastSensorUpdate = curTime; 

       for (int i = 0; i < Totalcircles; i++) { 
        model[i].setAccel(values[DATA_X], values[DATA_Y]); 
       } 
      } 
     } 
    } 
} 

model.java

package com.stuffthathappens.games; 

import java.util.concurrent.atomic.AtomicReference; 

import android.os.Vibrator; 

/** 
* This data model tracks the width and height of the playing field along 
* with the current position of a ball. 
*/ 
public class BouncingBallModel { 
    // the ball speed is meters/second. When we draw to the screen, 
    // 1 pixel represents 1 meter. That ends up too slow, so multiply 
    // by this number. Bigger numbers speeds things up. 
    private final float pixelsPerMeter = 10; 

    private final int ballRadius; 

    // these are public, so make sure you synchronize on LOCK 
    // when reading these. I made them public since you need to 
    // get both X and Y in pairs, and this is more efficient than 
    // getter methods. With two getters, you'd still need to 
    // synchronize. 
    public float ballPixelX, ballPixelY; 

    private int pixelWidth, pixelHeight; 

    // values are in meters/second 
    private float velocityX, velocityY; 

    // typical values range from -10...10, but could be higher or lower if 
    // the user moves the phone rapidly 
    private float accelX, accelY; 

    /** 
    * When the ball hits an edge, multiply the velocity by the rebound. 
    * A value of 1.0 means the ball bounces with 100% efficiency. Lower 
    * numbers simulate balls that don't bounce very much. 
    */ 
    private static final float rebound = 0.8f; 

    // if the ball bounces and the velocity is less than this constant, 
    // stop bouncing. 
    private static final float STOP_BOUNCING_VELOCITY = 2f; 

    private volatile long lastTimeMs = -1; 

    public final Object LOCK = new Object(); 

    private AtomicReference<Vibrator> vibratorRef = 
     new AtomicReference<Vibrator>(); 

    public BouncingBallModel(int ballRadius) { 
     this.ballRadius = ballRadius; 
    } 

    public void setAccel(float ax, float ay) { 
     synchronized (LOCK) { 
      this.accelX = ax; 
      this.accelY = ay; 
     } 
    } 

    public void setSize(int width, int height) { 
     synchronized (LOCK) { 
      this.pixelWidth = width; 
      this.pixelHeight = height; 
     } 
    } 

    public int getBallRadius() { 
     return ballRadius; 
    } 

    /** 
    * Call this to move the ball to a particular location on the screen. This 
    * resets the velocity to zero, but the acceleration doesn't change so 
    * the ball should start falling shortly. 
    */ 
    public void moveBall(int ballX, int ballY) { 
     synchronized (LOCK) { 
      this.ballPixelX = ballX; 
      this.ballPixelY = ballY; 
      velocityX = 0; 
      velocityY = 0; 
     } 
    } 

    public void updatePhysics() { 
     // copy everything to local vars (hence the 'l' prefix) 
     float lWidth, lHeight, lBallX, lBallY, lAx, lAy, lVx, lVy; 
     synchronized (LOCK) { 
      lWidth = pixelWidth; 
      lHeight = pixelHeight; 
      lBallX = ballPixelX; 
      lBallY = ballPixelY; 
      lVx = velocityX;    
      lVy = velocityY; 
      lAx = accelX; 
      lAy = -accelY; 
     } 


     if (lWidth <= 0 || lHeight <= 0) { 
      // invalid width and height, nothing to do until the GUI comes up 
      return; 
     } 


     long curTime = System.currentTimeMillis(); 
     if (lastTimeMs < 0) { 
      lastTimeMs = curTime; 
      return; 
     } 

     long elapsedMs = curTime - lastTimeMs; 
     lastTimeMs = curTime; 

     // update the velocity 
     // (divide by 1000 to convert ms to seconds) 
     // end result is meters/second 
     lVx += ((elapsedMs * lAx)/1000) * pixelsPerMeter; 
     lVy += ((elapsedMs * lAy)/1000) * pixelsPerMeter; 

     // update the position 
     // (velocity is meters/sec, so divide by 1000 again) 
     lBallX += ((lVx * elapsedMs)/1000) * pixelsPerMeter; 
     lBallY += ((lVy * elapsedMs)/1000) * pixelsPerMeter; 

     boolean bouncedX = false; 
     boolean bouncedY = false; 

     if (lBallY - ballRadius < 0) { 
      lBallY = ballRadius; 
      lVy = -lVy * rebound; 
      bouncedY = true; 
     } else if (lBallY + ballRadius > lHeight) { 
      lBallY = lHeight - ballRadius; 
      lVy = -lVy * rebound; 
      bouncedY = true; 
     } 
     if (bouncedY && Math.abs(lVy) < STOP_BOUNCING_VELOCITY) { 
      lVy = 0; 
      bouncedY = false; 
     } 

     if (lBallX - ballRadius < 0) { 
      lBallX = ballRadius; 
      lVx = -lVx * rebound; 
      bouncedX = true; 
     } else if (lBallX + ballRadius > lWidth) { 
      lBallX = lWidth - ballRadius; 
      lVx = -lVx * rebound; 
      bouncedX = true; 
     } 
     if (bouncedX && Math.abs(lVx) < STOP_BOUNCING_VELOCITY) { 
      lVx = 0; 
      bouncedX = false; 
     } 


     // safely copy local vars back to object fields 
     synchronized (LOCK) { 
      ballPixelX = lBallX; 
      ballPixelY = lBallY; 

      velocityX = lVx; 
      velocityY = lVy; 
     } 

     if (bouncedX || bouncedY) { 
      Vibrator v = vibratorRef.get(); 
      if (v != null) { 
       v.vibrate(20L); 
      } 
     } 
    } 

    public void setVibrator(Vibrator v) { 
     vibratorRef.set(v); 
    } 
} 

logcat的錯誤:

FATAL EXCEPTION: main 
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.stuffthathappens.games/com.stuffthathappens.games.BouncingBallActivity}: java.lang.NullPointerException 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2194) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2229) 
    at android.app.ActivityThread.access$600(ActivityThread.java:139) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1261) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loop(Looper.java:154) 
    at android.app.ActivityThread.main(ActivityThread.java:4945) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:511) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
    at dalvik.system.NativeStart.main(Native Method) 
Caused by: java.lang.NullPointerException 
    at com.stuffthathappens.games.BouncingBallActivity.onCreate(BouncingBallActivity.java:52) 
    at android.app.Activity.performCreate(Activity.java:4531) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1071) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2150) 
+0

它看起來並不像你初始化數組'BouncingBallModel []模型;' – xecaps12

+0

@ xecaps12如何以及在哪裏辦that.I真的很感激你help.Thanks – jason

+0

我認爲這場耗時的照顧。 ....... for(int i = 0;我 jason

回答