确定矩形上垂直或水平墙上的命中

时间:2023-02-09 15:47:36

Currently i am working on bouncing a ball of a wall, in classic 2D-geometry.

目前我正在以经典的2D几何图形弹跳一个墙球。

The wall can be hit on both vertical and horizontal sides, and the result of the reflection depends on which side the ball hits.

墙壁可以在垂直和水平两侧被击中,反射的结果取决于球击中的哪一侧。

I have tried some different solutions, but they just make me more confused.

我尝试了一些不同的解决方案,但它们让我更加困惑。

How can i determine whether the ball is hitting a vertical or horizontal side of the wall?

如何确定球是否击中墙的垂直或水平侧?

PseudoCode for the overview:

PseudoCode概述:

iterate through each wall
if (collision between ball and wall)
  determine if vertical/horizontal hit
  calculate new velocity for ball

I use this code for collision detection and it works like a charm: source: Circle-Rectangle collision detection (intersection)

我使用此代码进行碰撞检测,它就像一个魅力:源:圆形 - 矩形碰撞检测(交集)

var isCollision = function (_projectile) {
    if(direction != undefined){
        var circleDistance = {};
        circleDistance.x = Math.abs(_projectile.getCenter().x - centerX);
        circleDistance.y = Math.abs(_projectile.getCenter().y - centerY);

        if (circleDistance.x > (width/2 + _projectile.getRadius())) { return false; }
        if (circleDistance.y > (height/2 + _projectile.getRadius())) { return false; }

        if (circleDistance.x <= (width/2)) { return true; }
        if (circleDistance.y <= (height/2)) { return true; }

        var cornerDistance_sq = square(circleDistance.x - width/2) + square(circleDistance.y - height/2);

        return (cornerDistance_sq <= (square(_projectile.getRadius())));
    }
    return false;
};

var square = function(_value){
    return _value * _value;
};

Thank you!

2 个解决方案

#1


update after question update

问题更新后更新

Asuming the ball has a direction/velocity vector dx,dy and has a radius of r (ball.x, ball.y are the ball positions of the ball center) do sth like this (have used similar in a billiard game, it is basic geometry and physics):

假设球有一个方向/速度矢量dx,dy并且半径为r(ball.x,ball.y是球中心的球位置)就像这样(在台球比赛中使用类似的,它是基本几何和物理):

if (ball.x+ball.dx+r > wallV.x) ball.dx = -ball.dx // ball bounces off the 
vertical wall

if ( ball.y+ball.dy+r > wallH.y ) ball.dy = -ball.dy // ball bounces off horizontal wall

do similar for opposite walls if needed, since velocity vector changes, the new ball position after bouncing (or anyway) will be ball.x += ball.dx; ball.y += ball.dy;

如果需要,对相反的墙做类似的事情,因为速度矢量改变,弹跳后(或者无论如何)的新球位置将是ball.x + = ball.dx; ball.y + = ball.dy;

确定矩形上垂直或水平墙上的命中

Bonus if you add some friction factor (meaning the magnitudes of dx dy eventually fade away to zero, the ball eventually stops after following a path)

如果你添加一些摩擦系数(意味着dx dy的大小最终消失为零,奖励最终会在跟随路径后停止),

#2


To solve properly a collision, you can't just test on X => if collision solve and return THEN test on y => if collision solve on y.
You have to check which axe (x OR y) collides first, and there's also the case when the ball hits two walls at the same time.
So you can't just reason with space : you have to deal with time, and compute an ETA -Estimated Time Arrival- for all walls, based on the ball speed (assuming walls are still).

要正确解决碰撞,你不能只测试X =>如果碰撞求解并在y =>上返回THEN测试,如果在y上碰撞求解。你必须首先检查哪个轴(x或y)碰撞,并且还有球同时击中两个墙的情况。所以你不能只用空间来推理:你必须处理时间,并根据球的速度(假设墙壁仍然是)计算所有墙壁的ETA估计时间到达时间。

pseudo code :

伪代码:

