Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript p5.js对象碰撞和对象缠绕_Javascript_Canvas_Collision Detection_P5.js - Fatal编程技术网

Javascript p5.js对象碰撞和对象缠绕

Javascript p5.js对象碰撞和对象缠绕,javascript,canvas,collision-detection,p5.js,Javascript,Canvas,Collision Detection,P5.js,我在p5.js中写了一些代码,看看我是否能正确地制作一个碰撞检测系统,但当我放入超过2个方块时,方块似乎在其他方块中相互碰撞。我想知道是否有任何方法可以阻止这一切,另外,如果你对如何整理/缩短我的代码有什么好的建议,我想听听 我的代码: var r; //later defined as an array for the squares var num; //number of squares function setup(){ r = []; num = 10; cre

我在p5.js中写了一些代码,看看我是否能正确地制作一个碰撞检测系统,但当我放入超过2个方块时,方块似乎在其他方块中相互碰撞。我想知道是否有任何方法可以阻止这一切,另外,如果你对如何整理/缩短我的代码有什么好的建议,我想听听

我的代码:

var r; //later defined as an array for the squares
var num; //number of squares
function setup(){
    r = [];
    num = 10;
    createCanvas(windowWidth,windowHeight- 4);
    for(var i = 0;i < num; i++){

        r[i] = new Box(random(width-40),random(height-40),40,40);

    }

}

