【问题标题】:Ball to Ball collision detection球对球碰撞检测
【发布时间】:2015-01-07 06:26:20
【问题描述】:

我试图在两个球碰撞时获得交点,以便我可以将它们重新反弹到其他方向。我尝试了各种方法来实现它,但没有成功。谁能告诉我有没有简单的方法来检测碰撞并重新反弹它。这是我的示例代码,球与设备的屏幕碰撞并反弹回来:-

class Ball extends ShapeDrawable {
        protected static final int BOUNDS_IN = 0;
        protected static final int BOUNDS_OUT_LEFT = 1;
        protected static final int BOUNDS_OUT_TOP = 2;
        protected static final int BOUNDS_OUT_RIGHT = 3;
        protected static final int BOUNDS_OUT_BOTTOM = 4;

        public float x;
        public float y;
        public int r;

        public float dx;
        public float dy;

        public Ball() {
            super(new OvalShape());

            getPaint().setColor(0xff888888);
        }

        public void reBounds() {
            setBounds((int) x - r, (int) y - r, (int) x + r, (int) y + r);
        }

        public void step(long deltaTimeMs) {
            // Log.i(TAG, "Time:" + deltaTimeMs);

            x += dx * deltaTimeMs / 100;
            y += dy * deltaTimeMs / 100;

            // Log.i(TAG, "x: "+x);
        }

        public int inBounds(int minx, int miny, int maxx, int maxy) {
            if (dx > 0 && x + r > maxx) {
                return BOUNDS_OUT_RIGHT;
            } else if (dx < 0 && x - r < minx) {
                return BOUNDS_OUT_LEFT;
            } else if (dy > 0 && y + r > maxy) {
                return BOUNDS_OUT_BOTTOM;
            } else if (dy < 0 && y - r < miny) {
                return BOUNDS_OUT_TOP;
            }
            return BOUNDS_IN;
        }
    };

    public CustomDrawableView(Context context) {
        super(context);

        Log.i(TAG, "Constructor Start");

        balls = new ArrayList<Ball>();

        update();

        Log.i(TAG, "Constructor End");
    }

    protected void onFirstDraw(Canvas canvas) {
        addRandomBalls(5);
    }

    protected void addRandomBalls(int number) {
        Ball mBall;

        Random r = new Random();

        for (int i = 0; i < number; i++) {
            mBall = new Ball();
            mBall.x = r.nextInt(MAX_X);
            mBall.y = r.nextInt(MAX_Y);
            mBall.r = 40;
            mBall.dx = r.nextInt(50) - 25;
            mBall.dy = r.nextInt(50) - 25;

            balls.add(mBall);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        MAX_X = MeasureSpec.getSize(widthMeasureSpec);
        MAX_Y = MeasureSpec.getSize(heightMeasureSpec);
    }

    protected void onDraw(Canvas canvas) {
        // Log.i(TAG, "onDraw Start");

        if (EXECUTE_ON_DRAW == false) {
            EXECUTE_ON_DRAW = true;

            onFirstDraw(canvas);
        }

        for (Ball b : balls) {
            // Log.i(TAG, "ball draw");
            b.reBounds();
            b.draw(canvas);
        }
    }

    public void update() {
        long now = System.currentTimeMillis();

        long difference = now - then;
        int inBound;
        for (Ball b : balls) {
            b.step(difference);
            inBound = b.inBounds(0, 0, MAX_X, MAX_Y);

            if (inBound == Ball.BOUNDS_OUT_BOTTOM
                    || inBound == Ball.BOUNDS_OUT_TOP) {
                b.dy *= -1;
            } else if (inBound == Ball.BOUNDS_OUT_LEFT
                    || inBound == Ball.BOUNDS_OUT_RIGHT) {
                b.dx *= -1;
            }
        }

        then = now;

        invalidate();

        mRedrawHandler.sleep(60);
    }

【问题讨论】:

  • 您需要使用空间索引数据结构来有效地执行此操作。一个相对简单的是四叉树 - 有关实现它并将其用于碰撞检测的一些信息可以在这里找到:graphics.ethz.ch/~achapiro/gc.html

标签: android math game-physics


【解决方案1】:

不知道我是否明白你的意思,但检查两个圆之间碰撞的最简单和最成功的方法是检查半径。您必须在每个球的中心找到 x 和 y 坐标。 它应该是这样的: centerX = x + widthOfBall/2 ; centerY =y + heigthOfBall/2;要检查两个球之间的碰撞,您只需要检查两个半径之和是否高于两个球中心之间的距离。要检查两个中心之间的距离谷歌两点之间的距离。

【讨论】:

  • Vedad - 检查所有对的碰撞在屏幕上的球数中花费 O(n^2) - 可能不适合任何中等大小的 n。空间索引是必要的。
  • sum of two half radius 我想你的意思是two half diametertwo times radius 如果两个球的半径相同?
  • 首先对不起我的英语,这不是很好:) 是的,我的意思是两个半径的总和。
猜你喜欢
  • 2010-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多