2016-01-16 5 views
0
function distance(x1, y1, x2, y2) { 
      var x = x1 - x2; 
      var y = y1 - y2; 
      return(Math.sqrt((x*x) + (y*y))) 
    }; 

    function collisionCirc(circ1, circ2) { 
      var d = distance(circ1.x, circ1.y, circ2.x, circ2.y); 
      var r = circ1.radius + circ2.radius; 
      return(r > d); 
    }; 

    function collisionCircPoint(circ1, circ2) { 
      var cx = ((circ1.x * circ2.radius) + (circ2.x * circ1.radius))/(circ1.radius + circ2.radius); 
      var cy = ((circ1.y * circ2.radius) + (circ2.y * circ1.radius))/(circ1.radius + circ2.radius); 
      var p = [cx, cy]; 
      return p; 
    }; 

    function angleDegrees(x1, y1, x2, y2) { 
      return (Math.atan2(y2 - y1, x2 - x1) * 180/Math.PI) + 180; 
    }; 

    function updateCollisions() { 
      var a; 
      var p; 

      Player.hitArea = new PIXI.Circle(Player.sprite.x, Player.sprite.y, 20); 
      MapObjects.chest.hitArea = new PIXI.Circle(MapObjects.chest.x, MapObjects.chest.y, 20); 

      if (collisionCirc(Player.hitArea, MapObjects.chest.hitArea)) { 
       a = angleDegrees(Player.sprite.x, Player.sprite.y, MapObjects.chest.x, MapObjects.chest.y); 
       p = collisionCircPoint(Player.hitArea, MapObjects.chest.hitArea); 
         Player.sprite.x = p[0]; 
         Player.sprite.y = p[1]; 
      }; 

    }; 

У меня есть 2 спрайта на карте, и каждый из них имеет заданный круг. Я пытаюсь сделать гладкое круговое столкновение, которое игрок не может пройти. Я думал, что могу просто установить координаты Player.sprite в точку столкновения, но он просто искажает его в координатах MapObjects.chest, хотя точка столкновения правильная и находится в 20 пикселях от центра MapObject.chest. Что я делаю неправильно или какая дополнительная информация необходима для создания столкновения, так же как библиотеки физики JavaScript, где я могу обходить круг объекта?Использование круговой математики для сплошного столкновения

ответ

1

Точка удара между игроком и препятствием. Если вы переместите игрока к точке столкновения, вы фактически перемещаете игрока ближе. Например, если между игроком и препятствием ровно 40 px (r1 + r2), точка столкновения между ними, всего лишь 20 px от препятствия!

Когда у вас есть несколько объектов, получить правильное положение, когда столкновение уже произошло, сложно. Если поблизости есть только одно препятствие, вы можете просто перенести игрока прямо из препятствия. Однако таким образом игрок может оказаться в другом препятствии.

Еще одно решение - вернуться к началу и попробовать небольшие движения, пока не произойдет столкновение. Таким образом, вы, в конечном счете, получите это правильно, но это также может быть медленным.

Математически правильное решение состоит в том, чтобы вычислить максимальное расстояние до перемещения до столкновения. Это делается путем решения следующего векторного уравнения:

# p = player position before moving 
# o = obstacle position 
# u = player direction (unit vector) 
# d = distance to move 
distance(o, p + d * u) = o.radius + p.radius 

Это математика, вы можете решить эту проблему самостоятельно или с помощью такого инструмента, как Wolfram Alpha.

Решение этого уравнения даст вам нулевое, одно или два возможных значения расстояния. Отрицательные значения, которые вы можете отклонить, поскольку они означают, что игрок уже преодолел препятствие. Если вы получаете только одно значение, это означает, что игрок просто очистит препятствие, которое вы также можете уволить. Два значения означают, что столкновение происходит между этими расстояниями; меньшее значение - это то, где начинается столкновение, и большее значение - это то, где игрок уже прошел через препятствие. Кроме того, если одно значение положительное, а другое отрицательное, это означает, что игрок уже находится внутри препятствия, чего никогда не должно было случиться.

Вы должны выполнить эту проверку для всех находящихся поблизости препятствий, а затем переместить плеер в соответствии с наименьшим неотрицательным результатом (то есть нулем или положительным) или менее, если игрок не может двигаться так быстро.

Наконец, чтобы окружить круглый объект, вы можете немного переместить игрока в перпендикулярном направлении (слева или справа, в зависимости от того, на какой стороне препятствия будет проходить игрок) после столкновения, если это не вызывает никаких новых столкновений.

Существует много других возможных вариантов реализации.

0
 Player.hitArea = new PIXI.Circle(Player.sprite.x, Player.sprite.y, 20); 
     MapObjects.chest.hitArea = new PIXI.Circle(MapObjects.chest.x, MapObjects.chest.y, 20); 
     if (collisionCirc(Player.hitArea, MapObjects.chest.hitArea)) { 
      p = collisionCircPoint(Player.hitArea, MapObjects.chest.hitArea); 
      a = angleDegrees(Player.sprite.x, Player.sprite.y, MapObjects.chest.x, MapObjects.chest.y); 
       if (Player.sprite.x - MapObjects.chest.x > 0) { 
        Player.sprite.x += 1; 
       } else if (Player.sprite.x + MapObjects.chest.x > 0) { 
        Player.sprite.x -= 1; 
       }; 
       if (Player.sprite.y - MapObjects.chest.y > 0) { 
        Player.sprite.y += 1; 
       } else if (Player.sprite.y + MapObjects.chest.y > 0) { 
        Player.sprite.y -= 1; 
       }; 
      }; 
     }; 

Я добавил, что и на самом деле работает достаточно хорошо, минус скорость игрока быть немного слишком быстро, когда работает в hitArea в MapObjects.chest в под определенным углом. Поработайте над этим позже.