function draw(){
    background(40);
    for(var i = 0;i < num; i++)    {
        r[i].show();
        for(var j = 0;j<num; j++){

            //this is the if statement evaluating if the left and right of the square is touching each other. i is one square and j is the other. you see in each if statement i have the acceleration being added, this is because if it wasn't then they would be true if the squares were touching each other on any side
            if(r[i].right+r[i].xa >= r[j].left && r[i].bottom >= r[j].top && r[i].top <= r[j].bottom && r[i].left + r[i].xa <= r[j].right){
                r[i].xa *= -1;
                r[j].xa *= -1;

            }
            //this is also just as confusing just read through it carefully
            if(r[i].bottom + r[i].ya >= r[j].top && r[i].right >=r[j].left && r[i].left <= r[j].right && r[i].top + r[i].ya <= r[j].bottom){
                r[i].ya *= -1;
                r[j].ya *= -1;
            }
        }    
    }


}
function Box(x, y, wid, hei){

    this.x = x;//input for square shape
    this.y = y;//ditto
    this.width = wid;//ditto
    this.height= hei;//ditto
    this.xa = random(2,5);//xa is the x acceleration
    this.ya = random(2,5);//ya is the y acceleration
    this.left;
    this.right;
    this.top;
    this.bottom;
    this.show = function(){
        this.left = this.x;     //i define left,right,top,bottom in show function so they get updated
        this.right = this.x +this.width;
        this.top = this.y;
        this.bottom = this.y +this.height;
        push();
        fill(255);
        noStroke();
        rect(this.x,this.y,this.width,this.height);
        pop();//push pop just in case i want to change square colors individually in the future
        this.x += this.xa;//adding acceleration to the squares
        this.y += this.ya;//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        if(this.x > width-this.width||this.x <0){//bouncing off the right and left wall
            this.xa *= -1;
            if(this.x > width/2){// making sure if the square spawns or glitches on the other side of the wall it doesn't get stuck, this checks which side the square is on when it touches the wall then moves it directly on the wall
                this.x = width-this.width;
            }else{
                this.x = 0;
            }
        }
        if(this.y > height-this.height||this.y <0){// same as above but for the y axis
            this.ya *= -1;
            if(this.y > height/2){
                this.y = height-this.height;
            }else{
                this.y = 0;
            }

        }

    }
}
function windowResized(){
    createCanvas(windowWidth,windowHeight- 4);//window resizing adjustment
}
var-r//后来定义为正方形的数组
var-num//方块数
函数设置(){
r=[];
num=10;
createCanvas(窗口宽度,窗口高度-4);
对于(变量i=0;i
您可以使用查看它。 只需复制并粘贴。

无法解决的问题的解决方案 对不起,没有这样的事

当场景中有许多移动对象时,碰撞解决方案并不容易

你眼前的问题 你的问题主要是因为你在假设盒子碰撞时的移动方向。将方向乘以-1以反转方向

对于2个对象都很好,但是添加第3个对象,您将最终得到3个对象。每次你改变方向,box1和box2都会彼此移动,然后在同一帧中box1和box3会移动,现在box1和box3会分开。你的速度是恒定的,所以在三向碰撞后,总会有两个盒子朝着相同的方向移动,但重叠

下一帧上的重叠框检测重叠和两个反向,因为它们已经沿同一方向移动,方向开关不会帮助它们分开

向前迈出的一步 还有一步,下面对代码的修改只是确保在可能的情况下碰撞会导致长方体彼此远离

function draw() {
    background(40);
    for (var i = 0; i < num; i++) {
        const bx1 = r[i];
        r[i].show();
        for (var j = 0; j < num; j++) {
            if (j !== i) {
                // t for top, b for bottom, r for right and l for left. 1 for first box 2 for second
                // bx for box
                const bx2 = r[j];
                const t1 = bx1.top + bx1.ya;
                const b1 = bx1.bottom + bx1.ya;
                const l1 = bx1.left + bx1.xa;
                const r1 = bx1.right + bx1.xa;
                const t2 = bx2.top + bx2.ya;
                const b2 = bx2.bottom + bx2.ya;
                const l2 = bx2.left + bx2.xa;
                const r2 = bx2.right + bx2.xa;
                // the or's mean that the condition will complete at the first passed clause
                // If not (not over lapping)  AKA is overlapping
                if (!(t1 > b2 || b1 < t2 || l1 > r2 || r1 < l2)) {
                    if (r1 >= l2) {
                        bx1.xa = -Math.abs(bx1.xa);
                        bx2.xa = Math.abs(bx2.xa);
                    }
                    if (l1 <= r2) {
                        bx1.xa = Math.abs(bx1.xa);
                        bx2.xa = -Math.abs(bx2.xa);
                    }

                    if (b1 >= t2) {
                        bx1.ya = -Math.abs(bx1.ya);
                        bx2.ya = Math.abs(bx2.ya);
                    }
                    if (t1 <= b2) {
                        bx1.ya = Math.abs(bx1.ya);
                        bx2.ya = -Math.abs(bx2.ya);
                    }
                }
            }
        }
    }
}
您可以按如下方式移动一个框

sx = box.x - box.ox;
sy = box.y - box.oy;
box.ox = box.x;
box.oy = box.y;
box.x += sx;  // the boxes old position
box.y += sy;
当你击中某物时,你需要改变原来的位置,以便给下一次迭代提供正确的方向

if(box.y > ground){
   box.y = ground - (box.y - ground); // move away from ground same dist as moved into ground
   box.oy = box.y -sy;
}
分组做。 一次移动所有对象,然后立即测试碰撞。不要一次移动和测试一个


Verlet集成更加宽容,因为它可以让移动速度吸收一些错误。而不是像标准向量方法那样完全到位。

我实际上很难理解您的代码,因此很难确定可能的原因。我建议您对代码进行注释,并提取每个单独的条件,将这些条件存储在一个具有描述性名称的变量中,然后将这些变量插入if语句中。变量名将有助于澄清您的意图并提高if语句的可读性,这将使您更容易识别错误。@B.弗莱明谢谢您,我将为您编辑并执行此操作。我应该为矩形创建变量,比如r[I]。对。left etc.@B.Fleming我已经编辑了我的代码并对其进行了注释。您评论为“混乱”的部分是最需要重构的部分。“仔细阅读”可能有助于我理解它在做什么,但不能理解它为什么这样做,或者现有的行为是否是你想要的。如果您在If语句之外进行单独的比较,并将其结果存储在描述性变量中,那么If语句将更易于您阅读和调试,也更易于其他人阅读和理解您尝试执行的操作。长而复杂的if语句调试和维护起来很痛苦,如果可能的话应该避免;我要把我修复的虫子贴出来作为答案我被这个答案吓呆了。我很想弄明白这一点。这是一个很好的关于物体碰撞的信息来源,我在互联网上找不到,谢谢。
if(box.y > ground){
   box.y = ground - (box.y - ground); // move away from ground same dist as moved into ground
   box.oy = box.y -sy;
}