请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于circle互相碰撞的bug

bobo老师您好,添加circle互相碰撞机制后,我有一个问题:

一开始页面不会有bug,但碰撞事件较密集(例如多个circle在边界碰撞)会出现circle“吸附”到绘图板边界的情况(我猜测是否和每次绘图的刷新帧率(这里是1000/20=50)有关),如图:
图片描述

circle之间碰撞逻辑如下:

public void move(int minx,int miny,int maxx,int maxy,Circle[] circles) {
        x += vx;
        y += vy;
        checkCollision(minx,miny,maxx,maxy,circles);
    }

    private void checkCollision(int minx,int miny,int maxx,int maxy,Circle[] circles) {
        //监测边界碰撞
        if (x <= minx || x >= maxx) vx = -vx;
        if (y <= miny || y >= maxy) vy = -vy;

        //监测圆的碰撞,碰撞的判定条件为圆心距离之和小于2r
        for (Circle c : circles) {
            if (this == c) continue;
            //交换速度
            if (getD(this,c) <= 4*r*r) {
                int cvx = c.vx, cvy = c.vy;
                c.vx = vx;
                c.vy = vy;
                vx = cvx;
                vy = cvy;
            }
        }
    }

    //得到两圆心距离的平方
    private int getD(Circle c1, Circle c2) {
        return (int) (Math.pow(Math.abs(c1.x-c2.x),2) + Math.pow(Math.abs(c1.y-c2.y),2));
    }

相应地我在初始生成circle数组时避免circle之间的重叠:

	//绘制n个半径为r的圆
    public static Circle[] generateCircles(int n, int r, int sceneWidth, int sceneHeight) {
        Circle[] circles = new Circle[n];
        int[][] location = new int[n][2];
        for (int i = 0; i < n; i++) {
            int x,y;
            //检查初始是否有重叠,如果有重叠则重新生成x和y
            do {
                x = r+(int)(Math.random()*(sceneWidth-2*r));
                y = r+(int)(Math.random()*(sceneHeight-2*r));
            } while (checkIfInValid(location,x,y,r));
            location[i][0] = x;
            location[i][1] = y;
            int vx = (int)(Math.random()*11)-5;
            int vy = (int)(Math.random()*11)-5;
            circles[i] = new Circle(x,y,vx,vy,r);
        }
        return circles;
    }

    //检查是否有重叠,如果有重叠返回true,如果没有重叠返回false
    private static boolean checkIfInValid(int[][] location, int x, int y,int r) {
        for (int[] ints : location) {
            int cx = ints[0], cy = ints[1];
            if (cx == 0) break;
            int d2 = (int) (Math.pow(Math.abs(x-cx),2) + Math.pow(Math.abs(y-cy),2));
            if (d2 <= 4*r*r) return true;
        }
        return false;
    }

请问是否应该应该改写碰撞逻辑?

正在回答

1回答

目测是在边界产生的 bug,根据我观察你给我的图示:道理上圆是不应该“进入上边界或者下边界的。你展示的动画貌似一旦圆“进入”上边界或者下边界(圆心和边界的距离小于 r),就会出问题。(但 interesting 为什么左右边界没有看到问题。)


不管怎样,你可以尝试一下,在圆心到边界的距离小于 r 的时候,不但改变速度,同时改变圆心的位置,强行让圆心和碰撞边界之间的距离是 r。合理推测出现问题的原因是:在某一帧,圆心“进入了边界,但在下一帧,圆心还在边界内部,所以速度不断改变方向,在边界内”不同震荡。


继续加油!:)

1 回复 有任何疑惑可以回复我~
  • 提问者 云古符 #1
    嗯嗯,确实应该在边界发生碰撞时强行变更圆心距离为r,这回解决了,谢谢老师!
    回复 有任何疑惑可以回复我~ 2023-02-18 12:37:13
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信