Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.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 为什么赢了';在我的乒乓球游戏中,球不会完全反弹吗?_Javascript_Arrays_Object_For Loop_Continue - Fatal编程技术网

Javascript 为什么赢了';在我的乒乓球游戏中,球不会完全反弹吗?

Javascript 为什么赢了';在我的乒乓球游戏中,球不会完全反弹吗?,javascript,arrays,object,for-loop,continue,Javascript,Arrays,Object,For Loop,Continue,我在javascript的画布上有多个省略号,我希望它们都能相互反弹。我尝试使用距离公式,然后在距离小于球半径*2时更改球的x和y方向 这对于一个球来说效果很好,但是对于很多球来说效果不太好,因为它经常会导致可怕的“反弹循环” 为了解决这个问题,我决定根据球相互碰撞的位置改变球反弹的方式,以避免反弹循环,并使游戏更接近现实物理 如果有侧向碰撞,我想反转两个球的x方向,如果有上下碰撞,我想反转两个球的y方向 因此,我计算了所有的点,例如,45度到135度之间与度相关的点(即90点),并将它们与2

我在javascript的画布上有多个省略号,我希望它们都能相互反弹。我尝试使用距离公式,然后在距离小于球半径*2时更改球的x和y方向

这对于一个球来说效果很好,但是对于很多球来说效果不太好,因为它经常会导致可怕的“反弹循环”

为了解决这个问题,我决定根据球相互碰撞的位置改变球反弹的方式,以避免反弹循环,并使游戏更接近现实物理

如果有侧向碰撞,我想反转两个球的x方向,如果有上下碰撞,我想反转两个球的y方向

因此,我计算了所有的点,例如,45度到135度之间与度相关的点(即90点),并将它们与225度到315度之间的所有90点进行比较,反之亦然

如果圆边缘上的任意点与所有其他球中心点之间的距离小于半径,我希望两个球的Y方向都反转

我在135度和225度到315度和405度(相当于45度)重复相同的过程,并反转两个球的X方向

就目前而言,我认为球应该按照我所希望的方式相互反弹,但事实并非如此。它们从彼此的侧面、顶部、底部反弹,偶尔也会以一定角度反弹,但它们倾向于彼此向内倾斜,然后改变方向。这是一个

下面是从上到下比较的代码:

    // radius is the same for all the balls and is at 25.
