在碰撞侧滑动(2d自上而下运动)

时间:2018-06-03 14:57:08

标签: node.js 2d collision-detection top-down

我正在从头开始研究实时移动系统。我想绝对避免安装bilion节点模块,因为我更喜欢自己编写代码(也是为了深入了解正在发生的事情)。

到目前为止,我有一个有效的碰撞检测和碰撞距离模块。

现在我有一个在包含各种矩形的区域中移动的圆圈。所有内容都有bb //bounding box属性,圆圈包含中间xy坐标以及radius,而矩形包含左上角和右下角的坐标 - 正确点。

我在这里只使用2个函数:collision(如果2 bb碰撞则返回true)和circ_to_rect_dist(返回矩形最近边之间的距离)圆的最近点,如果圆是碰撞,则为0。它还返回距离的水平和垂直分量。)({d: distance, h: delta x, v: delta y}

现在,代码成功停止向墙壁移动(如果您的速度大于距离,则移动您联系)。但是一旦有接触,除了会破坏接触的方向之外,我不能朝其他方向移动。

例如,如果我的圆圈触及矩形的左侧,我无法向上或向下移动。那是因为最近点之间的垂直距离仍为0。

有关如何修改系统以使其能够“滑动”在墙上的任何想法吗?

另外,还有一个我无法解释的小错误: 向右,向下和向左移动会导致块的移动按预期移动,向上移动会让你怪异地弹跳,这很奇怪,考虑到它在其他3个方向上工作得很好......

无论如何,这是相关的代码: 运动功能:

step()
        {
        //MOVEMENT
        //MOVEMENT V 2.3
        if(this.hspeed != 0 || this.vspeed != 0)
            {
            var newx = this.bb.x + this.hspeed;
            var newy = this.bb.y + this.vspeed;

            for(var w=0; w < Wall.list.length; w++)
                {
                var wall = Wall.list[w];
                if(bb.collision(bb.circ(newx, newy, this.bb.radius), wall.bb))
                    {
                    var move_dist = bb.circ_to_rect_dist(this.bb, wall.bb)
                    var hspeed = move_dist.h * (this.hspeed<0?-1:1);
                    var vspeed = move_dist.v * (this.vspeed<0?-1:1);
                    newx = this.bb.x + hspeed;
                    newy = this.bb.y + vspeed;
                    }
                }
            this.bb.x = newx;
            this.bb.y = newy;
            }

        //OTHER
        for(var i in this.attacks)
            {
            if(this.attacks[i].reload > 0)
                {
                this.attacks[i].reload--;
                }
            else
                {
                if(this.attacks[i].pressed == 1)
                    {
                    this.attacks[i].reload = this.attacks_data[i].reload;
                    this.shoot(i);
                    }
                }
            }
        }

这是我正在使用的一组碰撞相关函数:

const bb = {}
module.exports = bb;
bb.point = function(x, y)
    {
    return(
        {
        type: "point",
        x: x,
        y: y
        });
    }
bb.line = function(x1, y1, x2, y2)
    {
    return(
        {
        type: "line",
        point: [bb.point(x1, y1), bb.point(x2, y2)]
        });
    }
bb.rect = function(x1, y1, x2, y2)
    {
    return(
        {
        type: "rect",
        point: [{x: x1, y: y1}, {x: x2, y: y2}]
        });
    }
bb.circ = function(x, y, radius)
    {
    return(
        {
        type: "circ",
        x: x,
        y: y,
        radius: radius
        });
    }


bb.circ_to_line_dist = function(a, b)
    {
    var ptl = bb.point_to_line_dist(a, b);
    ptl.d -= Math.min(a.radius, ptl.d);
    ptl.h -= Math.min(a.radius, ptl.h);
    ptl.v -= Math.min(a.radius, ptl.v);
    return(ptl);
    }
bb.circ_to_rect_dist = function(a, b)
    {
    var lines = bb.rect_extract_lines(b);
    var min_dist = bb.circ_to_line_dist(a, lines[0]);
    for(var i=1; i<lines.length; i++)
        {
        var tmp_dist = bb.circ_to_line_dist(a, lines[i]);
        if(tmp_dist.d < min_dist.d)
            {min_dist = tmp_dist;}
        }
    return(min_dist);
    }
bb.point_to_point_dist = function(a, b)
    {
    var dx = Math.abs(a.x - b.x);
    var dy = Math.abs(a.y - b.y);
    return({d: Math.sqrt(dx*dx + dy*dy), h: dx, v: dy});
    }
bb.point_to_line_dist = function(a, b)
    {
    /*var num = Math.abs( (b.point[1].y-b.point[0].y)*a.x - (b.point[1].x-b.point[0].x)*a.y + (b.point[1].x*b.point[0].y) - (b.point[1].y*b.point[0].x) );
    var den = bb.point_to_point_dist(b.point[0], b.point[1]);
    return(num/den);*/
    var A = a.x - b.point[0].x;
    var B = a.y - b.point[0].y;
    var C = b.point[1].x - b.point[0].x;
    var D = b.point[1].y - b.point[0].y;

    var dot = A * C + B * D;
    var len_sq = C * C + D * D;
    var param = -1;
    if (len_sq != 0) //in case of 0 length line
        {
        param = dot / len_sq;
        }

    var xx, yy;

    if (param < 0)
        {
        xx = b.point[0].x;
        yy = b.point[0].y;
        }
    else if (param > 1)
        {
        xx = b.point[1].x;
        yy = b.point[1].y;
        }
    else
        {
        xx = b.point[0].x + param * C;
        yy = b.point[0].y + param * D;
        }

    var dx = Math.abs(a.x - xx);
    var dy = Math.abs(a.y - yy);
    return {d: Math.sqrt(dx * dx + dy * dy), h: dx, v: dy};
    }


//circle and rectangle collision
bb.circ_to_rect = function(a, b)
    {
    if(bb.point_to_rect(a, b))
        {return(true);}

    var lines = bb.rect_extract_lines(b);
    for(var i in lines)
        {
        if(bb.line_to_circ(lines[i], a))
            {return(true);}
        }
    return(bb.point_to_rect(a, b));
    }

0 个答案:

没有答案