minETA = a too big number;
colliderList = [];
for (each wall in walls) {
   thisWallETA = computeETA(ball, wall);
   if (thisWallETA > minETA) continue;
   if (thisWallETA < minETA) {
      minETA = thisWallETA;
      colliderList.length = 0;
      colliderList.push(wall);
      continue;
   } 
   if (thisWallETA == minETA) {
      colliderList.push(wall);
      continue;          
   }
}

Then when the colliderList has only one item => solve on corresponding axe. If it has two items => solve on both axes.
Then increase the current time by minETA, and try again until the currentTime + minETA you found is > to thisCycleTime + thisCycleDt.

然后当colliderList在相应的ax上只有一个item => solve时。如果它有两个项目=>两个轴上的求解。然后通过minETA增加当前时间,然后再次尝试,直到找到的currentTime + minETA>> thisCycleTime + thisCycleDt。

If you're interested, i might clarify some things up.

如果你有兴趣,我可能会澄清一些事情。

Good luck !

祝好运 !

#1


update after question update

问题更新后更新

Asuming the ball has a direction/velocity vector dx,dy and has a radius of r (ball.x, ball.y are the ball positions of the ball center) do sth like this (have used similar in a billiard game, it is basic geometry and physics):

假设球有一个方向/速度矢量dx,dy并且半径为r(ball.x,ball.y是球中心的球位置)就像这样(在台球比赛中使用类似的,它是基本几何和物理):

if (ball.x+ball.dx+r > wallV.x) ball.dx = -ball.dx // ball bounces off the 
vertical wall

if ( ball.y+ball.dy+r > wallH.y ) ball.dy = -ball.dy // ball bounces off horizontal wall

do similar for opposite walls if needed, since velocity vector changes, the new ball position after bouncing (or anyway) will be ball.x += ball.dx; ball.y += ball.dy;

如果需要,对相反的墙做类似的事情,因为速度矢量改变,弹跳后(或者无论如何)的新球位置将是ball.x + = ball.dx; ball.y + = ball.dy;

确定矩形上垂直或水平墙上的命中

Bonus if you add some friction factor (meaning the magnitudes of dx dy eventually fade away to zero, the ball eventually stops after following a path)

如果你添加一些摩擦系数(意味着dx dy的大小最终消失为零,奖励最终会在跟随路径后停止),

#2


To solve properly a collision, you can't just test on X => if collision solve and return THEN test on y => if collision solve on y.
You have to check which axe (x OR y) collides first, and there's also the case when the ball hits two walls at the same time.
So you can't just reason with space : you have to deal with time, and compute an ETA -Estimated Time Arrival- for all walls, based on the ball speed (assuming walls are still).

要正确解决碰撞,你不能只测试X =>如果碰撞求解并在y =>上返回THEN测试,如果在y上碰撞求解。你必须首先检查哪个轴(x或y)碰撞,并且还有球同时击中两个墙的情况。所以你不能只用空间来推理:你必须处理时间,并根据球的速度(假设墙壁仍然是)计算所有墙壁的ETA估计时间到达时间。

pseudo code :

伪代码:

minETA = a too big number;
colliderList = [];
for (each wall in walls) {
   thisWallETA = computeETA(ball, wall);
   if (thisWallETA > minETA) continue;
   if (thisWallETA < minETA) {
      minETA = thisWallETA;
      colliderList.length = 0;
      colliderList.push(wall);
      continue;
   } 
   if (thisWallETA == minETA) {
      colliderList.push(wall);
      continue;          
   }
}

Then when the colliderList has only one item => solve on corresponding axe. If it has two items => solve on both axes.
Then increase the current time by minETA, and try again until the currentTime + minETA you found is > to thisCycleTime + thisCycleDt.

然后当colliderList在相应的ax上只有一个item => solve时。如果它有两个项目=>两个轴上的求解。然后通过minETA增加当前时间,然后再次尝试,直到找到的currentTime + minETA>> thisCycleTime + thisCycleDt。

If you're interested, i might clarify some things up.

如果你有兴趣,我可能会澄清一些事情。

Good luck !

祝好运 !