let ballToBallDistance = (x1, y1, x2, y2) => {
    return Math.sqrt((Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)));
}
const ballCollisionY = (start, end) => {
    for (let i = start; i <= end; i++) {
        return ballObjects[0].ballRadius * Math.sin((i * Math.PI / 180));
    }
}
const ballCollisionX = (start, end) => {
    for (let i = start; i <= end; i++) {
        return ballObjects[0].ballRadius * Math.cos((i * Math.PI / 180));
    }
}
const upperYBall = {
    bounceTopBottom() {
        let n = 0;
        for (let i = 0; i < ballObjects.length; i++) {
            if (ballObjects.length == 1) {
                return;
            }
            if (n == i) {
                continue;
            }
            let yUpXPoint = ballObjects[n].ballXPos - ballCollisionX(45, 135);
            let yUpYPoint = ballObjects[n].ballYPos - ballCollisionY(45, 135);
            let centerBallX = ballObjects[i].ballXPos;
            let centerBallY = ballObjects[i].ballYPos;
            let pointDistance = ballToBallDistance(yUpXPoint, yUpYPoint, centerBallX, centerBallY);
            if (pointDistance <= 25) {
                ballObjects[n].ballMotionY = ballObjects[n].ballMotionY * -1;
            }
            if (i == ballObjects.length - 1) {
                ++n;
                i = -1;
                continue;
            }
        }
    }
}
const lowerYBall = {
    bounceBottomTop() {
        let n = 0;
        for (let i = 0; i < ballObjects.length; i++) {
            if (ballObjects.length == 1) {
                return;
            }
            if (n == i) {
                continue;
            }
            let yDownXPoint = ballObjects[n].ballXPos - ballCollisionX(225, 315);
            let yDownYPoint = ballObjects[n].ballYPos - ballCollisionY(225, 315);
            let centerBallX = ballObjects[i].ballXPos;
            let centerBallY = ballObjects[i].ballYPos;
            let pointDistance = ballToBallDistance(yDownXPoint, yDownYPoint, centerBallX, centerBallY);
            if (pointDistance <= 25) {
                ballObjects[n].ballMotionY = ballObjects[n].ballMotionY * -1;
            }
            if (i == ballObjects.length - 1) {
                ++n;
                i = -1;
                continue;
            }
        }
    }
}
//所有球的半径相同,为25。
设ballToBallDistance=(x1,y1,x2,y2)=>{
返回Math.sqrt((Math.pow(x2-x1,2)+Math.pow(y2-y1,2));
}
const ballCollisionY=(开始、结束)=>{
for(让我=开始;我{

对于(让i=start;i我建议您从特例编码切换到更通用的方法

当两个球碰撞时:

  • 计算碰撞法线(角度)
  • 根据以前的速度和法线计算新速度
  • 重新定位球,使其不再重叠,防止“反弹循环”
  • 您将需要:

    计算两个球之间角度的方法:

    function ballToBallAngle(ball1,ball2) {
        return Math.atan2(ball2.y-ball1.y,ball2.x-ball1.x)
    }
    
    从角度导出法向量的方法:

    function calcNormalFromAngle(angle){
      return [
        Math.cos(angle),
        Math.sin(angle)
      ]
    }
    
    计算两个向量的点积的方法:

    function dotproduct (a, b){
        return a.map((x, i) => a[i] * b[i]).reduce((m, n) => m + n)
    }
    
    最后给出了一种计算弹跳角的方法,对其进行了完美的描述

    因此,要将其放在一起,请参见下面的片段:

    let canvas=document.querySelector('canvas')
    设ctx=canvas.getContext('2d')
    让球=[
    {x:40,y:40,半径:25,vx:4,vy:3},
    {x:300,y:300,半径:50,vx:-2,vy:-3},
    {x:100,y:220,半径:25,vx:4,vy:-3},
    {x:400,y:400,半径:50,vx:-1,vy:-3},
    {x:200,y:400,半径:32,vx:2,vy:-3}
    ]
    函数tick(){
    球。forEach((球,索引)=>{
    ball.x+=ball.vx
    ball.y+=ball.vy
    //检查x边界冲突
    if(球x-球半径<0){
    弹跳球(球,数学,圆周率)
    ball.x=ball.radius
    }否则如果(球x+球半径>500){
    弹跳球(球,0)
    球体x=500-球体半径
    }
    //检查y边界碰撞
    if(球y-球半径<0){
    弹跳球(球,Math.PI/2)
    ball.y=ball.radius
    }否则如果(球y+球半径>500){
    弹跳球(球,-Math.PI/2)
    球体y=500-球体半径
    }
    球。forEach((其他球,其他指数)=>{
    如果(索引==其他索引)
    返回
    //球相交多少像素
    让交点=球半径+其他球半径-球到球距离(球,其他球)
    //如果大于0,则它们必须碰撞
    如果(交点>0){
    让球角度=球角度(球、其他球)
    让法线=calcNormalFromAngle(角度)
    弹跳球(球、角度)
    弹跳球(其他球,角度+数学PI)
    //设置位置,使它们不再重叠
    ball.x-=法线[0]*交点/2
    ball.y-=法线[1]*交点/2
    其他球x+=正常[0]*交点/2
    其他球y+=正常[1]*交点/2
    }
    })
    })
    render()
    requestAnimationFrame(勾选)
    }
    函数render(){
    clearRect(0,0,canvas.width,canvas.height)
    balls.forEach(ball=>{
    ctx.beginPath();
    弧(ball.x,ball.y,ball.radius,0,2*Math.PI);
    ctx.stroke();
    })
    }
    功能弹跳球(球、角度){
    让法线=calcNormalFromAngle(角度)
    让速度=[ball.vx,ball.vy]
    设ul=点积(速度,正常)/点积(正常,正常)
    设u=[
    正常[0]*ul,
    正常[1]*ul
    ]
    设w=[
    速度[0]-u[0],
    速度[1]-u[1]
    ]
    设新的_速度=[
    w[0]-u[0],
    w[1]-u[1]
    ]
    ball.vx=新的_速度[0]
    ball.vy=新的速度[1]
    }
    功能点积(a,b){
    返回a.map((x,i)=>a[i]*b[i])。reduce((m,n)=>m+n)
    }
    功能球到球距离(球1、球2){
    返回Math.sqrt((Math.pow(ball2.x-ball1.x,2)+Math.pow(ball2.y-ball1.y,2));
    }
    函数ballToBallAngle(ball1、ball2){
    返回Math.atan2(ball2.y-ball1.y,ball2.x-ball1.x)
    }
    函数calcNormalFromAngle(角度){
    返回[
    数学cos(角度),
    数学。sin(角度)
    ]
    }
    勾选();
    正文{
    背景色:#eee;
    }
    帆布{
    背景色:白色;
    }