无法让第二圈按照自己的路径运行



我无法创建更多的圆圈遵循自己的路径与drawCircle。

我使用了下面的代码,它创建了另一个圆,但遵循第一个圆的路径,但不是独立的。我如何移动两个圆彼此独立?

我添加了

    c.drawCircle(ballX-100, ballY-100, 50, ballPaintyellow);

如何使上面的圆独立于第一个圆?我真的很感激你的帮助。提前感谢。

BouncingBallActivity.java

 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 final BouncingBallModel model = new BouncingBallModel(BALL_RADIUS);
        private GameLoop gameLoop;
        private Paint backgroundPaint;
        private Paint ballPaint;
        private SensorManager sensorMgr;
        private long lastSensorUpdate = -1;

        private Paint ballPaintyellow;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.bouncing_ball);
            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();
            model.setVibrator(null);
            sensorMgr.unregisterListener(this, SENSOR_ACCELEROMETER);
            sensorMgr = null;
            model.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);
            model.setVibrator(vibrator);
        }
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {
            model.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, ballY;
            synchronized (model.LOCK) {
                ballX = model.ballPixelX;
                ballY = model.ballPixelY;
            }
            c.drawCircle(ballX, ballY, BALL_RADIUS, ballPaint);

            c.drawCircle(ballX-100, ballY-100, 50, ballPaintyellow);
        }
        public void surfaceDestroyed(SurfaceHolder holder) {
            try {
                model.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();
                        model.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;
                    model.setAccel(values[DATA_X], values[DATA_Y]);
                }
            }
        }
    }

Bouncingballmodel.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);
    }
}

您使用的视图与它无关....目前你只有一个BouncingBallModel

private final BouncingBallModel model = new BouncingBallModel(BALL_RADIUS);

这是你画东西时看到的。现在如果你想画多个球,你将需要许多BouncingBallModel。因此,要么创建一个BouncingBallModel model2,要么使用数组使其动态。

然后遍历数组并绘制每个球

最新更新